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