• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 /*
18  * Copyright (C) 2008 The Android Open Source Project
19  *
20  * Licensed under the Apache License, Version 2.0 (the "License");
21  * you may not use this file except in compliance with the License.
22  * You may obtain a copy of the License at
23  *
24  *      http://www.apache.org/licenses/LICENSE-2.0
25  *
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS,
28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29  * See the License for the specific language governing permissions and
30  * limitations under the License.
31  */
32 
33 package java.lang;
34 
35 import dalvik.system.VMStack;
36 import java.lang.annotation.Annotation;
37 import java.lang.reflect.AnnotatedElement;
38 import java.net.URL;
39 
40 /**
41  * Contains information about a Java package. This includes implementation and
42  * specification versions. Typically this information is retrieved from the
43  * manifest.
44  * <p>
45  * Packages are managed by class loaders. All classes loaded by the same loader
46  * from the same package share a {@code Package} instance.
47  * </p>
48  *
49  * @see java.lang.ClassLoader
50  */
51 public class Package implements AnnotatedElement {
52     private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];
53 
54     private final String name;
55     private final String specTitle;
56     private final String specVersion;
57     private final String specVendor;
58     private final String implTitle;
59     private final String implVersion;
60     private final String implVendor;
61     private final URL sealBase;
62 
Package(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)63     Package(String name, String specTitle, String specVersion, String specVendor,
64             String implTitle, String implVersion, String implVendor, URL sealBase) {
65         this.name = name;
66         this.specTitle = specTitle;
67         this.specVersion = specVersion;
68         this.specVendor = specVendor;
69         this.implTitle = implTitle;
70         this.implVersion = implVersion;
71         this.implVendor = implVendor;
72         this.sealBase = sealBase;
73     }
74 
75     /**
76      * Gets the annotation associated with the specified annotation type and
77      * this package, if present.
78      *
79      * @param annotationType
80      *            the annotation type to look for.
81      * @return an instance of {@link Annotation} or {@code null}.
82      * @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class)
83      */
84     @SuppressWarnings("unchecked")
getAnnotation(Class<A> annotationType)85     public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
86         for (Annotation annotation : getAnnotations()) {
87             if (annotationType.isInstance(annotation)) {
88                 return (A) annotation;
89             }
90         }
91         return null;
92     }
93 
94     /**
95      * Returns an empty array. Package annotations are not supported on Android.
96      */
getAnnotations()97     public Annotation[] getAnnotations() {
98         return NO_ANNOTATIONS;
99     }
100 
101     /**
102      * Returns an empty array. Package annotations are not supported on Android.
103      */
getDeclaredAnnotations()104     public Annotation[] getDeclaredAnnotations() {
105         return NO_ANNOTATIONS;
106     }
107 
108     /**
109      * Indicates whether the specified annotation is present.
110      *
111      * @param annotationType
112      *            the annotation type to look for.
113      * @return {@code true} if the annotation is present; {@code false}
114      *         otherwise.
115      * @see java.lang.reflect.AnnotatedElement#isAnnotationPresent(java.lang.Class)
116      */
isAnnotationPresent(Class<? extends Annotation> annotationType)117     public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
118         return getAnnotation(annotationType) != null;
119     }
120 
121     /**
122      * Returns the title of the implementation of this package, or {@code null}
123      * if this is unknown. The format of this string is unspecified.
124      *
125      * @return the implementation title, may be {@code null}.
126      */
getImplementationTitle()127     public String getImplementationTitle() {
128         return implTitle;
129     }
130 
131     /**
132      * Returns the name of the vendor or organization that provides this
133      * implementation of the package, or {@code null} if this is unknown. The
134      * format of this string is unspecified.
135      *
136      * @return the implementation vendor name, may be {@code null}.
137      */
getImplementationVendor()138     public String getImplementationVendor() {
139         return implVendor;
140     }
141 
142     /**
143      * Returns the version of the implementation of this package, or {@code
144      * null} if this is unknown. The format of this string is unspecified.
145      *
146      * @return the implementation version, may be {@code null}.
147      */
getImplementationVersion()148     public String getImplementationVersion() {
149         return implVersion;
150     }
151 
152     /**
153      * Returns the name of this package in the standard dot notation; for
154      * example: "java.lang".
155      *
156      * @return the name of this package.
157      */
getName()158     public String getName() {
159         return name;
160     }
161 
162     /**
163      * Attempts to locate the requested package in the caller's class loader. If
164      * no package information can be located, {@code null} is returned.
165      *
166      * @param packageName
167      *            the name of the package to find.
168      * @return the requested package, or {@code null}.
169      * @see ClassLoader#getPackage(java.lang.String)
170      */
getPackage(String packageName)171     public static Package getPackage(String packageName) {
172         ClassLoader classloader = VMStack.getCallingClassLoader();
173         if (classloader == null) {
174             classloader = ClassLoader.getSystemClassLoader();
175         }
176         return classloader.getPackage(packageName);
177     }
178 
179     /**
180      * Returns all the packages known to the caller's class loader.
181      *
182      * @return all the packages known to the caller's class loader.
183      * @see ClassLoader#getPackages
184      */
getPackages()185     public static Package[] getPackages() {
186         ClassLoader classloader = VMStack.getCallingClassLoader();
187         if (classloader == null) {
188             classloader = ClassLoader.getSystemClassLoader();
189         }
190         return classloader.getPackages();
191     }
192 
193     /**
194      * Returns the title of the specification this package implements, or
195      * {@code null} if this is unknown.
196      *
197      * @return the specification title, may be {@code null}.
198      */
getSpecificationTitle()199     public String getSpecificationTitle() {
200         return specTitle;
201     }
202 
203     /**
204      * Returns the name of the vendor or organization that owns and maintains
205      * the specification this package implements, or {@code null} if this is
206      * unknown.
207      *
208      * @return the specification vendor name, may be {@code null}.
209      */
getSpecificationVendor()210     public String getSpecificationVendor() {
211         return specVendor;
212     }
213 
214     /**
215      * Returns the version of the specification this package implements, or
216      * {@code null} if this is unknown. The version string is a sequence of
217      * non-negative integers separated by dots; for example: "1.2.3".
218      *
219      * @return the specification version string, may be {@code null}.
220      */
getSpecificationVersion()221     public String getSpecificationVersion() {
222         return specVersion;
223     }
224 
225     @Override
hashCode()226     public int hashCode() {
227         return name.hashCode();
228     }
229 
230     /**
231      * Indicates whether this package's specification version is compatible with
232      * the specified version string. Version strings are compared by comparing
233      * each dot separated part of the version as an integer.
234      *
235      * @param version
236      *            the version string to compare against.
237      * @return {@code true} if the package versions are compatible; {@code
238      *         false} otherwise.
239      * @throws NumberFormatException
240      *             if this package's version string or the one provided are not
241      *             in the correct format.
242      */
isCompatibleWith(String version)243     public boolean isCompatibleWith(String version) throws NumberFormatException {
244         String[] requested = version.split("\\.");
245         String[] provided = specVersion.split("\\.");
246 
247         for (int i = 0; i < Math.min(requested.length, provided.length); i++) {
248             int reqNum = Integer.parseInt(requested[i]);
249             int provNum = Integer.parseInt(provided[i]);
250 
251             if (reqNum > provNum) {
252                 return false;
253             } else if (reqNum < provNum) {
254                 return true;
255             }
256         }
257 
258         if (requested.length > provided.length) {
259             return false;
260         }
261 
262         return true;
263     }
264 
265     /**
266      * Indicates whether this package is sealed.
267      *
268      * @return {@code true} if this package is sealed; {@code false} otherwise.
269      */
isSealed()270     public boolean isSealed() {
271         return sealBase != null;
272     }
273 
274     /**
275      * Indicates whether this package is sealed with respect to the specified
276      * URL.
277      *
278      * @param url
279      *            the URL to check.
280      * @return {@code true} if this package is sealed with {@code url}; {@code
281      *         false} otherwise
282      */
isSealed(URL url)283     public boolean isSealed(URL url) {
284         return sealBase != null && sealBase.sameFile(url);
285     }
286 
287     @Override
toString()288     public String toString() {
289         return "package " + name;
290     }
291 }
292