OSDN Git Service

Remove Id tag
[stigmata/stigmata.git] / src / main / java / jp / sourceforge / stigmata / BirthmarkEnvironment.java
1 package jp.sourceforge.stigmata;
2
3 import java.beans.PropertyChangeEvent;
4 import java.beans.PropertyChangeListener;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.ServiceLoader;
13 import java.util.Set;
14
15 import javax.imageio.spi.ServiceRegistry;
16
17 import jp.sourceforge.stigmata.digger.ClasspathContext;
18 import jp.sourceforge.stigmata.filter.ComparisonPairFilterManager;
19 import jp.sourceforge.stigmata.resolvers.StigmataHomeManager;
20 import jp.sourceforge.stigmata.result.history.ExtractedBirthmarkServiceManager;
21 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
22 import jp.sourceforge.stigmata.utils.WellknownClassManager;
23
24 /**
25  * This class represents the context for extracting/comparing birthmarks.
26  * 
27  * @author  Haruaki TAMADA
28  */
29 public class BirthmarkEnvironment{
30     /**
31      * Default environment. All instance of this class is based on default environment.
32      */
33     private static BirthmarkEnvironment DEFAULT_ENVIRONMENT = new BirthmarkEnvironment(true);
34
35     /**
36      * home directory path.
37      */
38     private static StigmataHomeManager stigmataHome = new StigmataHomeManager();
39
40     /**
41      * parent of this environment.
42      */
43     private BirthmarkEnvironment parent;
44
45     /**
46      * context for classpath.
47      */
48     private ClasspathContext classpathContext;
49
50     /**
51      * wellknown class manager. This object judge a class is user made class or
52      * wellknown class.
53      */
54     private WellknownClassManager manager;
55
56     /**
57      * collection of services.
58      */
59     private Map<String, BirthmarkSpi> services = new HashMap<String, BirthmarkSpi>();
60
61     /**
62      * properties manager.
63      */
64     private Map<String, String> properties = new HashMap<String, String>();
65
66     /**
67      * listeners for updating properties.
68      */
69     private List<PropertyChangeListener> propertyListeners = new ArrayList<PropertyChangeListener>();
70
71     /**
72      * filter manager.
73      */
74     private ComparisonPairFilterManager filterManager;
75
76     /**
77      * history manager.
78      */
79     private ExtractedBirthmarkServiceManager historyManager;
80
81     /**
82      * 
83      */
84     private ClassLoader loader;
85
86     /**
87      * constructor for root environment
88      */
89     private BirthmarkEnvironment(boolean flag){
90         manager = new WellknownClassManager();
91         classpathContext = new ClasspathContext();
92         filterManager = new ComparisonPairFilterManager(this);
93         historyManager = new ExtractedBirthmarkServiceManager(this);
94     }
95
96     /**
97      * constructor for specifying parent environment.
98      */
99     public BirthmarkEnvironment(BirthmarkEnvironment parent){
100         this.parent = parent;
101         this.manager = new WellknownClassManager(parent.getWellknownClassManager());
102         this.classpathContext = new ClasspathContext(parent.getClasspathContext());
103         this.filterManager = new ComparisonPairFilterManager(this, parent.getFilterManager());
104         this.historyManager = new ExtractedBirthmarkServiceManager(this, parent.getHistoryManager());
105     }
106
107     /**
108      * returns the default birthmark environment.
109      */
110     public static final BirthmarkEnvironment getDefaultEnvironment(){
111         return DEFAULT_ENVIRONMENT;
112     }
113
114     public static synchronized final String getStigmataHome(){
115         return stigmataHome.getStigmataHome();
116     }
117
118     static void resetSettings(){
119         DEFAULT_ENVIRONMENT = new BirthmarkEnvironment(false);
120     }
121
122     public BirthmarkEnvironment getParent(){
123         return parent;
124     }
125
126     /**
127      * remove property mapped given key.
128      */
129     public void removeProperty(String key){
130         String old = properties.get(key);
131         properties.remove(key);
132         firePropertyEvent(new PropertyChangeEvent(this, key, old, null));
133     }
134
135     /**
136      * add given property.
137      */
138     public void addProperty(String key, String value){
139         boolean contains = properties.containsKey(key);
140         String old = getProperty(key);
141         properties.put(key, value);
142
143         // value is updated?
144         if(!((old != null && old.equals(value)) ||
145              (contains && old == null && value == null))){
146             firePropertyEvent(new PropertyChangeEvent(this, key, old, value));
147         }
148     }
149
150     /**
151      * returns the property mapped given key
152      */
153     public String getProperty(String key){
154         String value = properties.get(key);
155         if(value == null && parent != null){
156             value = parent.getProperty(key);
157         }
158         return value;
159     }
160
161     /**
162      * fire property change event to listeners.
163      * @param e Event object.
164      */
165     private void firePropertyEvent(PropertyChangeEvent e){
166         for(PropertyChangeListener listener: propertyListeners){
167             listener.propertyChange(e);
168         }
169     }
170
171     /**
172      * add listener for updating properties.
173      */
174     public void addPropertyListener(PropertyChangeListener listener){
175         propertyListeners.add(listener);
176     }
177
178     /**
179      * remove specified listener.
180      */
181     public void removePropertyListener(PropertyChangeListener listener){
182         propertyListeners.remove(listener);
183     }
184
185     public void clearProperties(){
186         properties.clear();
187     }
188
189     public Iterator<String> propertyKeys(){
190         Set<String> set = new HashSet<String>();
191         if(parent != null){
192             for(Iterator<String> i = parent.propertyKeys(); i.hasNext(); ){
193                 set.add(i.next());
194             }
195         }
196         set.addAll(properties.keySet());
197         return set.iterator();
198     }
199
200     /**
201      * returns the classpath context.
202      */
203     public ClasspathContext getClasspathContext(){
204         return classpathContext;
205     }
206
207     /**
208      * add given birthmark service to this environment.
209      */
210     public synchronized void addService(BirthmarkSpi service){
211         if(parent == null || parent.getService(service.getType()) == null){
212             services.put(service.getType(), service);
213         }
214     }
215
216     /**
217      * remove given birthmark service from this environment.
218      */
219     public void removeService(String type){
220         services.remove(type);
221     }
222
223     /**
224      * return birthmark service registered with given birthmark type.
225      */
226     public BirthmarkSpi getService(String type){
227         BirthmarkSpi service = services.get(type);
228         if(service == null && parent != null){
229             service = parent.getService(type);
230         }
231         return service;
232     }
233
234     /**
235      * return all birthmark services searching traverse to root environment.
236      */
237     public synchronized BirthmarkSpi[] getServices(){
238         List<BirthmarkSpi> list = getServiceList();
239         BirthmarkSpi[] services = list.toArray(new BirthmarkSpi[list.size()]);
240         Arrays.sort(services, new BirthmarkSpiComparator());
241
242         return services;
243     }
244
245     public <T> Iterator<T> lookupProviders(Class<T> providerClass){
246         Iterator<T> iterator;
247         if(loader != null){
248             ServiceLoader<T> services = ServiceLoader.load(providerClass, loader);
249             iterator = services.iterator();
250         }
251         else{
252             iterator = ServiceRegistry.lookupProviders(providerClass);
253         }
254         return iterator;
255     }
256
257     /**
258      * return birthmark services lookup from current class path.
259      */
260     public synchronized BirthmarkSpi[] findServices(){
261         List<BirthmarkSpi> list = getServiceList();
262
263         for(Iterator<BirthmarkSpi> i = lookupProviders(BirthmarkSpi.class); i.hasNext(); ){
264             BirthmarkSpi spi = i.next();
265             if(getService(spi.getType()) == null){
266                 list.add(spi);
267             }
268         }
269         BirthmarkSpi[] services = list.toArray(new BirthmarkSpi[list.size()]);
270         Arrays.sort(services, new BirthmarkSpiComparator());
271
272         return services;
273     }
274
275     /**
276      * return wellknown class manager.
277      */
278     public WellknownClassManager getWellknownClassManager(){
279         return manager;
280     }
281
282     public ComparisonPairFilterManager getFilterManager(){
283         return filterManager;
284     }
285
286     public ExtractedBirthmarkServiceManager getHistoryManager(){
287         return historyManager;
288     }
289
290     void setClassLoader(ClassLoader loader){
291         this.loader = loader;
292     }
293
294     /**
295      * find the all birthmark services searching to root environment.
296      */
297     private List<BirthmarkSpi> getServiceList(){
298         List<BirthmarkSpi> list = new ArrayList<BirthmarkSpi>();
299         if(parent != null){
300             for(BirthmarkSpi spi: parent.getServices()){
301                 list.add(spi);
302             }
303         }
304         for(String key : services.keySet()){
305             list.add(services.get(key));
306         }
307         return list;
308     }
309 }