aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java458
1 files changed, 0 insertions, 458 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java
deleted file mode 100644
index 754cedf79..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 com.android.ide.eclipse.adt.internal.sdk;
-
-import com.android.SdkConstants;
-import com.google.common.io.Closeables;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.SubMonitor;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import javax.management.InvalidAttributeValueException;
-
-/**
- * Custom class loader able to load a class from the SDK jar file.
- */
-public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader {
-
- /**
- * Wrapper around a {@link Class} to provide the methods of
- * {@link IAndroidClassLoader.IClassDescriptor}.
- */
- public final static class ClassWrapper implements IClassDescriptor {
- private Class<?> mClass;
-
- public ClassWrapper(Class<?> clazz) {
- mClass = clazz;
- }
-
- @Override
- public String getFullClassName() {
- return mClass.getCanonicalName();
- }
-
- @Override
- public IClassDescriptor[] getDeclaredClasses() {
- Class<?>[] classes = mClass.getDeclaredClasses();
- IClassDescriptor[] iclasses = new IClassDescriptor[classes.length];
- for (int i = 0 ; i < classes.length ; i++) {
- iclasses[i] = new ClassWrapper(classes[i]);
- }
-
- return iclasses;
- }
-
- @Override
- public IClassDescriptor getEnclosingClass() {
- return new ClassWrapper(mClass.getEnclosingClass());
- }
-
- @Override
- public String getSimpleName() {
- return mClass.getSimpleName();
- }
-
- @Override
- public IClassDescriptor getSuperclass() {
- return new ClassWrapper(mClass.getSuperclass());
- }
-
- @Override
- public boolean equals(Object clazz) {
- if (clazz instanceof ClassWrapper) {
- return mClass.equals(((ClassWrapper)clazz).mClass);
- }
- return super.equals(clazz);
- }
-
- @Override
- public int hashCode() {
- return mClass.hashCode();
- }
-
-
- @Override
- public boolean isInstantiable() {
- int modifiers = mClass.getModifiers();
- return Modifier.isAbstract(modifiers) == false && Modifier.isPublic(modifiers) == true;
- }
-
- public Class<?> wrappedClass() {
- return mClass;
- }
-
- }
-
- private String mOsFrameworkLocation;
-
- /** A cache for binary data extracted from the zip */
- private final HashMap<String, byte[]> mEntryCache = new HashMap<String, byte[]>();
- /** A cache for already defined Classes */
- private final HashMap<String, Class<?> > mClassCache = new HashMap<String, Class<?> >();
-
- /**
- * Creates the class loader by providing the os path to the framework jar archive
- *
- * @param osFrameworkLocation OS Path of the framework JAR file
- */
- public AndroidJarLoader(String osFrameworkLocation) {
- super();
- mOsFrameworkLocation = osFrameworkLocation;
- }
-
- @Override
- public String getSource() {
- return mOsFrameworkLocation;
- }
-
- /**
- * Pre-loads all class binary data that belong to the given package by reading the archive
- * once and caching them internally.
- * <p/>
- * This does not actually preload "classes", it just reads the unzipped bytes for a given
- * class. To obtain a class, one must call {@link #findClass(String)} later.
- * <p/>
- * All classes which package name starts with "packageFilter" will be included and can be
- * found later.
- * <p/>
- * May throw some exceptions if the framework JAR cannot be read.
- *
- * @param packageFilter The package that contains all the class data to preload, using a fully
- * qualified binary name (.e.g "com.my.package."). The matching algorithm
- * is simple "startsWith". Use an empty string to include everything.
- * @param taskLabel An optional task name for the sub monitor. Can be null.
- * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
- * @throws IOException
- * @throws InvalidAttributeValueException
- * @throws ClassFormatError
- */
- public void preLoadClasses(String packageFilter, String taskLabel, IProgressMonitor monitor)
- throws IOException, InvalidAttributeValueException, ClassFormatError {
- // Transform the package name into a zip entry path
- String pathFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
-
- SubMonitor progress = SubMonitor.convert(monitor, taskLabel == null ? "" : taskLabel, 100);
-
- // create streams to read the intermediary archive
- FileInputStream fis = new FileInputStream(mOsFrameworkLocation);
- ZipInputStream zis = new ZipInputStream(fis);
- ZipEntry entry;
- while ((entry = zis.getNextEntry()) != null) {
- // get the name of the entry.
- String entryPath = entry.getName();
-
- if (!entryPath.endsWith(SdkConstants.DOT_CLASS)) {
- // only accept class files
- continue;
- }
-
- // check if it is part of the package to preload
- if (pathFilter.length() > 0 && !entryPath.startsWith(pathFilter)) {
- continue;
- }
- String className = entryPathToClassName(entryPath);
-
- if (!mEntryCache.containsKey(className)) {
- long entrySize = entry.getSize();
- if (entrySize > Integer.MAX_VALUE) {
- throw new InvalidAttributeValueException();
- }
- byte[] data = readZipData(zis, (int)entrySize);
- mEntryCache.put(className, data);
- }
-
- // advance 5% of whatever is allocated on the progress bar
- progress.setWorkRemaining(100);
- progress.worked(5);
- progress.subTask(String.format("Preload %1$s", className));
- }
- }
-
- /**
- * Finds and loads all classes that derive from a given set of super classes.
- * <p/>
- * As a side-effect this will load and cache most, if not all, classes in the input JAR file.
- *
- * @param packageFilter Base name of package of classes to find.
- * Use an empty string to find everyting.
- * @param superClasses The super classes of all the classes to find.
- * @return An hash map which keys are the super classes looked for and which values are
- * ArrayList of the classes found. The array lists are always created for all the
- * valid keys, they are simply empty if no deriving class is found for a given
- * super class.
- * @throws IOException
- * @throws InvalidAttributeValueException
- * @throws ClassFormatError
- */
- @SuppressWarnings("resource") // Eclipse doesn't understand Closeables.closeQuietly
- @Override
- public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
- String packageFilter,
- String[] superClasses)
- throws IOException, InvalidAttributeValueException, ClassFormatError {
-
- packageFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
-
- HashMap<String, ArrayList<IClassDescriptor>> mClassesFound =
- new HashMap<String, ArrayList<IClassDescriptor>>();
-
- for (String className : superClasses) {
- mClassesFound.put(className, new ArrayList<IClassDescriptor>());
- }
-
- // create streams to read the intermediary archive
- FileInputStream fis = new FileInputStream(mOsFrameworkLocation);
- ZipInputStream zis = new ZipInputStream(fis);
- try {
- ZipEntry entry;
- while ((entry = zis.getNextEntry()) != null) {
- // get the name of the entry and convert to a class binary name
- String entryPath = entry.getName();
- if (!entryPath.endsWith(SdkConstants.DOT_CLASS)) {
- // only accept class files
- continue;
- }
- if (packageFilter.length() > 0 && !entryPath.startsWith(packageFilter)) {
- // only accept stuff from the requested root package.
- continue;
- }
- String className = entryPathToClassName(entryPath);
-
- Class<?> loaded_class = mClassCache.get(className);
- if (loaded_class == null) {
- byte[] data = mEntryCache.get(className);
- if (data == null) {
- // Get the class and cache it
- long entrySize = entry.getSize();
- if (entrySize > Integer.MAX_VALUE) {
- throw new InvalidAttributeValueException();
- }
- data = readZipData(zis, (int)entrySize);
- }
- try {
- loaded_class = defineAndCacheClass(className, data);
- } catch (NoClassDefFoundError error) {
- if (error.getMessage().startsWith("java/")) {
- // Can't define these; we just need to stop
- // iteration here
- continue;
- }
- throw error;
- }
- }
-
- for (Class<?> superClass = loaded_class.getSuperclass();
- superClass != null;
- superClass = superClass.getSuperclass()) {
- String superName = superClass.getCanonicalName();
- if (mClassesFound.containsKey(superName)) {
- mClassesFound.get(superName).add(new ClassWrapper(loaded_class));
- break;
- }
- }
- }
- } finally {
- Closeables.closeQuietly(zis);
- }
-
- return mClassesFound;
- }
-
- /** Helper method that converts a Zip entry path into a corresponding
- * Java full qualified binary class name.
- * <p/>
- * F.ex, this converts "com/my/package/Foo.class" into "com.my.package.Foo".
- */
- private String entryPathToClassName(String entryPath) {
- return entryPath.replaceFirst("\\.class$", "").replaceAll("[/\\\\]", "."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- /**
- * Finds the class with the specified binary name.
- *
- * {@inheritDoc}
- */
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- try {
- // try to find the class in the cache
- Class<?> cached_class = mClassCache.get(name);
- if (cached_class == ClassNotFoundException.class) {
- // we already know we can't find this class, don't try again
- throw new ClassNotFoundException(name);
- } else if (cached_class != null) {
- return cached_class;
- }
-
- // if not found, look it up and cache it
- byte[] data = loadClassData(name);
- if (data != null) {
- return defineAndCacheClass(name, data);
- } else {
- // if the class can't be found, record a CNFE class in the map so
- // that we don't try to reload it next time
- mClassCache.put(name, ClassNotFoundException.class);
- throw new ClassNotFoundException(name);
- }
- } catch (ClassNotFoundException e) {
- throw e;
- } catch (Exception e) {
- throw new ClassNotFoundException(e.getMessage());
- }
- }
-
- /**
- * Defines a class based on its binary data and caches the resulting class object.
- *
- * @param name The binary name of the class (i.e. package.class1$class2)
- * @param data The binary data from the loader.
- * @return The class defined
- * @throws ClassFormatError if defineClass failed.
- */
- private Class<?> defineAndCacheClass(String name, byte[] data) throws ClassFormatError {
- Class<?> cached_class;
- cached_class = defineClass(null, data, 0, data.length);
-
- if (cached_class != null) {
- // Add new class to the cache class and remove it from the zip entry data cache
- mClassCache.put(name, cached_class);
- mEntryCache.remove(name);
- }
- return cached_class;
- }
-
- /**
- * Loads a class data from its binary name.
- * <p/>
- * This uses the class binary data that has been preloaded earlier by the preLoadClasses()
- * method if possible.
- *
- * @param className the binary name
- * @return an array of bytes representing the class data or null if not found
- * @throws InvalidAttributeValueException
- * @throws IOException
- */
- private synchronized byte[] loadClassData(String className)
- throws InvalidAttributeValueException, IOException {
-
- byte[] data = mEntryCache.get(className);
- if (data != null) {
- return data;
- }
-
- // The name is a binary name. Something like "android.R", or "android.R$id".
- // Make a path out of it.
- String entryName = className.replaceAll("\\.", "/") + SdkConstants.DOT_CLASS; //$NON-NLS-1$ //$NON-NLS-2$
-
- // create streams to read the intermediary archive
- FileInputStream fis = new FileInputStream(mOsFrameworkLocation);
- ZipInputStream zis = new ZipInputStream(fis);
- try {
- // loop on the entries of the intermediary package and put them in the final package.
- ZipEntry entry;
-
- while ((entry = zis.getNextEntry()) != null) {
- // get the name of the entry.
- String currEntryName = entry.getName();
-
- if (currEntryName.equals(entryName)) {
- long entrySize = entry.getSize();
- if (entrySize > Integer.MAX_VALUE) {
- throw new InvalidAttributeValueException();
- }
-
- data = readZipData(zis, (int)entrySize);
- return data;
- }
- }
-
- return null;
- } finally {
- zis.close();
- }
- }
-
- /**
- * Reads data for the <em>current</em> entry from the zip input stream.
- *
- * @param zis The Zip input stream
- * @param entrySize The entry size. -1 if unknown.
- * @return The new data for the <em>current</em> entry.
- * @throws IOException If ZipInputStream.read() fails.
- */
- private byte[] readZipData(ZipInputStream zis, int entrySize) throws IOException {
- int block_size = 1024;
- int data_size = entrySize < 1 ? block_size : entrySize;
- int offset = 0;
- byte[] data = new byte[data_size];
-
- while(zis.available() != 0) {
- int count = zis.read(data, offset, data_size - offset);
- if (count < 0) { // read data is done
- break;
- }
- offset += count;
-
- if (entrySize >= 1 && offset >= entrySize) { // we know the size and we're done
- break;
- }
-
- // if we don't know the entry size and we're not done reading,
- // expand the data buffer some more.
- if (offset >= data_size) {
- byte[] temp = new byte[data_size + block_size];
- System.arraycopy(data, 0, temp, 0, data_size);
- data_size += block_size;
- data = temp;
- block_size *= 2;
- }
- }
-
- if (offset < data_size) {
- // buffer was allocated too large, trim it
- byte[] temp = new byte[offset];
- if (offset > 0) {
- System.arraycopy(data, 0, temp, 0, offset);
- }
- data = temp;
- }
-
- return data;
- }
-
- /**
- * Returns a {@link IAndroidClassLoader.IClassDescriptor} by its fully-qualified name.
- * @param className the fully-qualified name of the class to return.
- * @throws ClassNotFoundException
- */
- @Override
- public IClassDescriptor getClass(String className) throws ClassNotFoundException {
- try {
- return new ClassWrapper(loadClass(className));
- } catch (ClassNotFoundException e) {
- throw e; // useful for debugging
- }
- }
-}