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