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 
     53     private final String name, specTitle, specVersion, specVendor, implTitle,
     54             implVersion, implVendor;
     55     private final URL sealBase;
     56 
     57     Package(String name, String specTitle, String specVersion, String specVendor,
     58             String implTitle, String implVersion, String implVendor, URL sealBase) {
     59         this.name = name;
     60         this.specTitle = specTitle;
     61         this.specVersion = specVersion;
     62         this.specVendor = specVendor;
     63         this.implTitle = implTitle;
     64         this.implVersion = implVersion;
     65         this.implVendor = implVendor;
     66         this.sealBase = sealBase;
     67     }
     68 
     69     /**
     70      * Gets the annotation associated with the specified annotation type and
     71      * this package, if present.
     72      *
     73      * @param annotationType
     74      *            the annotation type to look for.
     75      * @return an instance of {@link Annotation} or {@code null}.
     76      * @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class)
     77      */
     78     @SuppressWarnings("unchecked")
     79     public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
     80         Annotation[] list = getAnnotations();
     81         for (int i = 0; i < list.length; i++) {
     82             if (annotationType.isInstance(list[i])) {
     83                 return (A) list[i];
     84             }
     85         }
     86 
     87         return null;
     88     }
     89 
     90     /**
     91      * Gets all annotations associated with this package, if any.
     92      *
     93      * @return an array of {@link Annotation} instances, which may be empty.
     94      * @see java.lang.reflect.AnnotatedElement#getAnnotations()
     95      */
     96     public Annotation[] getAnnotations() {
     97         return getDeclaredAnnotations(this, true);
     98     }
     99 
    100     /**
    101      * Gets all annotations directly declared on this package, if any.
    102      *
    103      * @return an array of {@link Annotation} instances, which may be empty.
    104      * @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotations()
    105      */
    106     public Annotation[] getDeclaredAnnotations() {
    107         return getDeclaredAnnotations(this, false);
    108     }
    109 
    110     /*
    111      * Returns the list of declared annotations of the given package.
    112      * If no annotations exist, an empty array is returned.
    113      *
    114      * @param pkg the package of interest
    115      * @param publicOnly reflects whether we want only public annotation or all
    116      * of them.
    117      * @return the list of annotations
    118      */
    119     // TODO(Google) Provide proper (native) implementation.
    120     private static native Annotation[] getDeclaredAnnotations(Package pkg,
    121             boolean publicOnly);
    122 
    123     /**
    124      * Indicates whether the specified annotation is present.
    125      *
    126      * @param annotationType
    127      *            the annotation type to look for.
    128      * @return {@code true} if the annotation is present; {@code false}
    129      *         otherwise.
    130      * @see java.lang.reflect.AnnotatedElement#isAnnotationPresent(java.lang.Class)
    131      */
    132     public boolean isAnnotationPresent(
    133             Class<? extends Annotation> annotationType) {
    134         return getAnnotation(annotationType) != null;
    135     }
    136 
    137     /**
    138      * Returns the title of the implementation of this package, or {@code null}
    139      * if this is unknown. The format of this string is unspecified.
    140      *
    141      * @return the implementation title, may be {@code null}.
    142      */
    143     public String getImplementationTitle() {
    144         return implTitle;
    145     }
    146 
    147     /**
    148      * Returns the name of the vendor or organization that provides this
    149      * implementation of the package, or {@code null} if this is unknown. The
    150      * format of this string is unspecified.
    151      *
    152      * @return the implementation vendor name, may be {@code null}.
    153      */
    154     public String getImplementationVendor() {
    155         return implVendor;
    156     }
    157 
    158     /**
    159      * Returns the version of the implementation of this package, or {@code
    160      * null} if this is unknown. The format of this string is unspecified.
    161      *
    162      * @return the implementation version, may be {@code null}.
    163      */
    164     public String getImplementationVersion() {
    165         return implVersion;
    166     }
    167 
    168     /**
    169      * Returns the name of this package in the standard dot notation; for
    170      * example: "java.lang".
    171      *
    172      * @return the name of this package.
    173      */
    174     public String getName() {
    175         return name;
    176     }
    177 
    178     /**
    179      * Attempts to locate the requested package in the caller's class loader. If
    180      * no package information can be located, {@code null} is returned.
    181      *
    182      * @param packageName
    183      *            the name of the package to find.
    184      * @return the requested package, or {@code null}.
    185      * @see ClassLoader#getPackage(java.lang.String)
    186      */
    187     public static Package getPackage(String packageName) {
    188         ClassLoader classloader = VMStack.getCallingClassLoader();
    189         return classloader.getPackage(packageName);
    190     }
    191 
    192     /**
    193      * Returns all the packages known to the caller's class loader.
    194      *
    195      * @return all the packages known to the caller's class loader.
    196      * @see ClassLoader#getPackages
    197      */
    198     public static Package[] getPackages() {
    199         ClassLoader classloader = VMStack.getCallingClassLoader();
    200         return classloader.getPackages();
    201     }
    202 
    203     /**
    204      * Returns the title of the specification this package implements, or
    205      * {@code null} if this is unknown.
    206      *
    207      * @return the specification title, may be {@code null}.
    208      */
    209     public String getSpecificationTitle() {
    210         return specTitle;
    211     }
    212 
    213     /**
    214      * Returns the name of the vendor or organization that owns and maintains
    215      * the specification this package implements, or {@code null} if this is
    216      * unknown.
    217      *
    218      * @return the specification vendor name, may be {@code null}.
    219      */
    220     public String getSpecificationVendor() {
    221         return specVendor;
    222     }
    223 
    224     /**
    225      * Returns the version of the specification this package implements, or
    226      * {@code null} if this is unknown. The version string is a sequence of
    227      * non-negative integers separated by dots; for example: "1.2.3".
    228      *
    229      * @return the specification version string, may be {@code null}.
    230      */
    231     public String getSpecificationVersion() {
    232         return specVersion;
    233     }
    234 
    235     @Override
    236     public int hashCode() {
    237         return name.hashCode();
    238     }
    239 
    240     /**
    241      * Indicates whether this package's specification version is compatible with
    242      * the specified version string. Version strings are compared by comparing
    243      * each dot separated part of the version as an integer.
    244      *
    245      * @param version
    246      *            the version string to compare against.
    247      * @return {@code true} if the package versions are compatible; {@code
    248      *         false} otherwise.
    249      * @throws NumberFormatException
    250      *             if this package's version string or the one provided are not
    251      *             in the correct format.
    252      */
    253     public boolean isCompatibleWith(String version)
    254             throws NumberFormatException {
    255         String[] requested = version.split("\\.");
    256         String[] provided = specVersion.split("\\.");
    257 
    258         for (int i = 0; i < Math.min(requested.length, provided.length); i++) {
    259             int reqNum = Integer.parseInt(requested[i]);
    260             int provNum = Integer.parseInt(provided[i]);
    261 
    262             if (reqNum > provNum) {
    263                 return false;
    264             } else if (reqNum < provNum) {
    265                 return true;
    266             }
    267         }
    268 
    269         if (requested.length > provided.length) {
    270             return false;
    271         }
    272 
    273         return true;
    274     }
    275 
    276     /**
    277      * Indicates whether this package is sealed.
    278      *
    279      * @return {@code true} if this package is sealed; {@code false} otherwise.
    280      */
    281     public boolean isSealed() {
    282         return sealBase != null;
    283     }
    284 
    285     /**
    286      * Indicates whether this package is sealed with respect to the specified
    287      * URL.
    288      *
    289      * @param url
    290      *            the URL to check.
    291      * @return {@code true} if this package is sealed with {@code url}; {@code
    292      *         false} otherwise
    293      */
    294     public boolean isSealed(URL url) {
    295         return sealBase != null && sealBase.sameFile(url);
    296     }
    297 
    298     @Override
    299     public String toString() {
    300         return "package " + name;
    301     }
    302 }
    303