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