OSDN Git Service

separate environment and context
authortama3 <tama3@acee48c3-7b26-0410-bdac-b3d0e5314bbc>
Tue, 28 Aug 2007 06:43:49 +0000 (06:43 +0000)
committertama3 <tama3@acee48c3-7b26-0410-bdac-b3d0e5314bbc>
Tue, 28 Aug 2007 06:43:49 +0000 (06:43 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/stigmata/trunk@176 acee48c3-7b26-0410-bdac-b3d0e5314bbc

pom.xml
src/docs/tutorial.ppt [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/BirthmarkComparisonFailedException.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/BirthmarkContext.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/BirthmarkEngine.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ComparisonMethod.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ExtractionResult.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ExtractorNotFoundException.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/FilterNotFoundException.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/Stigmata2.java [new file with mode: 0755]
src/site/apt/experts.apt [new file with mode: 0755]

diff --git a/pom.xml b/pom.xml
index 5784620..3c6b83d 100755 (executable)
--- a/pom.xml
+++ b/pom.xml
 
   <repositories>
     <repository>
-      <id>maven.cafebabe.jp</id>
-      <name>The cafebabe Maven2 Repository</name>
-      <url>http://cafebabe.jp/repository/maven2</url>
-    </repository>
-    <repository>
       <id>stigmata.sourceforge.jp</id>
       <name>Stigmata Maven2 Repository in sourceforge.jp</name>
       <url>http://stigmata.sourceforge.jp/maven2</url>
diff --git a/src/docs/tutorial.ppt b/src/docs/tutorial.ppt
new file mode 100755 (executable)
index 0000000..17db602
Binary files /dev/null and b/src/docs/tutorial.ppt differ
diff --git a/src/main/java/jp/naist/se/stigmata/BirthmarkComparisonFailedException.java b/src/main/java/jp/naist/se/stigmata/BirthmarkComparisonFailedException.java
new file mode 100755 (executable)
index 0000000..9eadce4
--- /dev/null
@@ -0,0 +1,29 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+/**\r
+ * \r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public class BirthmarkComparisonFailedException extends BirthmarkException{\r
+    private static final long serialVersionUID = 3194872113405859851L;\r
+\r
+    public BirthmarkComparisonFailedException(){\r
+    }\r
+\r
+    public BirthmarkComparisonFailedException(String message){\r
+        super(message);\r
+    }\r
+\r
+    public BirthmarkComparisonFailedException(Throwable cause){\r
+        super(cause);\r
+    }\r
+\r
+    public BirthmarkComparisonFailedException(String message, Throwable cause){\r
+        super(message, cause);\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/BirthmarkContext.java b/src/main/java/jp/naist/se/stigmata/BirthmarkContext.java
new file mode 100755 (executable)
index 0000000..59ec985
--- /dev/null
@@ -0,0 +1,116 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import jp.naist.se.stigmata.event.OperationType;\r
+\r
+/**\r
+ * \r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+class BirthmarkContext{\r
+    public enum ExtractionTarget{\r
+        TARGET_X, TARGET_Y, TARGET_XY;\r
+    };\r
+    private List<String> birthmarkTypes = new ArrayList<String>();\r
+    private ComparisonMethod method = ComparisonMethod.ROUND_ROBIN;\r
+    private ExtractionTarget et = ExtractionTarget.TARGET_X;\r
+    private List<String> filterTypes = new ArrayList<String>();\r
+    private Map<String, String> nameMappings = new HashMap<String, String>();\r
+    private ExtractionUnit unit = ExtractionUnit.CLASS;\r
+    private OperationType operation;\r
+\r
+    public BirthmarkContext(OperationType type){\r
+        setOperation(type);\r
+    }\r
+\r
+    public OperationType getOperation(){\r
+        return operation;\r
+    }\r
+\r
+    public void setOperation(OperationType operation){\r
+        this.operation = operation;\r
+    }\r
+\r
+    public void addNameMapping(String name1, String name2){\r
+        nameMappings.put(name1, name2);\r
+    }\r
+\r
+    public void removeNameMapping(String name1){\r
+        nameMappings.remove(name1);\r
+    }\r
+\r
+    public Map<String, String> getNameMappings(){\r
+        return Collections.unmodifiableMap(nameMappings);\r
+    }\r
+\r
+    public void setExtractionTarget(ExtractionTarget target){\r
+        this.et = target;\r
+    }\r
+\r
+    public ExtractionTarget getExtractionTarget(){\r
+        return et;\r
+    }\r
+\r
+    public void addExtractionType(String type){\r
+        birthmarkTypes.add(type);\r
+    }\r
+\r
+    public void removeExtractionType(String type){\r
+        birthmarkTypes.remove(type);\r
+    }\r
+\r
+    public synchronized String[] getExtractionTypes(){\r
+        return birthmarkTypes.toArray(new String[getExtractionTypeCount()]);\r
+    }\r
+\r
+    public int getExtractionTypeCount(){\r
+        return birthmarkTypes.size();\r
+    }\r
+\r
+    public ComparisonMethod getComparisonMethod(){\r
+        return method;\r
+    }\r
+\r
+    public void setComparisonMethod(ComparisonMethod method){\r
+        this.method = method;\r
+    }\r
+\r
+    public ExtractionUnit getExtractionUnit(){\r
+        return unit;\r
+    }\r
+\r
+    public void setExtractionUnit(ExtractionUnit unit){\r
+        this.unit = unit;\r
+    }\r
+\r
+    public void addFilterType(String filterType){\r
+        filterTypes.add(filterType);\r
+    }\r
+\r
+    public void removeFilterType(String filterType){\r
+        filterTypes.remove(filterType);\r
+    }\r
+\r
+    public synchronized String[] getFilterTypes(){\r
+        return filterTypes.toArray(new String[getFilterTypesCount()]);\r
+    }\r
+\r
+    public Iterator<String> filterTypes(){\r
+        return filterTypes.iterator();\r
+    }\r
+\r
+    public int getFilterTypesCount(){\r
+        return filterTypes.size();\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/BirthmarkEngine.java b/src/main/java/jp/naist/se/stigmata/BirthmarkEngine.java
new file mode 100755 (executable)
index 0000000..0ba265d
--- /dev/null
@@ -0,0 +1,485 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.net.MalformedURLException;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+\r
+import jp.naist.se.stigmata.event.BirthmarkEngineEvent;\r
+import jp.naist.se.stigmata.event.BirthmarkEngineListener;\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
+import jp.naist.se.stigmata.reader.ClassFileEntry;\r
+import jp.naist.se.stigmata.reader.ClasspathContext;\r
+import jp.naist.se.stigmata.reader.DefaultClassFileArchive;\r
+import jp.naist.se.stigmata.reader.JarClassFileArchive;\r
+import jp.naist.se.stigmata.reader.WarClassFileArchive;\r
+import jp.naist.se.stigmata.spi.BirthmarkSpi;\r
+\r
+import org.apache.commons.beanutils.BeanUtils;\r
+\r
+/**\r
+ * \r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public class BirthmarkEngine{\r
+    private BirthmarkEnvironment environment;\r
+    private List<BirthmarkEngineListener> listeners = new ArrayList<BirthmarkEngineListener>();\r
+    private Stack<WarningMessages> stack = new Stack<WarningMessages>();\r
+    private WarningMessages warnings;\r
+    private OperationType latestOperationType;\r
+    private OperationType targetType;\r
+\r
+    public BirthmarkEngine(){\r
+        this(BirthmarkEnvironment.getDefaultEnvironment());\r
+    }\r
+\r
+    public BirthmarkEngine(BirthmarkEnvironment env){\r
+        this.environment = env;\r
+    }\r
+\r
+    public void addBirthmarkEngineListener(BirthmarkEngineListener listener){\r
+        listeners.add(listener);\r
+    }\r
+\r
+    public void removeBirthmarkEngineListener(BirthmarkEngineListener listener){\r
+        listeners.remove(listener);\r
+    }\r
+\r
+    public ComparisonResultSet filter(String[] target, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        ComparisonResultSet crs = compare(target, context);\r
+        crs = filter(crs, context);\r
+        \r
+        operationDone(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        return crs;\r
+    }\r
+\r
+    public ComparisonResultSet filter(String[] targetX, String[] targetY, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        ComparisonResultSet crs = compare(targetX, targetY, context);\r
+        crs = filter(crs, context);\r
+        \r
+        operationDone(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        return crs;\r
+    }\r
+\r
+    public ComparisonResultSet filter(ExtractionResult er, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        ComparisonResultSet crs = compare(er, context);\r
+        crs = filter(crs, context);\r
+        \r
+        operationDone(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        return crs;\r
+    }\r
+\r
+    public ComparisonResultSet filter(ComparisonResultSet crs, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.FILTER_BIRTHMARKS);\r
+\r
+        String[] filterTypes = context.getFilterTypes();\r
+\r
+        if(filterTypes != null){\r
+            List<ComparisonPairFilterSet> filterList = new ArrayList<ComparisonPairFilterSet>();\r
+            ComparisonPairFilterManager manager = environment.getFilterManager();\r
+            for(int i = 0; i < filterTypes.length; i++){\r
+                ComparisonPairFilterSet fset = manager.getFilterSet(filterTypes[i]);\r
+                if(fset != null){\r
+                    filterList.add(fset);\r
+                }\r
+                else{\r
+                    warnings.addMessage(new FilterNotFoundException("filter not found"), filterTypes[i]);\r
+                }\r
+            }\r
+            ComparisonPairFilterSet[] cpfs = filterList.toArray(new ComparisonPairFilterSet[filterList.size()]);\r
+\r
+            crs = new FilteredComparisonResultSet(crs, cpfs);\r
+        }\r
+        \r
+        operationDone(OperationType.FILTER_BIRTHMARKS);\r
+        return crs;\r
+    }\r
+\r
+    public ComparisonResultSet compare(String[] target, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.COMPARE_BIRTHMARKS);\r
+\r
+        ExtractionResult er = extract(target, context);\r
+        ComparisonResultSet crs = compare(er, context);\r
+\r
+        operationDone(OperationType.COMPARE_BIRTHMARKS);\r
+\r
+        return crs;\r
+    }\r
+\r
+    public ComparisonResultSet compare(String[] targetX, String[] targetY, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.COMPARE_BIRTHMARKS);\r
+\r
+        ExtractionResult er = extract(targetX, targetY, context);\r
+        ComparisonResultSet crs = compare(er, context);\r
+\r
+        operationDone(OperationType.COMPARE_BIRTHMARKS);\r
+\r
+        return crs;\r
+    }\r
+\r
+    public ComparisonResultSet compare(ExtractionResult er, BirthmarkContext context) throws BirthmarkExtractionFailedException, BirthmarkComparisonFailedException{\r
+        operationStart(OperationType.COMPARE_BIRTHMARKS);\r
+\r
+        ComparisonResultSet crs = null;\r
+        switch(context.getComparisonMethod()){\r
+        case ROUND_ROBIN:\r
+            crs = new RoundRobinComparisonResultSet(\r
+                er.getBirthmarkSetXY(), environment, true\r
+            );\r
+            break;\r
+        case ROUND_ROBIN_XY:\r
+            crs = new RoundRobinComparisonResultSet(\r
+                er.getBirthmarkSetX(), er.getBirthmarkSetY(), environment\r
+            );\r
+        case GUESSED_PAIR:\r
+            crs = new CertainPairComparisonResultSet(\r
+                er.getBirthmarkSetX(), er.getBirthmarkSetY(), environment\r
+            );\r
+            break;\r
+        case SPECIFIED_PAIR:\r
+            crs = new CertainPairComparisonResultSet(\r
+                er.getBirthmarkSetX(), er.getBirthmarkSetY(),\r
+                context.getNameMappings(), environment\r
+            );\r
+            break;\r
+        }\r
+\r
+        operationDone(OperationType.COMPARE_BIRTHMARKS);\r
+        return crs;\r
+    }\r
+\r
+    public ExtractionResult extract(String[] target, BirthmarkContext context) throws BirthmarkExtractionFailedException{\r
+        operationStart(OperationType.EXTRACT_BIRTHMARKS);\r
+        ExtractionResult er = extract(target, null, context);\r
+        operationDone(OperationType.EXTRACT_BIRTHMARKS);\r
+        return er;\r
+    }\r
+\r
+    public ExtractionResult extract(String[] targetX, String[] targetY, BirthmarkContext context) throws BirthmarkExtractionFailedException{\r
+        operationStart(OperationType.EXTRACT_BIRTHMARKS);\r
+        ExtractionResult er = new ExtractionResult();\r
+\r
+        try{\r
+            switch(context.getComparisonMethod()){\r
+            case ROUND_ROBIN:\r
+                String[] targetXY = mergeTarget(targetX, targetY);\r
+                BirthmarkSet[] s = extractImpl(targetXY, context);\r
+                er.setBirthmarkSetXY(s);\r
+                break;\r
+            case GUESSED_PAIR:\r
+            case SPECIFIED_PAIR:\r
+            case ROUND_ROBIN_XY:\r
+            default:\r
+                if(targetX == null || targetY == null){\r
+                    throw new BirthmarkExtractionFailedException("targetX or targetY is null");\r
+                }\r
+                BirthmarkSet[] extractResultX = extractImpl(targetX, context);\r
+                BirthmarkSet[] extractResultY = extractImpl(targetY, context);\r
+\r
+                er.setBirthmarkSetX(extractResultX);\r
+                er.setBirthmarkSetY(extractResultY);\r
+                break;\r
+            }\r
+            return er;\r
+        } catch(IOException e){\r
+            throw new BirthmarkExtractionFailedException(e);\r
+        } finally{\r
+            operationDone(OperationType.EXTRACT_BIRTHMARKS);\r
+        }\r
+    }\r
+\r
+    private String[] mergeTarget(String[] t1, String[] t2){\r
+        List<String> list = new ArrayList<String>();\r
+        addToList(list, t1);\r
+        addToList(list, t2);\r
+\r
+        return list.toArray(new String[list.size()]);\r
+    }\r
+\r
+    private void addToList(List<String> list, String[] target){\r
+        if(target != null){\r
+            for(String s: target){\r
+                list.add(s);\r
+            }\r
+        }\r
+    }\r
+\r
+    private BirthmarkSet[] extractImpl(String[] target, BirthmarkContext context) throws BirthmarkExtractionFailedException, IOException{\r
+        ClassFileArchive[] archives = createArchives(target, environment);\r
+        BirthmarkExtractor[] extractors = createExtractors(context.getExtractionTypes(), environment);\r
+        ExtractionUnit unit = context.getExtractionUnit();\r
+\r
+        BirthmarkSet[] extractResult = null;\r
+        if(unit == ExtractionUnit.CLASS){\r
+            extractResult = extractFromClass(archives, extractors, environment);\r
+        }\r
+        else if(unit == ExtractionUnit.PACKAGE){\r
+            extractResult = extractFromPackage(archives, extractors, environment);\r
+        }\r
+        else if(unit == ExtractionUnit.ARCHIVE){\r
+            extractResult = extractFromProduct(archives, extractors, environment);\r
+        }\r
+\r
+        return extractResult;\r
+    }\r
+\r
+    private BirthmarkExtractor[] createExtractors(String[] birthmarkTypes, BirthmarkEnvironment environment){\r
+        List<BirthmarkExtractor> list = new ArrayList<BirthmarkExtractor>();\r
+        for(String type: birthmarkTypes){\r
+            BirthmarkExtractor extractor = createExtractor(type, environment);\r
+            list.add(extractor);\r
+        }\r
+        return list.toArray(new BirthmarkExtractor[list.size()]);\r
+    }\r
+\r
+    private BirthmarkExtractor createExtractor(String birthmarkType, BirthmarkEnvironment environment){\r
+        BirthmarkSpi spi = environment.getService(birthmarkType);\r
+        BirthmarkExtractor extractor = null;\r
+        if(spi != null){\r
+            extractor = spi.getExtractor();\r
+            try{\r
+                if(extractor != null){\r
+                    Map props = BeanUtils.describe(extractor);\r
+                    props.remove("class");\r
+                    props.remove("provider");\r
+                    for(Object keyObject: props.keySet()){\r
+                        String key = "extractor." + spi.getType() + "." + String.valueOf(keyObject);\r
+                        if(environment.getProperty(key) != null){\r
+                            BeanUtils.setProperty(\r
+                                extractor, (String)keyObject, environment.getProperty(key)\r
+                            );\r
+                        }\r
+                    }\r
+                }\r
+            } catch(InvocationTargetException e){\r
+                throw new InternalError(e.getMessage());\r
+            } catch(NoSuchMethodException e){\r
+                throw new InternalError(e.getMessage());\r
+            } catch(IllegalAccessException e){\r
+                throw new InternalError(e.getMessage());\r
+            }\r
+        }\r
+        if(extractor == null){\r
+            warnings.addMessage(new ExtractorNotFoundException("extractor not found"), birthmarkType);\r
+        }\r
+\r
+        return null;\r
+    }\r
+\r
+    private byte[] inputStreamToByteArray(InputStream in) throws IOException{\r
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();\r
+        int read;\r
+        byte[] dataBuffer = new byte[512];\r
+        while((read = in.read(dataBuffer, 0, dataBuffer.length)) != -1){\r
+            bout.write(dataBuffer, 0, read);\r
+        }\r
+        byte[] data = bout.toByteArray();\r
+\r
+        bout.close();\r
+        return data;\r
+    }\r
+\r
+    private BirthmarkSet[] extractFromPackage(ClassFileArchive[] archives, BirthmarkExtractor[] extractors, BirthmarkEnvironment context) throws IOException, BirthmarkExtractionFailedException{\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, BirthmarkEnvironment context) throws IOException, BirthmarkExtractionFailedException{\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, BirthmarkEnvironment context) throws IOException, BirthmarkExtractionFailedException{\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, BirthmarkEnvironment environment) throws IOException, MalformedURLException{\r
+        ClasspathContext bytecode = environment.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
+    private void operationStart(OperationType type){\r
+        if(warnings == null){\r
+            warnings = new WarningMessages(type);\r
+            fireEvent(new BirthmarkEngineEvent(OperationStage.OPERATION_START, type, warnings));\r
+            latestOperationType = type;\r
+            targetType = type;\r
+        }\r
+        stack.push(warnings);\r
+        /*\r
+         * call subOperationStart method only once when some operation is occured.\r
+         * Ex. extraction, comparison, filtering\r
+         */\r
+        if(latestOperationType != type){\r
+            fireEvent(new BirthmarkEngineEvent(OperationStage.SUB_OPERATION_START, type, warnings));\r
+            latestOperationType = type;\r
+        }\r
+    }\r
+\r
+    private void operationDone(OperationType type){\r
+        if(latestOperationType != type && targetType != type){\r
+            fireEvent(new BirthmarkEngineEvent(OperationStage.SUB_OPERATION_DONE, type, warnings));\r
+            latestOperationType = type;\r
+        }\r
+        stack.pop();\r
+        if(stack.size() == 0){\r
+            fireEvent(new BirthmarkEngineEvent(OperationStage.OPERATION_DONE, type, warnings));\r
+            warnings = null;\r
+            latestOperationType = null;\r
+        }\r
+    }\r
+\r
+    private void fireEvent(BirthmarkEngineEvent e){\r
+        for(BirthmarkEngineListener 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
diff --git a/src/main/java/jp/naist/se/stigmata/ComparisonMethod.java b/src/main/java/jp/naist/se/stigmata/ComparisonMethod.java
new file mode 100755 (executable)
index 0000000..bc581c9
--- /dev/null
@@ -0,0 +1,37 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+/**\r
+ * This enum represents birthmark comparison method. let <it>X</it> be a set of\r
+ * target <it>{ x1, x2, ..., xn, }</it> and <it>Y</it> be a set of target\r
+ * <it>{ y1, y2, ..., ym, }</it>.\r
+ * \r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public enum ComparisonMethod{\r
+    /**\r
+     * This constants represents comparing all combination between <it>X</it>\r
+     * and <it>Y</it>. <it>x1 - y1, x1 - y2, x1 - y3, ..., xn - ym-1, xn, ym</it>.\r
+     */\r
+    ROUND_ROBIN_XY,\r
+    /**\r
+     * This constants represents comparing all combination between <it>X</it>.\r
+     * <it>x1 - x1, x1 - x2, x1 - x3, ..., xn - xn-1 xn, xn</it>.\r
+     */\r
+    ROUND_ROBIN,\r
+    /**\r
+     * This constants represents comparing some pairs. The pair is guessed by\r
+     * its name. If x1 and y3 have same name, then the pair of x1 and y3 is\r
+     * compared.\r
+     */\r
+    GUESSED_PAIR,\r
+    /**\r
+     * This constants represents comparing some pairs. The pair is specified by\r
+     * user.\r
+     */\r
+    SPECIFIED_PAIR,\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/ExtractionResult.java b/src/main/java/jp/naist/se/stigmata/ExtractionResult.java
new file mode 100755 (executable)
index 0000000..1e0d2fb
--- /dev/null
@@ -0,0 +1,62 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+import jp.naist.se.stigmata.BirthmarkContext.ExtractionTarget;\r
+\r
+/**\r
+ * \r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public class ExtractionResult{\r
+    private BirthmarkSet[] targetX;\r
+    private BirthmarkSet[] targetY;\r
+    private ExtractionTarget target = ExtractionTarget.TARGET_X;\r
+\r
+    public BirthmarkSet[] getBirthmarkSetXY(){\r
+        if(target != ExtractionTarget.TARGET_XY){\r
+            throw new IllegalStateException("extraction mode is not XY");\r
+        }\r
+        return targetX;\r
+    }\r
+\r
+    public void setBirthmarkSetXY(BirthmarkSet[] targetXY){\r
+        target = ExtractionTarget.TARGET_XY;\r
+        this.targetX = targetXY;\r
+    }\r
+\r
+    public BirthmarkSet[] getBirthmarkSetX(){\r
+        if(target == ExtractionTarget.TARGET_XY){\r
+            throw new IllegalStateException("extraction mode is XY");\r
+        }\r
+        return targetX;\r
+    }\r
+\r
+    public void setBirthmarkSetX(BirthmarkSet[] targetX){\r
+        target = ExtractionTarget.TARGET_X;\r
+        this.targetX = targetX;\r
+    }\r
+\r
+    public BirthmarkSet[] getBirthmarkSetY(){\r
+        if(target == ExtractionTarget.TARGET_XY){\r
+            throw new IllegalStateException("extraction mode is XY");\r
+        }\r
+        return targetY;\r
+    }\r
+\r
+    public void setBirthmarkSetY(BirthmarkSet[] targetY){\r
+        target = ExtractionTarget.TARGET_Y;\r
+        this.targetY = targetY;\r
+    }\r
+\r
+    public ExtractionTarget getExtractionTarget(){\r
+        return target;\r
+    }\r
+\r
+    public void setExtractionTarget(ExtractionTarget target){\r
+        this.target = target;\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/ExtractorNotFoundException.java b/src/main/java/jp/naist/se/stigmata/ExtractorNotFoundException.java
new file mode 100755 (executable)
index 0000000..6f3df30
--- /dev/null
@@ -0,0 +1,29 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+/**\r
+ *\r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public class ExtractorNotFoundException extends BirthmarkException{\r
+    private static final long serialVersionUID = 2050231007494812969L;\r
+\r
+    public ExtractorNotFoundException(){\r
+    }\r
+\r
+    public ExtractorNotFoundException(String message, Throwable cause){\r
+        super(message, cause);\r
+    }\r
+\r
+    public ExtractorNotFoundException(String message){\r
+        super(message);\r
+    }\r
+\r
+    public ExtractorNotFoundException(Throwable cause){\r
+        super(cause);\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/FilterNotFoundException.java b/src/main/java/jp/naist/se/stigmata/FilterNotFoundException.java
new file mode 100755 (executable)
index 0000000..c3f5cfa
--- /dev/null
@@ -0,0 +1,29 @@
+package jp.naist.se.stigmata;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+/**\r
+ * \r
+ * @author Haruaki Tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public class FilterNotFoundException extends BirthmarkException{\r
+    private static final long serialVersionUID = -3981002035876805953L;\r
+\r
+    public FilterNotFoundException(){\r
+    }\r
+\r
+    public FilterNotFoundException(String message, Throwable cause){\r
+        super(message, cause);\r
+    }\r
+\r
+    public FilterNotFoundException(String message){\r
+        super(message);\r
+    }\r
+\r
+    public FilterNotFoundException(Throwable cause){\r
+        super(cause);\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/Stigmata2.java b/src/main/java/jp/naist/se/stigmata/Stigmata2.java
new file mode 100755 (executable)
index 0000000..f354c30
--- /dev/null
@@ -0,0 +1,98 @@
+package jp.naist.se.stigmata;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.util.Iterator;\r
+\r
+import javax.imageio.spi.ServiceRegistry;\r
+\r
+import jp.naist.se.stigmata.event.BirthmarkEngineListener;\r
+import jp.naist.se.stigmata.spi.BirthmarkSpi;\r
+import jp.naist.se.stigmata.utils.ConfigFileImporter;\r
+\r
+public class Stigmata2{\r
+    private static Stigmata2 stigmata = new Stigmata2();\r
+    private BirthmarkEnvironment defaultEnvironment;\r
+    private BirthmarkEngine engine;\r
+\r
+    private Stigmata2(){\r
+        configuration();\r
+        engine = new BirthmarkEngine(defaultEnvironment);\r
+    }\r
+\r
+    public static Stigmata2 getInstance(){\r
+        return stigmata;\r
+    }\r
+\r
+    public void addBirthmarkEngineListener(BirthmarkEngineListener listener){\r
+        engine.addBirthmarkEngineListener(listener);\r
+    }\r
+\r
+    public void removeBirthmarkEngineListener(BirthmarkEngineListener listener){\r
+        engine.removeBirthmarkEngineListener(listener);\r
+    }\r
+\r
+    public ComparisonResultSet compare(String[] files, BirthmarkContext context) throws BirthmarkException{\r
+        return engine.compare(files, context);\r
+    }\r
+\r
+    public ComparisonResultSet compare(String[] fileX, String[] fileY, BirthmarkContext context) throws BirthmarkException{\r
+        return engine.compare(fileX, fileY, context);\r
+    }\r
+\r
+    public void configuration(){\r
+        configuration(null);\r
+    }\r
+\r
+    public void configuration(String filePath){\r
+        InputStream target = null;\r
+        if(filePath != null){\r
+            try{\r
+                target = new FileInputStream(filePath);\r
+            } catch(FileNotFoundException e){\r
+                filePath = null;\r
+            }\r
+        }\r
+\r
+        if(filePath == null){\r
+            File file = new File("stigmata.xml");\r
+            if(!file.exists()){\r
+                file = new File(System.getProperty("user.home"), ".stigmata.xml");\r
+                if(!file.exists()){\r
+                    file = null;\r
+                }\r
+            }\r
+            if(file != null){\r
+                try {\r
+                    target = new FileInputStream(file);\r
+                } catch (FileNotFoundException ex) {\r
+                    // never throwed this exception;\r
+                    throw new InternalError(ex.getMessage());\r
+                }\r
+            }\r
+        }\r
+        if(target == null){\r
+            target = getClass().getResourceAsStream("/resources/stigmata.xml");\r
+        }\r
+        initConfiguration(target);\r
+    }\r
+\r
+    private void initConfiguration(InputStream in){\r
+        if(defaultEnvironment == null){\r
+            defaultEnvironment = BirthmarkEnvironment.getDefaultEnvironment();\r
+        }\r
+        try {\r
+            ConfigFileImporter parser = new ConfigFileImporter(defaultEnvironment);\r
+            parser.parse(in);\r
+        } catch(IOException e){\r
+            throw new ApplicationInitializationError(e);\r
+        }\r
+        for(Iterator<BirthmarkSpi> i = ServiceRegistry.lookupProviders(BirthmarkSpi.class); i.hasNext(); ){\r
+            BirthmarkSpi service = i.next();\r
+            defaultEnvironment.addService(service);\r
+        }\r
+    }\r
+}\r
diff --git a/src/site/apt/experts.apt b/src/site/apt/experts.apt
new file mode 100755 (executable)
index 0000000..e7ea76e
--- /dev/null
@@ -0,0 +1,53 @@
+ ----\r
+ Expert mode\r
+ ----\r
+ Haruaki Tamada\r
+ ----\r
+ 2007-06-29\r
+ ----\r
+\r
+Comparison Methods\r
+\r
+ Let <p> and <q> be a target class files, and <f> be a birthmark\r
+extraction method.  Then, <f(p)> and <f(q)> be a extracted birthmarks\r
+which elements are <(e^p_1, e^p_2, ..., e^p_n)> and <(e^q_1, e^q_2,\r
+..., e^q_m)>.\r
+\r
+*Plain\r
+\r
+ Let <L> be a number of matched elements of two birthmarks and same\r
+index.  Then, the similarity of this method is calculated by\r
+\r
+ <L> / <(n + m)>\r
+\r
+*Logical AND\r
+\r
+ |<f(p) cap f(q)>| / |<f(p)>| |<f(q)>|\r
+\r
+*DP matching\r
+\r
+ DP matching method\r
+\r
+*Edit distance\r
+\r
+ Edit distance.\r
+\r
+*Cosine similarity\r
+\r
+ Using this comparison method, birthmarks must have name and its\r
+frequency.  Threfore, elements of <f(p)> be a set of <(\{name_1,\r
+freq_1\}, \{name_2, freq_2\}, ..., \{name_n, freq_n\})>.\r
+\r
+ Next, if <f(p)> have name <FOO> and <f(q)> do not have <FOO>, we add\r
+element <\{FOO, 0\}> to f(q).  Both birthmarks makes to appearing all\r
+names.\r
+\r
+ Then, the similarity of <f(p)> and <f(q)>is denoted by\r
+\r
+ <norm1 = sqrt(freq^p_1 * freq^p_1 + freq^p_2 * freq^p_2 + ... + freq^p_n * freq^p_n)>\r
+\r
+ <norm2 = sqrt(freq^q_1 * freq^q_1 + freq^q_2 * freq^q_2 + ... + freq^q_n * freq^q_n)>\r
+\r
+ <product = freq^p_1 * freq^q_1 + freq^p_2 * freq^q_2 + ... + freq^p_n * freq^q_n>\r
+\r
+ <similarity = product / (norm1 * norm2)>
\ No newline at end of file