Home | History | Annotate | Download | only in lang
      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 
     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")
     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      */
     97     public Annotation[] getAnnotations() {
     98         return NO_ANNOTATIONS;
     99     }
    100 
    101     /**
    102      * Returns an empty array. Package annotations are not supported on Android.
    103      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    221     public String getSpecificationVersion() {
    222         return specVersion;
    223     }
    224 
    225     @Override
    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      */
    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      */
    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      */
    283     public boolean isSealed(URL url) {
    284         return sealBase != null && sealBase.sameFile(url);
    285     }
    286 
    287     @Override
    288     public String toString() {
    289         return "package " + name;
    290     }
    291 }
    292