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 33package java.lang; 34 35import dalvik.system.VMStack; 36import java.lang.annotation.Annotation; 37import java.lang.reflect.AnnotatedElement; 38import 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 */ 51public 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