blob: 58cee36afe246744eb5753f2a871f2736dd000ba [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang;
import dalvik.system.VMStack;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.net.URL;
/**
* Contains information about a Java package. This includes implementation and
* specification versions. Typically this information is retrieved from the
* manifest.
* <p>
* Packages are managed by class loaders. All classes loaded by the same loader
* from the same package share a {@code Package} instance.
* </p>
* @since Android 1.0
*
* @see java.lang.ClassLoader
*/
public class Package implements AnnotatedElement {
private final String name, specTitle, specVersion, specVendor, implTitle,
implVersion, implVendor;
private final URL sealBase;
Package(String name, String specTitle, String specVersion, String specVendor,
String implTitle, String implVersion, String implVendor, URL sealBase) {
this.name = name;
this.specTitle = specTitle;
this.specVersion = specVersion;
this.specVendor = specVendor;
this.implTitle = implTitle;
this.implVersion = implVersion;
this.implVendor = implVendor;
this.sealBase = sealBase;
}
/**
* Gets the annotation associated with the specified annotation type and
* this package, if present.
*
* @param annotationType
* the annotation type to look for.
* @return an instance of {@link Annotation} or {@code null}.
* @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class)
* @since Android 1.0
*/
@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
Annotation[] list = getAnnotations();
for (int i = 0; i < list.length; i++) {
if (annotationType.isInstance(list[i])) {
return (A) list[i];
}
}
return null;
}
/**
* Gets all annotations associated with this package, if any.
*
* @return an array of {@link Annotation} instances, which may be empty.
* @see java.lang.reflect.AnnotatedElement#getAnnotations()
* @since Android 1.0
*/
public Annotation[] getAnnotations() {
return getDeclaredAnnotations(this, true);
}
/**
* Gets all annotations directly declared on this package, if any.
*
* @return an array of {@link Annotation} instances, which may be empty.
* @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotations()
* @since Android 1.0
*/
public Annotation[] getDeclaredAnnotations() {
return getDeclaredAnnotations(this, false);
}
/*
* Returns the list of declared annotations of the given package.
* If no annotations exist, an empty array is returned.
*
* @param pkg the package of interest
* @param publicOnly reflects whether we want only public annotation or all
* of them.
* @return the list of annotations
*/
// TODO(Google) Provide proper (native) implementation.
private static native Annotation[] getDeclaredAnnotations(Package pkg,
boolean publicOnly);
/**
* Indicates whether the specified annotation is present.
*
* @param annotationType
* the annotation type to look for.
* @return {@code true} if the annotation is present; {@code false}
* otherwise.
* @see java.lang.reflect.AnnotatedElement#isAnnotationPresent(java.lang.Class)
* @since Android 1.0
*/
public boolean isAnnotationPresent(
Class<? extends Annotation> annotationType) {
return getAnnotation(annotationType) != null;
}
/**
* Returns the title of the implementation of this package, or {@code null}
* if this is unknown. The format of this string is unspecified.
*
* @return the implementation title, may be {@code null}.
* @since Android 1.0
*/
public String getImplementationTitle() {
return implTitle;
}
/**
* Returns the name of the vendor or organization that provides this
* implementation of the package, or {@code null} if this is unknown. The
* format of this string is unspecified.
*
* @return the implementation vendor name, may be {@code null}.
* @since Android 1.0
*/
public String getImplementationVendor() {
return implVendor;
}
/**
* Returns the version of the implementation of this package, or {@code
* null} if this is unknown. The format of this string is unspecified.
*
* @return the implementation version, may be {@code null}.
* @since Android 1.0
*/
public String getImplementationVersion() {
return implVersion;
}
/**
* Returns the name of this package in the standard dot notation; for
* example: "java.lang".
*
* @return the name of this package.
* @since Android 1.0
*/
public String getName() {
return name;
}
/**
* Attempts to locate the requested package in the caller's class loader. If
* no package information can be located, {@code null} is returned.
*
* @param packageName
* the name of the package to find.
* @return the requested package, or {@code null}.
* @see ClassLoader#getPackage(java.lang.String)
* @since Android 1.0
*/
public static Package getPackage(String packageName) {
ClassLoader classloader = VMStack.getCallingClassLoader();
return classloader.getPackage(packageName);
}
/**
* Returns all the packages known to the caller's class loader.
*
* @return all the packages known to the caller's class loader.
* @see ClassLoader#getPackages
* @since Android 1.0
*/
public static Package[] getPackages() {
ClassLoader classloader = VMStack.getCallingClassLoader();
return classloader.getPackages();
}
/**
* Returns the title of the specification this package implements, or
* {@code null} if this is unknown.
*
* @return the specification title, may be {@code null}.
* @since Android 1.0
*/
public String getSpecificationTitle() {
return specTitle;
}
/**
* Returns the name of the vendor or organization that owns and maintains
* the specification this package implements, or {@code null} if this is
* unknown.
*
* @return the specification vendor name, may be {@code null}.
* @since Android 1.0
*/
public String getSpecificationVendor() {
return specVendor;
}
/**
* Returns the version of the specification this package implements, or
* {@code null} if this is unknown. The version string is a sequence of
* non-negative integers separated by dots; for example: "1.2.3".
*
* @return the specification version string, may be {@code null}.
* @since Android 1.0
*/
public String getSpecificationVersion() {
return specVersion;
}
@Override
public int hashCode() {
return name.hashCode();
}
/**
* Indicates whether this package's specification version is compatible with
* the specified version string. Version strings are compared by comparing
* each dot separated part of the version as an integer.
*
* @param version
* the version string to compare against.
* @return {@code true} if the package versions are compatible; {@code
* false} otherwise.
* @throws NumberFormatException
* if this package's version string or the one provided are not
* in the correct format.
* @since Android 1.0
*/
public boolean isCompatibleWith(String version)
throws NumberFormatException {
String[] requested = version.split("\\.");
String[] provided = specVersion.split("\\.");
for (int i = 0; i < Math.min(requested.length, provided.length); i++) {
int reqNum = Integer.parseInt(requested[i]);
int provNum = Integer.parseInt(provided[i]);
if (reqNum > provNum) {
return false;
} else if (reqNum < provNum) {
return true;
}
}
if (requested.length > provided.length) {
return false;
}
return true;
}
/**
* Indicates whether this package is sealed.
*
* @return {@code true} if this package is sealed; {@code false} otherwise.
* @since Android 1.0
*/
public boolean isSealed() {
return sealBase != null;
}
/**
* Indicates whether this package is sealed with respect to the specified
* URL.
*
* @param url
* the URL to check.
* @return {@code true} if this package is sealed with {@code url}; {@code
* false} otherwise
* @since Android 1.0
*/
public boolean isSealed(URL url) {
return sealBase != null && sealBase.sameFile(url);
}
@Override
public String toString() {
return "package " + name;
}
}