import java.util.Iterator;\r
import java.util.List;\r
import java.util.Map;\r
+import java.util.Stack;\r
import java.util.logging.Logger;\r
\r
import javax.imageio.spi.ServiceRegistry;\r
\r
+import jp.naist.se.stigmata.event.OperationEvent;\r
+import jp.naist.se.stigmata.event.OperationListener;\r
+import jp.naist.se.stigmata.event.OperationStage;\r
+import jp.naist.se.stigmata.event.OperationType;\r
+import jp.naist.se.stigmata.event.WarningMessages;\r
import jp.naist.se.stigmata.filter.ComparisonPairFilterManager;\r
import jp.naist.se.stigmata.filter.FilteredComparisonResultSet;\r
import jp.naist.se.stigmata.reader.ClassFileArchive;\r
\r
private BirthmarkContext defaultContext = BirthmarkContext.getDefaultContext();\r
private boolean configDone = false;\r
+ private Stack<WarningMessages> stack = new Stack<WarningMessages>();\r
+ private WarningMessages warnings;\r
+ private List<OperationListener> listeners = new ArrayList<OperationListener>();\r
\r
private Stigmata(){\r
}\r
return instance;\r
}\r
\r
+ public void addOperationListener(OperationListener listener){\r
+ listeners.add(listener);\r
+ }\r
+\r
+ public void removeOperationListener(OperationListener listener){\r
+ listeners.remove(listener);\r
+ }\r
+\r
+ public WarningMessages getWarnings(){\r
+ return warnings;\r
+ }\r
+\r
public void configuration(){\r
+ operationStart(OperationType.CONFIGURATION);\r
configuration(null);\r
+ operationDone(OperationType.CONFIGURATION);\r
}\r
\r
public void configuration(String filePath){\r
* create a new {@link BirthmarkContext <code>BirthmarkContext</code>}.\r
*/\r
public BirthmarkContext createContext(){\r
- if(!configDone){\r
- configuration();\r
- }\r
- return new BirthmarkContext();\r
+ operationStart(OperationType.CREATE_CONTEXT);\r
+ BirthmarkContext context = new BirthmarkContext();\r
+ operationDone(OperationType.EXTRACT_BIRTHMARKS);\r
+ return context;\r
}\r
\r
public BirthmarkSet[] extract(String[] birthmarks, String[] files) throws BirthmarkExtractionException{\r
- if(!configDone){\r
- configuration();\r
- }\r
- return extract(birthmarks, files, createContext());\r
+ operationStart(OperationType.EXTRACT_BIRTHMARKS);\r
+ BirthmarkSet[] set = extract(birthmarks, files, createContext());\r
+ operationDone(OperationType.EXTRACT_BIRTHMARKS);\r
+\r
+ return set;\r
}\r
\r
public BirthmarkSet[] extract(String[] birthmarks, String[] files,\r
BirthmarkContext context) throws BirthmarkExtractionException{\r
- if(!configDone){\r
- configuration();\r
- }\r
+ operationStart(OperationType.EXTRACT_BIRTHMARKS);\r
try{\r
return extractImpl(birthmarks, files, context);\r
} catch(IOException e){\r
- throw new BirthmarkExtractionException(e);\r
- }\r
- }\r
-\r
- private BirthmarkSet[] extractImpl(String[] birthmarks, String[] files, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
- ClassFileArchive[] archives = createArchives(files, context);\r
- BirthmarkExtractor[] extractors = createExtractors(birthmarks, context);\r
- ExtractionUnit unit = context.getExtractionUnit();\r
- \r
- if(unit == ExtractionUnit.CLASS){\r
- return extractFromClass(archives, extractors, context);\r
- }\r
- else if(unit == ExtractionUnit.PACKAGE){\r
- return extractFromPackage(archives, extractors, context);\r
- }\r
- else if(unit == ExtractionUnit.ARCHIVE){\r
- return extractFromProduct(archives, extractors, context);\r
- }\r
- return null;\r
- }\r
-\r
- private BirthmarkSet[] extractFromPackage(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
- Map<String, BirthmarkSet> list = new HashMap<String, BirthmarkSet>();\r
- \r
- for(ClassFileArchive archive: archives){\r
- for(ClassFileEntry entry: archive){\r
- String name = entry.getClassName();\r
- String packageName = parsePackageName(name);\r
- BirthmarkSet bs = list.get(packageName);\r
- if(bs == null){\r
- bs = new BirthmarkSet(packageName, archive.getLocation());\r
- list.put(packageName, bs);\r
- }\r
-\r
- byte[] data = inputStreamToByteArray(entry.getLocation().openStream());\r
- for(BirthmarkExtractor extractor: extractors){\r
- if(extractor.isAcceptable(ExtractionUnit.PACKAGE)){\r
- Birthmark b = bs.getBirthmark(extractor.getProvider().getType());\r
- if(b == null){\r
- b = extractor.createBirthmark();\r
- bs.addBirthmark(b);\r
- }\r
- extractor.extract(b, new ByteArrayInputStream(data), context);\r
- }\r
- }\r
- }\r
- }\r
-\r
- BirthmarkSet[] bslist = new BirthmarkSet[list.size()];\r
- int index = 0;\r
- for(BirthmarkSet bs: list.values()){\r
- bslist[index] = bs;\r
- index++;\r
- }\r
- return bslist;\r
- }\r
-\r
- private String parsePackageName(String name){\r
- String n = name.replace('/', '.');\r
- int index = n.lastIndexOf('.');\r
- if(index > 0){\r
- n = n.substring(0, index - 1);\r
- }\r
-\r
- return n;\r
- }\r
-\r
- private BirthmarkSet[] extractFromClass(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
- List<BirthmarkSet> list = new ArrayList<BirthmarkSet>();\r
-\r
- for(ClassFileArchive archive: archives){\r
- for(ClassFileEntry entry: archive){\r
- BirthmarkSet birthmarkset = new BirthmarkSet(entry.getClassName(), entry.getLocation());\r
- list.add(birthmarkset);\r
- byte[] data = inputStreamToByteArray(entry.getLocation().openStream());\r
- for(BirthmarkExtractor extractor: extractors){\r
- if(extractor.isAcceptable(ExtractionUnit.CLASS)){\r
- Birthmark b = extractor.extract(new ByteArrayInputStream(data), context);\r
- birthmarkset.addBirthmark(b);\r
- }\r
- }\r
- }\r
+ throw new BirthmarkExtractionException(e);\r
+ } finally{\r
+ operationDone(OperationType.EXTRACT_BIRTHMARKS);\r
}\r
- return list.toArray(new BirthmarkSet[list.size()]);\r
- }\r
-\r
- private BirthmarkSet[] extractFromProduct(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
- List<BirthmarkSet> list = new ArrayList<BirthmarkSet>();\r
-\r
- for(ClassFileArchive archive: archives){\r
- BirthmarkSet birthmarkset = new BirthmarkSet(archive.getName(), archive.getLocation());\r
- list.add(birthmarkset);\r
-\r
- for(ClassFileEntry entry: archive){\r
- byte[] data = inputStreamToByteArray(entry.getLocation().openStream());\r
- for(BirthmarkExtractor extractor: extractors){\r
- if(extractor.isAcceptable(ExtractionUnit.ARCHIVE)){\r
- Birthmark b = birthmarkset.getBirthmark(extractor.getProvider().getType());\r
- if(b == null){\r
- b = extractor.createBirthmark();\r
- birthmarkset.addBirthmark(b);\r
- }\r
- extractor.extract(b, new ByteArrayInputStream(data), context);\r
- }\r
- }\r
- }\r
- }\r
-\r
- return list.toArray(new BirthmarkSet[list.size()]);\r
- }\r
-\r
- private ClassFileArchive[] createArchives(String[] files, BirthmarkContext context) throws IOException, MalformedURLException{\r
- ClasspathContext bytecode = context.getClasspathContext();\r
- List<ClassFileArchive> archives = new ArrayList<ClassFileArchive>();\r
- for(int i = 0; i < files.length; i++){\r
- if(files[i].endsWith(".class")){\r
- archives.add(new DefaultClassFileArchive(files[i]));\r
- }\r
- else if(files[i].endsWith(".jar") || files[i].endsWith(".zip")){\r
- archives.add(new JarClassFileArchive(files[i]));\r
- bytecode.addClasspath(new File(files[i]).toURI().toURL());\r
- }\r
- else if(files[i].endsWith(".war")){\r
- archives.add(new WarClassFileArchive(files[i]));\r
- }\r
- }\r
- return archives.toArray(new ClassFileArchive[archives.size()]);\r
}\r
\r
public ComparisonResultSet compare(BirthmarkSet[] holders) throws IOException{\r
- if(!configDone){\r
- configuration();\r
- }\r
- return compare(holders, createContext());\r
+ operationStart(OperationType.COMPARE_BIRTHMARKS);\r
+ ComparisonResultSet crs = compare(holders, createContext());\r
+ operationDone(OperationType.COMPARE_BIRTHMARKS);\r
+\r
+ return crs;\r
}\r
\r
public ComparisonResultSet compare(BirthmarkSet[] holders, BirthmarkContext context) throws IOException{\r
- if(!configDone){\r
- configuration();\r
- }\r
+ operationStart(OperationType.COMPARE_BIRTHMARKS);\r
ComparisonResultSet result = new RoundRobinComparisonResultSet(holders, context, true);\r
+ operationDone(OperationType.COMPARE_BIRTHMARKS);\r
\r
return result;\r
}\r
\r
public ComparisonResultSet compare(BirthmarkSet[] holders1, BirthmarkSet[] holders2) throws IOException{\r
- if(!configDone){\r
- configuration();\r
- }\r
- return compare(holders1, holders2, createContext());\r
+ operationStart(OperationType.COMPARE_BIRTHMARKS);\r
+ ComparisonResultSet crs = compare(holders1, holders2, createContext());\r
+ operationDone(OperationType.COMPARE_BIRTHMARKS);\r
+ return crs;\r
}\r
\r
public ComparisonResultSet compare(BirthmarkSet[] holders1, BirthmarkSet[] holders2, BirthmarkContext context) throws IOException{\r
- if(!configDone){\r
- configuration();\r
- }\r
+ operationStart(OperationType.COMPARE_BIRTHMARKS);\r
ComparisonResultSet result = new RoundRobinComparisonResultSet(holders1, holders2, context);\r
+ operationDone(OperationType.COMPARE_BIRTHMARKS);\r
\r
return result;\r
}\r
\r
public ComparisonResultSet filter(ComparisonResultSet resultset, String[] filters){\r
- return filter(resultset, filters, createContext());\r
+ operationStart(OperationType.FILTER_BIRTHMARKS);\r
+ ComparisonResultSet crs = filter(resultset, filters, createContext());\r
+ operationDone(OperationType.FILTER_BIRTHMARKS);\r
+\r
+ return crs;\r
}\r
\r
public ComparisonResultSet filter(ComparisonResultSet resultset, String[] filters, BirthmarkContext context){\r
+ operationStart(OperationType.FILTER_BIRTHMARKS);\r
if(filters != null){\r
List<ComparisonPairFilterSet> filterList = new ArrayList<ComparisonPairFilterSet>();\r
ComparisonPairFilterManager manager = context.getFilterManager();\r
\r
return filter(resultset, filterList.toArray(new ComparisonPairFilterSet[filterList.size()]));\r
}\r
+ operationDone(OperationType.FILTER_BIRTHMARKS);\r
return resultset;\r
}\r
\r
public ComparisonResultSet filter(ComparisonResultSet resultset, ComparisonPairFilterSet[] filters){\r
- return filter(resultset, filters, createContext());\r
+ operationStart(OperationType.FILTER_BIRTHMARKS);\r
+ ComparisonResultSet crs = filter(resultset, filters, createContext());\r
+ operationDone(OperationType.FILTER_BIRTHMARKS);\r
+\r
+ return crs;\r
}\r
\r
public ComparisonResultSet filter(ComparisonResultSet resultset, ComparisonPairFilterSet[] filters, BirthmarkContext context){\r
+ operationStart(OperationType.FILTER_BIRTHMARKS);\r
FilteredComparisonResultSet filterResultSet = new FilteredComparisonResultSet(resultset);\r
- \r
+ operationDone(OperationType.FILTER_BIRTHMARKS);\r
+\r
return filterResultSet;\r
}\r
\r
- public double compare(BirthmarkSet h1, BirthmarkSet h2){\r
- if(!configDone){\r
- configuration();\r
- }\r
- return compare(h1, h2, createContext());\r
+ public double compareDetails(BirthmarkSet h1, BirthmarkSet h2){\r
+ operationStart(OperationType.COMPARE_DETAIL_BIRTHMARKS);\r
+ double similarity = compareDetails(h1, h2, createContext());\r
+ operationDone(OperationType.COMPARE_DETAIL_BIRTHMARKS);\r
+ return similarity;\r
}\r
\r
- public double compare(BirthmarkSet h1, BirthmarkSet h2, BirthmarkContext context){\r
- if(!configDone){\r
- configuration();\r
- }\r
+ public double compareDetails(BirthmarkSet h1, BirthmarkSet h2, BirthmarkContext context){\r
+ operationStart(OperationType.COMPARE_DETAIL_BIRTHMARKS);\r
\r
List<Double> list = new ArrayList<Double>();\r
int count = 0;\r
similarity += d.doubleValue();\r
}\r
}\r
+ operationDone(OperationType.COMPARE_DETAIL_BIRTHMARKS);\r
return similarity / count;\r
}\r
\r
}\r
configDone = true;\r
}\r
+\r
+ private void operationStart(OperationType type){\r
+ if(type != OperationType.CONFIGURATION && !configDone){\r
+ configuration();\r
+ }\r
+ if(warnings == null){\r
+ warnings = new WarningMessages(type);\r
+ fireEvent(new OperationEvent(OperationStage.OPERATION_START, type, warnings));\r
+ }\r
+ stack.push(warnings);\r
+ fireEvent(new OperationEvent(OperationStage.SUB_OPERATION_START, type, warnings));\r
+ }\r
+\r
+ private void operationDone(OperationType type){\r
+ fireEvent(new OperationEvent(OperationStage.SUB_OPERATION_DONE, type, warnings));\r
+ stack.pop();\r
+ if(stack.size() == 0){\r
+ fireEvent(new OperationEvent(OperationStage.OPERATION_DONE, type, warnings));\r
+ warnings = null;\r
+ }\r
+ }\r
+\r
+ private void fireEvent(OperationEvent e){\r
+ for(OperationListener listener: listeners){\r
+ switch(e.getStage()){\r
+ case OPERATION_START:\r
+ listener.operationStart(e);\r
+ break;\r
+ case SUB_OPERATION_START:\r
+ listener.subOperationStart(e);\r
+ break;\r
+ case SUB_OPERATION_DONE:\r
+ listener.subOperationDone(e);\r
+ break;\r
+ case OPERATION_DONE:\r
+ listener.operationDone(e);\r
+ break;\r
+ default:\r
+ throw new InternalError("unknown stage: " + e.getStage());\r
+ }\r
+ }\r
+ }\r
+\r
+ private BirthmarkSet[] extractImpl(String[] birthmarks, String[] files, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
+ ClassFileArchive[] archives = createArchives(files, context);\r
+ BirthmarkExtractor[] extractors = createExtractors(birthmarks, context);\r
+ ExtractionUnit unit = context.getExtractionUnit();\r
+\r
+ if(unit == ExtractionUnit.CLASS){\r
+ return extractFromClass(archives, extractors, context);\r
+ }\r
+ else if(unit == ExtractionUnit.PACKAGE){\r
+ return extractFromPackage(archives, extractors, context);\r
+ }\r
+ else if(unit == ExtractionUnit.ARCHIVE){\r
+ return extractFromProduct(archives, extractors, context);\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private BirthmarkSet[] extractFromPackage(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
+ Map<String, BirthmarkSet> list = new HashMap<String, BirthmarkSet>();\r
+\r
+ for(ClassFileArchive archive: archives){\r
+ for(ClassFileEntry entry: archive){\r
+ try{\r
+ String name = entry.getClassName();\r
+ String packageName = parsePackageName(name);\r
+ BirthmarkSet bs = list.get(packageName);\r
+ if(bs == null){\r
+ bs = new BirthmarkSet(packageName, archive.getLocation());\r
+ list.put(packageName, bs);\r
+ }\r
+\r
+ byte[] data = inputStreamToByteArray(entry.getLocation().openStream());\r
+ for(BirthmarkExtractor extractor: extractors){\r
+ if(extractor.isAcceptable(ExtractionUnit.PACKAGE)){\r
+ Birthmark b = bs.getBirthmark(extractor.getProvider().getType());\r
+ if(b == null){\r
+ b = extractor.createBirthmark();\r
+ bs.addBirthmark(b);\r
+ }\r
+ extractor.extract(b, new ByteArrayInputStream(data), context);\r
+ }\r
+ }\r
+ } catch(IOException e){\r
+ warnings.addMessage(e, archive.getName());\r
+ }\r
+ }\r
+ }\r
+\r
+ return list.values().toArray(new BirthmarkSet[list.size()]);\r
+ }\r
+\r
+ private String parsePackageName(String name){\r
+ String n = name.replace('/', '.');\r
+ int index = n.lastIndexOf('.');\r
+ if(index > 0){\r
+ n = n.substring(0, index - 1);\r
+ }\r
+\r
+ return n;\r
+ }\r
+\r
+ private BirthmarkSet[] extractFromClass(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
+ List<BirthmarkSet> list = new ArrayList<BirthmarkSet>();\r
+\r
+ for(ClassFileArchive archive: archives){\r
+ for(ClassFileEntry entry: archive){\r
+ try{\r
+ BirthmarkSet birthmarkset = new BirthmarkSet(entry.getClassName(), entry.getLocation());\r
+ list.add(birthmarkset);\r
+ byte[] data = inputStreamToByteArray(entry.getLocation().openStream());\r
+ for(BirthmarkExtractor extractor: extractors){\r
+ if(extractor.isAcceptable(ExtractionUnit.CLASS)){\r
+ Birthmark b = extractor.extract(new ByteArrayInputStream(data), context);\r
+ birthmarkset.addBirthmark(b);\r
+ }\r
+ }\r
+ } catch(IOException e){\r
+ warnings.addMessage(e, entry.getClassName());\r
+ }\r
+ }\r
+ }\r
+ return list.toArray(new BirthmarkSet[list.size()]);\r
+ }\r
+\r
+ private BirthmarkSet[] extractFromProduct(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkContext context) throws IOException, BirthmarkExtractionException{\r
+ List<BirthmarkSet> list = new ArrayList<BirthmarkSet>();\r
+\r
+ for(ClassFileArchive archive: archives){\r
+ BirthmarkSet birthmarkset = new BirthmarkSet(archive.getName(), archive.getLocation());\r
+ list.add(birthmarkset);\r
+\r
+ for(ClassFileEntry entry: archive){\r
+ try{\r
+ byte[] data = inputStreamToByteArray(entry.getLocation().openStream());\r
+ for(BirthmarkExtractor extractor: extractors){\r
+ if(extractor.isAcceptable(ExtractionUnit.ARCHIVE)){\r
+ Birthmark b = birthmarkset.getBirthmark(extractor.getProvider().getType());\r
+ if(b == null){\r
+ b = extractor.createBirthmark();\r
+ birthmarkset.addBirthmark(b);\r
+ }\r
+ extractor.extract(b, new ByteArrayInputStream(data), context);\r
+ }\r
+ }\r
+ } catch(IOException e){\r
+ warnings.addMessage(e, entry.getClassName());\r
+ }\r
+ }\r
+ }\r
+ for(Iterator<BirthmarkSet> i = list.iterator(); i.hasNext(); ){\r
+ BirthmarkSet set = i.next();\r
+ if(set.getBirthmarksCount() == 0){\r
+ i.remove();\r
+ }\r
+ }\r
+\r
+ return list.toArray(new BirthmarkSet[list.size()]);\r
+ }\r
+\r
+ private ClassFileArchive[] createArchives(String[] files, BirthmarkContext context) throws IOException, MalformedURLException{\r
+ ClasspathContext bytecode = context.getClasspathContext();\r
+ List<ClassFileArchive> archives = new ArrayList<ClassFileArchive>();\r
+ for(int i = 0; i < files.length; i++){\r
+ try{\r
+ if(files[i].endsWith(".class")){\r
+ archives.add(new DefaultClassFileArchive(files[i]));\r
+ }\r
+ else if(files[i].endsWith(".jar") || files[i].endsWith(".zip")){\r
+ archives.add(new JarClassFileArchive(files[i]));\r
+ bytecode.addClasspath(new File(files[i]).toURI().toURL());\r
+ }\r
+ else if(files[i].endsWith(".war")){\r
+ archives.add(new WarClassFileArchive(files[i]));\r
+ }\r
+ } catch(IOException e){\r
+ warnings.addMessage(e, files[i]);\r
+ }\r
+ }\r
+ return archives.toArray(new ClassFileArchive[archives.size()]);\r
+ }\r
}\r