OSDN Git Service

enables to restore to default settings
[stigmata/stigmata-core.git] / src / main / java / jp / naist / se / stigmata / reader / ClasspathContext.java
1 package jp.naist.se.stigmata.reader;\r
2 \r
3 /*\r
4  * $Id$\r
5  */\r
6 \r
7 import java.net.URL;\r
8 import java.util.ArrayList;\r
9 import java.util.Iterator;\r
10 import java.util.List;\r
11 \r
12 import jp.naist.se.stigmata.utils.WarClassLoader;\r
13 \r
14 /**\r
15  * @author Haruaki TAMADA\r
16  * @version $Revision$ $Date$\r
17  */\r
18 public class ClasspathContext implements Iterable<URL>{\r
19     private static ClasspathContext DEFAULT_CONTEXT = new ClasspathContext(false);\r
20 \r
21     private ClasspathContext parent;\r
22     private List<URL> classpath = new ArrayList<URL>();\r
23     private ClassLoader loader = null;\r
24 \r
25     /**\r
26      * private constructor for root context.\r
27      */\r
28     private ClasspathContext(boolean flag){\r
29     }\r
30 \r
31     public ClasspathContext(){\r
32         this(DEFAULT_CONTEXT);\r
33     }\r
34 \r
35     /**\r
36      * constructor with parent classpath context.\r
37      */\r
38     public ClasspathContext(ClasspathContext parent){\r
39         this.parent = parent;\r
40     }\r
41 \r
42     /**\r
43      * returns parent classpath context.\r
44      */\r
45     public ClasspathContext getParent(){\r
46         return parent;\r
47     }\r
48 \r
49     /**\r
50      * returns default classpath context.\r
51      */\r
52     public static final ClasspathContext getDefaultContext(){\r
53         return DEFAULT_CONTEXT;\r
54     }\r
55 \r
56     /**\r
57      * adds given url to this context.  If this context already has given url or\r
58      * parent context has given url, this method do nothing.\r
59      */\r
60     public synchronized void addClasspath(URL url){\r
61         if(!contains(url)){\r
62             classpath.add(url);\r
63             loader = null;\r
64         }\r
65     }\r
66 \r
67     /**\r
68      * returns that this context or parent context have given url.\r
69      */\r
70     public synchronized boolean contains(URL url){\r
71         return (parent != null && parent.contains(url)) || classpath.contains(url); \r
72     }\r
73 \r
74     /**\r
75      * returns a size of classpath list, which this context and parent context have.\r
76      */\r
77     public int getClasspathSize(){\r
78         int count = classpath.size();\r
79         if(parent != null){\r
80             count += parent.getClasspathSize();\r
81         }\r
82         return count;\r
83     }\r
84 \r
85     /**\r
86      * returns an array of all of classpathes include parent context.\r
87      */\r
88     public synchronized URL[] getClasspathList(){\r
89         List<URL> list = new ArrayList<URL>();\r
90         for(URL url: this){\r
91             list.add(url);\r
92         }\r
93         return list.toArray(new URL[list.size()]);\r
94     }\r
95 \r
96     /**\r
97      * clears all of classpathes of this context. not clear parent context.\r
98      * If you want to clear this context and parent context, use {@link #clearAll <code>clearAll</code>} method.\r
99      * @see clearAll\r
100      */\r
101     public void clear(){\r
102         classpath.clear();\r
103     }\r
104 \r
105     /**\r
106      * clears all of classpathes of this context and parent context.\r
107      */\r
108     public void clearAll(){\r
109         clear();\r
110         if(parent != null){\r
111             parent.clearAll();\r
112         }\r
113     }\r
114 \r
115     public Iterator<URL> iterator(){\r
116         if(parent == null){\r
117             return classpath.iterator();\r
118         }\r
119         else{\r
120             final Iterator<URL> parentIterator = parent.iterator();\r
121             final Iterator<URL> thisIterator = classpath.iterator();\r
122             return new Iterator<URL>(){\r
123                 public boolean hasNext(){\r
124                     boolean next = parentIterator.hasNext();\r
125                     if(!next){\r
126                         next = thisIterator.hasNext();\r
127                     }\r
128                     return next;\r
129                 }\r
130                 public URL next(){\r
131                     URL nextObject = null;\r
132                     if(parentIterator.hasNext()){\r
133                         nextObject = parentIterator.next();\r
134                     }\r
135                     else{\r
136                         nextObject = thisIterator.next();\r
137                     }\r
138                     return nextObject;\r
139                 }\r
140                 public void remove(){\r
141                 }\r
142             };\r
143         }\r
144     }\r
145 \r
146     public synchronized ClassLoader createClassLoader(){\r
147         if(loader == null){\r
148             List<URL> list = new ArrayList<URL>();\r
149             for(URL url: this){\r
150                 list.add(url);\r
151             }\r
152 \r
153             loader = new WarClassLoader(list.toArray(new URL[list.size()]), getClass().getClassLoader());\r
154         }\r
155         return loader;\r
156     }\r
157 \r
158     public ClassFileEntry find(String className) throws ClassNotFoundException{\r
159         ClassLoader loader = createClassLoader();\r
160 \r
161         URL resource = loader.getResource(className.replace('.', '/') + ".class");\r
162         if(resource != null){\r
163             return new ClassFileEntry(className, resource);\r
164         }\r
165         return null;\r
166     }\r
167 \r
168     public Class<?> findClass(String className) throws ClassNotFoundException{\r
169         try{\r
170             ClassLoader loader = createClassLoader();\r
171 \r
172             return loader.loadClass(className);\r
173         } catch(NoClassDefFoundError e){\r
174             throw new ClassNotFoundException(e.getMessage(), e);\r
175         }\r
176     }\r
177 }\r