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