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