001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.lang;
019:
020: import java.net.URL;
021: import java.net.JarURLConnection;
022: import java.security.AccessController;
023: import java.security.PrivilegedAction;
024: import java.util.Map;
025: import java.util.Hashtable;
026: import java.util.Collection;
027: import java.util.NoSuchElementException;
028: import java.util.StringTokenizer;
029: import java.util.jar.Attributes;
030: import java.util.jar.Manifest;
031: import java.lang.ref.SoftReference;
032: import java.lang.reflect.AnnotatedElement;
033: import java.lang.annotation.Annotation;
034:
035: import org.apache.harmony.vm.VMGenericsAndAnnotations;
036: import org.apache.harmony.vm.VMStack;
037:
038: /**
039: * @com.intel.drl.spec_ref
040: */
041: public class Package implements AnnotatedElement {
042:
043: /**
044: *
045: * @com.intel.drl.spec_ref
046: *
047: **/
048: public Annotation[] getDeclaredAnnotations() {
049: Class pc = null;
050: try {
051: //default package cannot be annotated
052: pc = Class.forName(getName() + ".package-info", false,
053: loader);
054: } catch (ClassNotFoundException _) {
055: return new Annotation[0];
056: }
057: return VMGenericsAndAnnotations.getDeclaredAnnotations(pc); // get all annotations directly present on this element
058: }
059:
060: /**
061: *
062: * @com.intel.drl.spec_ref
063: *
064: **/
065: public Annotation[] getAnnotations() {
066: return getDeclaredAnnotations();
067: }
068:
069: /**
070: *
071: * @com.intel.drl.spec_ref
072: *
073: **/
074: @SuppressWarnings("unchecked")
075: public <A extends Annotation> A getAnnotation(
076: Class<A> annotationClass) {
077: if (annotationClass == null) {
078: throw new NullPointerException();
079: }
080: Annotation aa[] = getAnnotations();
081: for (int i = 0; i < aa.length; i++) {
082: if (aa[i].annotationType().equals(annotationClass)) {
083: return (A) aa[i];
084: }
085: }
086: return null;
087: }
088:
089: /**
090: *
091: * @com.intel.drl.spec_ref
092: *
093: **/
094: public boolean isAnnotationPresent(
095: Class<? extends Annotation> annotationClass) {
096: return getAnnotation(annotationClass) != null;
097: }
098:
099: /**
100: * The defining loader.
101: */
102: private final ClassLoader loader;
103:
104: /**
105: * A map of {url<String>, attrs<Manifest>} pairs for caching
106: * attributes of bootsrap jars.
107: */
108: private static SoftReference<Map<String, Manifest>> jarCache;
109:
110: /**
111: * An url of a source jar, for deffered attributes initialization.
112: * After the initialization, if any, is reset to null.
113: */
114: private String jar;
115:
116: private String implTitle;
117:
118: private String implVendor;
119:
120: private String implVersion;
121:
122: private final String name;
123:
124: private URL sealBase;
125:
126: private String specTitle;
127:
128: private String specVendor;
129:
130: private String specVersion;
131:
132: /**
133: * Name must not be null.
134: */
135: Package(ClassLoader ld, String packageName, String sTitle,
136: String sVersion, String sVendor, String iTitle,
137: String iVersion, String iVendor, URL base) {
138: loader = ld;
139: name = packageName;
140: specTitle = sTitle;
141: specVersion = sVersion;
142: specVendor = sVendor;
143: implTitle = iTitle;
144: implVersion = iVersion;
145: implVendor = iVendor;
146: sealBase = base;
147: }
148:
149: /**
150: * Lazy initialization constructor; this Package instance will try to
151: * resolve optional attributes only if such value is requested.
152: * Name must not be null.
153: */
154: Package(ClassLoader ld, String packageName, String jar) {
155: loader = ld;
156: name = packageName;
157: this .jar = jar;
158: }
159:
160: /**
161: * @com.intel.drl.spec_ref
162: */
163: public static Package getPackage(String name) {
164: ClassLoader callerLoader = VMClassRegistry
165: .getClassLoader(VMStack.getCallerClass(0));
166: return callerLoader == null ? ClassLoader.BootstrapLoader
167: .getPackage(name) : callerLoader.getPackage(name);
168: }
169:
170: /**
171: * @com.intel.drl.spec_ref
172: */
173: public static Package[] getPackages() {
174: ClassLoader callerLoader = VMClassRegistry
175: .getClassLoader(VMStack.getCallerClass(0));
176: if (callerLoader == null) {
177: Collection<Package> pkgs = ClassLoader.BootstrapLoader
178: .getPackages();
179: return (Package[]) pkgs.toArray(new Package[pkgs.size()]);
180: }
181: return callerLoader.getPackages();
182: }
183:
184: /**
185: * @com.intel.drl.spec_ref
186: */
187: public String getImplementationTitle() {
188: if (jar != null) {
189: init();
190: }
191: return implTitle;
192: }
193:
194: /**
195: * @com.intel.drl.spec_ref
196: */
197: public String getImplementationVendor() {
198: if (jar != null) {
199: init();
200: }
201: return implVendor;
202: }
203:
204: /**
205: * @com.intel.drl.spec_ref
206: */
207: public String getImplementationVersion() {
208: if (jar != null) {
209: init();
210: }
211: return implVersion;
212: }
213:
214: /**
215: * @com.intel.drl.spec_ref
216: */
217: public String getName() {
218: return name;
219: }
220:
221: /**
222: * @com.intel.drl.spec_ref
223: */
224: public String getSpecificationTitle() {
225: if (jar != null) {
226: init();
227: }
228: return specTitle;
229: }
230:
231: /**
232: * @com.intel.drl.spec_ref
233: */
234: public String getSpecificationVendor() {
235: if (jar != null) {
236: init();
237: }
238: return specVendor;
239: }
240:
241: /**
242: * @com.intel.drl.spec_ref
243: */
244: public String getSpecificationVersion() {
245: if (jar != null) {
246: init();
247: }
248: return specVersion;
249: }
250:
251: /**
252: * @com.intel.drl.spec_ref
253: */
254: public int hashCode() {
255: return name.hashCode();
256: }
257:
258: /**
259: * @com.intel.drl.spec_ref
260: */
261: public boolean isCompatibleWith(String desiredVersion)
262: throws NumberFormatException {
263:
264: if (jar != null) {
265: init();
266: }
267:
268: if (specVersion == null || specVersion.length() == 0) {
269: throw new NumberFormatException(
270: "No specification version defined for the package");
271: }
272:
273: if (!specVersion
274: .matches("[\\p{javaDigit}]+(.[\\p{javaDigit}]+)*")) {
275: throw new NumberFormatException(
276: "Package specification version is not of the correct dotted form : "
277: + specVersion);
278: }
279:
280: if (desiredVersion == null || desiredVersion.length() == 0) {
281: throw new NumberFormatException("Empty version to check");
282: }
283:
284: if (!desiredVersion
285: .matches("[\\p{javaDigit}]+(.[\\p{javaDigit}]+)*")) {
286: throw new NumberFormatException(
287: "Desired version is not of the correct dotted form : "
288: + desiredVersion);
289: }
290:
291: StringTokenizer specVersionTokens = new StringTokenizer(
292: specVersion, ".");
293:
294: StringTokenizer desiredVersionTokens = new StringTokenizer(
295: desiredVersion, ".");
296:
297: try {
298: while (specVersionTokens.hasMoreElements()) {
299: int desiredVer = Integer.parseInt(desiredVersionTokens
300: .nextToken());
301: int specVer = Integer.parseInt(specVersionTokens
302: .nextToken());
303: if (specVer != desiredVer) {
304: return specVer > desiredVer;
305: }
306: }
307: } catch (NoSuchElementException e) {
308: /*
309: * run out of tokens for desiredVersion
310: */
311: }
312:
313: /*
314: * now, if desired is longer than spec, and they have been
315: * equal so far (ex. 1.4 <-> 1.4.0.0) then the remainder
316: * better be zeros
317: */
318:
319: while (desiredVersionTokens.hasMoreTokens()) {
320: if (0 != Integer.parseInt(desiredVersionTokens.nextToken())) {
321: return false;
322: }
323: }
324:
325: return true;
326: }
327:
328: /**
329: * @com.intel.drl.spec_ref
330: */
331: public boolean isSealed() {
332: if (jar != null) {
333: init();
334: }
335: return sealBase != null;
336: }
337:
338: /**
339: * @com.intel.drl.spec_ref
340: */
341: public boolean isSealed(URL url) {
342: if (jar != null) {
343: init();
344: }
345: return url.equals(sealBase);
346: }
347:
348: /**
349: * @com.intel.drl.spec_ref
350: */
351: public String toString() {
352: if (jar != null) {
353: init();
354: }
355: return "package " + name
356: + (specTitle != null ? " " + specTitle : "")
357: + (specVersion != null ? " " + specVersion : "");
358: }
359:
360: /**
361: * Performs initialization of optional attributes, if the source jar location
362: * was specified in the lazy constructor.
363: */
364: private void init() {
365: try {
366: Map<String, Manifest> map = null;
367: Manifest manifest = null;
368: URL sealURL = null;
369: if (jarCache != null && (map = jarCache.get()) != null) {
370: manifest = map.get(jar);
371: }
372:
373: if (manifest == null) {
374: final URL url = sealURL = new URL(jar);
375:
376: manifest = AccessController
377: .doPrivileged(new PrivilegedAction<Manifest>() {
378: public Manifest run() {
379: try {
380: return ((JarURLConnection) url
381: .openConnection())
382: .getManifest();
383: } catch (Exception e) {
384: return new Manifest();
385: }
386: }
387: });
388: if (map == null) {
389: map = new Hashtable<String, Manifest>();
390: if (jarCache == null) {
391: jarCache = new SoftReference<Map<String, Manifest>>(
392: map);
393: }
394: }
395: map.put(jar, manifest);
396: }
397:
398: Attributes mainAttrs = manifest.getMainAttributes();
399: Attributes pkgAttrs = manifest.getAttributes(name.replace(
400: '.', '/')
401: + "/");
402:
403: specTitle = pkgAttrs == null
404: || (specTitle = pkgAttrs
405: .getValue(Attributes.Name.SPECIFICATION_TITLE)) == null ? mainAttrs
406: .getValue(Attributes.Name.SPECIFICATION_TITLE)
407: : specTitle;
408: specVersion = pkgAttrs == null
409: || (specVersion = pkgAttrs
410: .getValue(Attributes.Name.SPECIFICATION_VERSION)) == null ? mainAttrs
411: .getValue(Attributes.Name.SPECIFICATION_VERSION)
412: : specVersion;
413: specVendor = pkgAttrs == null
414: || (specVendor = pkgAttrs
415: .getValue(Attributes.Name.SPECIFICATION_VENDOR)) == null ? mainAttrs
416: .getValue(Attributes.Name.SPECIFICATION_VENDOR)
417: : specVendor;
418: implTitle = pkgAttrs == null
419: || (implTitle = pkgAttrs
420: .getValue(Attributes.Name.IMPLEMENTATION_TITLE)) == null ? mainAttrs
421: .getValue(Attributes.Name.IMPLEMENTATION_TITLE)
422: : implTitle;
423: implVersion = pkgAttrs == null
424: || (implVersion = pkgAttrs
425: .getValue(Attributes.Name.IMPLEMENTATION_VERSION)) == null ? mainAttrs
426: .getValue(Attributes.Name.IMPLEMENTATION_VERSION)
427: : implVersion;
428: implVendor = pkgAttrs == null
429: || (implVendor = pkgAttrs
430: .getValue(Attributes.Name.IMPLEMENTATION_VENDOR)) == null ? mainAttrs
431: .getValue(Attributes.Name.IMPLEMENTATION_VENDOR)
432: : implVendor;
433: String sealed = pkgAttrs == null
434: || (sealed = pkgAttrs
435: .getValue(Attributes.Name.SEALED)) == null ? mainAttrs
436: .getValue(Attributes.Name.SEALED)
437: : sealed;
438: if (Boolean.valueOf(sealed).booleanValue()) {
439: sealBase = sealURL != null ? sealURL : new URL(jar);
440: }
441: } catch (Exception e) {
442: }
443: jar = null;
444: }
445: }
|