1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.osgi.annotations;
20
21 import java.io.File;
22 import java.net.URI;
23 import java.net.URL;
24 import java.util.Comparator;
25 import java.util.Enumeration;
26 import java.util.Set;
27 import java.util.StringTokenizer;
28 import java.util.TreeSet;
29 import java.util.concurrent.ConcurrentHashMap;
30
31 import org.eclipse.jetty.annotations.ClassNameResolver;
32 import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
33 import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
34 import org.eclipse.jetty.util.ConcurrentHashSet;
35 import org.eclipse.jetty.util.resource.Resource;
36 import org.osgi.framework.Bundle;
37 import org.osgi.framework.Constants;
38
39
40
41
42 public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationParser
43 {
44 private Set<URI> _alreadyParsed = new ConcurrentHashSet<URI>();
45
46 private ConcurrentHashMap<URI,Bundle> _uriToBundle = new ConcurrentHashMap<URI, Bundle>();
47 private ConcurrentHashMap<Bundle,Resource> _bundleToResource = new ConcurrentHashMap<Bundle,Resource>();
48 private ConcurrentHashMap<Resource, Bundle> _resourceToBundle = new ConcurrentHashMap<Resource, Bundle>();
49 private ConcurrentHashMap<Bundle,URI> _bundleToUri = new ConcurrentHashMap<Bundle, URI>();
50
51
52
53
54
55
56
57
58 protected Resource indexBundle(Bundle bundle) throws Exception
59 {
60 File bundleFile = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle);
61 Resource resource = Resource.newResource(bundleFile.toURI());
62 URI uri = resource.getURI();
63 _uriToBundle.putIfAbsent(uri,bundle);
64 _bundleToUri.putIfAbsent(bundle,uri);
65 _bundleToResource.putIfAbsent(bundle,resource);
66 _resourceToBundle.putIfAbsent(resource,bundle);
67 return resource;
68 }
69 protected URI getURI(Bundle bundle)
70 {
71 return _bundleToUri.get(bundle);
72 }
73 protected Resource getResource(Bundle bundle)
74 {
75 return _bundleToResource.get(bundle);
76 }
77 protected Bundle getBundle (Resource resource)
78 {
79 return _resourceToBundle.get(resource);
80 }
81
82
83
84
85
86 @Override
87 public void parse (Set<? extends Handler> handlers, URI[] uris, ClassNameResolver resolver)
88 throws Exception
89 {
90 for (URI uri : uris)
91 {
92 Bundle associatedBundle = _uriToBundle.get(uri);
93 if (associatedBundle == null)
94 {
95 if (!_alreadyParsed.add(uri))
96 {
97 continue;
98 }
99
100
101 super.parse(handlers, new URI[] {uri},resolver);
102 }
103 else
104 {
105 parse(handlers, associatedBundle,resolver);
106 }
107 }
108 }
109
110 protected void parse(Set<? extends Handler> handlers, Bundle bundle, ClassNameResolver resolver)
111 throws Exception
112 {
113 URI uri = _bundleToUri.get(bundle);
114 if (!_alreadyParsed.add(uri))
115 {
116 return;
117 }
118
119 String bundleClasspath = (String)bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
120 if (bundleClasspath == null)
121 {
122 bundleClasspath = ".";
123 }
124
125 TreeSet<String> paths = new TreeSet<String>(
126 new Comparator<String>()
127 {
128 public int compare(String o1, String o2)
129 {
130 int paths1 = new StringTokenizer(o1,"/",false).countTokens();
131 int paths2 = new StringTokenizer(o2,"/",false).countTokens();
132 if (paths1 == paths2)
133 {
134 return o1.compareTo(o2);
135 }
136 return paths2 - paths1;
137 }
138 });
139 boolean hasDotPath = false;
140 StringTokenizer tokenizer = new StringTokenizer(bundleClasspath, ",;", false);
141 while (tokenizer.hasMoreTokens())
142 {
143 String token = tokenizer.nextToken().trim();
144 if (!token.startsWith("/"))
145 {
146 token = "/" + token;
147 }
148 if (token.equals("/."))
149 {
150 hasDotPath = true;
151 }
152 else if (!token.endsWith(".jar") && !token.endsWith("/"))
153 {
154 paths.add(token+"/");
155 }
156 else
157 {
158 paths.add(token);
159 }
160 }
161
162
163
164 if (bundle.getEntry("/.classpath") != null)
165 {
166 if (bundle.getEntry("/bin/") != null)
167 {
168 paths.add("/bin/");
169 }
170 else if (bundle.getEntry("/target/classes/") != null)
171 {
172 paths.add("/target/classes/");
173 }
174 }
175 Enumeration classes = bundle.findEntries("/","*.class",true);
176 if (classes == null)
177 {
178 return;
179 }
180 while (classes.hasMoreElements())
181 {
182 URL classUrl = (URL) classes.nextElement();
183 String path = classUrl.getPath();
184
185 String name = null;
186 for (String prefixPath : paths)
187 {
188 if (path.startsWith(prefixPath))
189 {
190 name = path.substring(prefixPath.length());
191 break;
192 }
193 }
194 if (name == null && hasDotPath)
195 {
196
197 name = path.substring(1);
198 }
199
200 String shortName = name.replace('/', '.').substring(0,name.length()-6);
201 if ((resolver == null)|| (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
202 scanClass(handlers, getResource(bundle), classUrl.openStream());
203 }
204 }
205 }