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