aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk')
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtConsoleSdkLog.java59
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtManifestMergeCallback.java46
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java458
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java417
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java605
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/IAndroidClassLoader.java81
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutParamsParser.java378
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java740
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java1620
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/WidgetClassLoader.java343
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-devices.xsd345
11 files changed, 0 insertions, 5092 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtConsoleSdkLog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtConsoleSdkLog.java
deleted file mode 100755
index 2396a4c46..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtConsoleSdkLog.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 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.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.utils.ILogger;
-
-/**
- * An {@link ILogger} logger that outputs to the ADT console.
- */
-public class AdtConsoleSdkLog implements ILogger {
-
- private static final String TAG = "SDK Manager"; //$NON-NLS-1$
-
- @Override
- public void error(@Nullable Throwable t, @Nullable String errorFormat, Object... args) {
- if (t != null) {
- AdtPlugin.logAndPrintError(t, TAG, "Error: " + errorFormat, args);
- } else {
- AdtPlugin.printErrorToConsole(TAG, String.format(errorFormat, args));
- }
- }
-
- @Override
- public void info(@NonNull String msgFormat, Object... args) {
- String msg = String.format(msgFormat, args);
- for (String s : msg.split("\n")) {
- if (s.trim().length() > 0) {
- AdtPlugin.printToConsole(TAG, s);
- }
- }
- }
-
- @Override
- public void verbose(@NonNull String msgFormat, Object... args) {
- info(msgFormat, args);
- }
-
- @Override
- public void warning(@NonNull String warningFormat, Object... args) {
- AdtPlugin.printToConsole(TAG, String.format("Warning: " + warningFormat, args));
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtManifestMergeCallback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtManifestMergeCallback.java
deleted file mode 100755
index dc539dcaa..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AdtManifestMergeCallback.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2012 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.annotations.NonNull;
-import com.android.manifmerger.ICallback;
-import com.android.manifmerger.ManifestMerger;
-import com.android.sdklib.AndroidTargetHash;
-import com.android.sdklib.AndroidVersion;
-import com.android.sdklib.IAndroidTarget;
-
-/**
- * A {@link ManifestMerger} {@link ICallback} that returns the
- * proper API level for known API codenames.
- */
-public class AdtManifestMergeCallback implements ICallback {
- @Override
- public int queryCodenameApiLevel(@NonNull String codename) {
- Sdk sdk = Sdk.getCurrent();
- if (sdk != null) {
- try {
- AndroidVersion version = new AndroidVersion(codename);
- String hashString = AndroidTargetHash.getPlatformHashString(version);
- IAndroidTarget t = sdk.getTargetFromHashString(hashString);
- if (t != null) {
- return t.getVersion().getApiLevel();
- }
- } catch (AndroidVersion.AndroidVersionException ignore) {}
- }
- return ICallback.UNKNOWN_CODENAME;
- }
-}
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
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
deleted file mode 100644
index 85ae9fdc0..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
+++ /dev/null
@@ -1,417 +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.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.rendering.LayoutLibrary;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.resources.ResourceRepository;
-import com.android.ide.common.resources.platform.AttributeInfo;
-import com.android.ide.common.sdk.LoadStatus;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
-import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ValuesDescriptors;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
-
-import org.eclipse.core.runtime.IStatus;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Map;
-
-/**
- * This class contains the data of an Android Target as loaded from the SDK.
- */
-public class AndroidTargetData {
-
- public final static int DESCRIPTOR_MANIFEST = 1;
- public final static int DESCRIPTOR_LAYOUT = 2;
- public final static int DESCRIPTOR_MENU = 3;
- public final static int DESCRIPTOR_OTHER_XML = 4;
- public final static int DESCRIPTOR_RESOURCES = 5;
- public final static int DESCRIPTOR_SEARCHABLE = 6;
- public final static int DESCRIPTOR_PREFERENCES = 7;
- public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8;
- public final static int DESCRIPTOR_DRAWABLE = 9;
- public final static int DESCRIPTOR_ANIMATOR = 10;
- public final static int DESCRIPTOR_ANIM = 11;
- public final static int DESCRIPTOR_COLOR = 12;
-
- private final IAndroidTarget mTarget;
-
- /**
- * mAttributeValues is a map { key => list [ values ] }.
- * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
- * The attribute namespace prefix must be:
- * - "android" for SdkConstants.NS_RESOURCES
- * - "xmlns" for the XMLNS URI.
- *
- * This is used for attributes that do not have a unique name, but still need to be populated
- * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}.
- */
- private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
-
- private AndroidManifestDescriptors mManifestDescriptors;
- private DrawableDescriptors mDrawableDescriptors;
- private AnimatorDescriptors mAnimatorDescriptors;
- private AnimDescriptors mAnimDescriptors;
- private ColorDescriptors mColorDescriptors;
- private LayoutDescriptors mLayoutDescriptors;
- private MenuDescriptors mMenuDescriptors;
- private OtherXmlDescriptors mOtherXmlDescriptors;
-
- private Map<String, Map<String, Integer>> mEnumValueMap;
-
- private ResourceRepository mFrameworkResources;
- private LayoutLibrary mLayoutLibrary;
- private Map<String, AttributeInfo> mAttributeMap;
-
- private boolean mLayoutBridgeInit = false;
-
- AndroidTargetData(IAndroidTarget androidTarget) {
- mTarget = androidTarget;
- }
-
- /**
- * Sets the associated map from string attribute name to
- * {@link AttributeInfo}
- *
- * @param attributeMap the map
- */
- public void setAttributeMap(@NonNull Map<String, AttributeInfo> attributeMap) {
- mAttributeMap = attributeMap;
- }
-
- /**
- * Returns the associated map from string attribute name to
- * {@link AttributeInfo}
- *
- * @return the map
- */
- @Nullable
- public Map<String, AttributeInfo> getAttributeMap() {
- return mAttributeMap;
- }
-
- /**
- * Creates an AndroidTargetData object.
- */
- void setExtraData(
- AndroidManifestDescriptors manifestDescriptors,
- LayoutDescriptors layoutDescriptors,
- MenuDescriptors menuDescriptors,
- OtherXmlDescriptors otherXmlDescriptors,
- DrawableDescriptors drawableDescriptors,
- AnimatorDescriptors animatorDescriptors,
- AnimDescriptors animDescriptors,
- ColorDescriptors colorDescriptors,
- Map<String, Map<String, Integer>> enumValueMap,
- String[] permissionValues,
- String[] activityIntentActionValues,
- String[] broadcastIntentActionValues,
- String[] serviceIntentActionValues,
- String[] intentCategoryValues,
- String[] platformLibraries,
- IOptionalLibrary[] optionalLibraries,
- ResourceRepository frameworkResources,
- LayoutLibrary layoutLibrary) {
-
- mManifestDescriptors = manifestDescriptors;
- mDrawableDescriptors = drawableDescriptors;
- mAnimatorDescriptors = animatorDescriptors;
- mAnimDescriptors = animDescriptors;
- mColorDescriptors = colorDescriptors;
- mLayoutDescriptors = layoutDescriptors;
- mMenuDescriptors = menuDescriptors;
- mOtherXmlDescriptors = otherXmlDescriptors;
- mEnumValueMap = enumValueMap;
- mFrameworkResources = frameworkResources;
- mLayoutLibrary = layoutLibrary;
-
- setPermissions(permissionValues);
- setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
- serviceIntentActionValues, intentCategoryValues);
- setOptionalLibraries(platformLibraries, optionalLibraries);
- }
-
- /**
- * Returns an {@link IDescriptorProvider} from a given Id.
- * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT},
- * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_OTHER_XML}.
- * All other values will throw an {@link IllegalArgumentException}.
- */
- public IDescriptorProvider getDescriptorProvider(int descriptorId) {
- switch (descriptorId) {
- case DESCRIPTOR_MANIFEST:
- return mManifestDescriptors;
- case DESCRIPTOR_LAYOUT:
- return mLayoutDescriptors;
- case DESCRIPTOR_MENU:
- return mMenuDescriptors;
- case DESCRIPTOR_OTHER_XML:
- return mOtherXmlDescriptors;
- case DESCRIPTOR_RESOURCES:
- // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent.
- return ValuesDescriptors.getInstance();
- case DESCRIPTOR_PREFERENCES:
- return mOtherXmlDescriptors.getPreferencesProvider();
- case DESCRIPTOR_APPWIDGET_PROVIDER:
- return mOtherXmlDescriptors.getAppWidgetProvider();
- case DESCRIPTOR_SEARCHABLE:
- return mOtherXmlDescriptors.getSearchableProvider();
- case DESCRIPTOR_DRAWABLE:
- return mDrawableDescriptors;
- case DESCRIPTOR_ANIMATOR:
- return mAnimatorDescriptors;
- case DESCRIPTOR_ANIM:
- return mAnimDescriptors;
- case DESCRIPTOR_COLOR:
- return mColorDescriptors;
- default :
- throw new IllegalArgumentException();
- }
- }
-
- /**
- * Returns the manifest descriptors.
- */
- public AndroidManifestDescriptors getManifestDescriptors() {
- return mManifestDescriptors;
- }
-
- /**
- * Returns the drawable descriptors
- */
- public DrawableDescriptors getDrawableDescriptors() {
- return mDrawableDescriptors;
- }
-
- /**
- * Returns the animation descriptors
- */
- public AnimDescriptors getAnimDescriptors() {
- return mAnimDescriptors;
- }
-
- /**
- * Returns the color descriptors
- */
- public ColorDescriptors getColorDescriptors() {
- return mColorDescriptors;
- }
-
- /**
- * Returns the animator descriptors
- */
- public AnimatorDescriptors getAnimatorDescriptors() {
- return mAnimatorDescriptors;
- }
-
- /**
- * Returns the layout Descriptors.
- */
- public LayoutDescriptors getLayoutDescriptors() {
- return mLayoutDescriptors;
- }
-
- /**
- * Returns the menu descriptors.
- */
- public MenuDescriptors getMenuDescriptors() {
- return mMenuDescriptors;
- }
-
- /**
- * Returns the XML descriptors
- */
- public OtherXmlDescriptors getXmlDescriptors() {
- return mOtherXmlDescriptors;
- }
-
- /**
- * Returns this list of possible values for an XML attribute.
- * <p/>This should only be called for attributes for which possible values depend on the
- * parent element node.
- * <p/>For attributes that have the same values no matter the parent node, use
- * {@link #getEnumValueMap()}.
- * @param elementName the name of the element containing the attribute.
- * @param attributeName the name of the attribute
- * @return an array of String with the possible values, or <code>null</code> if no values were
- * found.
- */
- public String[] getAttributeValues(String elementName, String attributeName) {
- String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
- return mAttributeValues.get(key);
- }
-
- /**
- * Returns this list of possible values for an XML attribute.
- * <p/>This should only be called for attributes for which possible values depend on the
- * parent and great-grand-parent element node.
- * <p/>The typical example of this is for the 'name' attribute under
- * activity/intent-filter/action
- * <p/>For attributes that have the same values no matter the parent node, use
- * {@link #getEnumValueMap()}.
- * @param elementName the name of the element containing the attribute.
- * @param attributeName the name of the attribute
- * @param greatGrandParentElementName the great-grand-parent node.
- * @return an array of String with the possible values, or <code>null</code> if no values were
- * found.
- */
- public String[] getAttributeValues(String elementName, String attributeName,
- String greatGrandParentElementName) {
- if (greatGrandParentElementName != null) {
- String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$
- greatGrandParentElementName, elementName, attributeName);
- String[] values = mAttributeValues.get(key);
- if (values != null) {
- return values;
- }
- }
-
- return getAttributeValues(elementName, attributeName);
- }
-
- /**
- * Returns the enum values map.
- * <p/>The map defines the possible values for XML attributes. The key is the attribute name
- * and the value is a map of (string, integer) in which the key (string) is the name of
- * the value, and the Integer is the numerical value in the compiled binary XML files.
- */
- public Map<String, Map<String, Integer>> getEnumValueMap() {
- return mEnumValueMap;
- }
-
- /**
- * Returns the {@link ProjectResources} containing the Framework Resources.
- */
- public ResourceRepository getFrameworkResources() {
- return mFrameworkResources;
- }
-
- /**
- * Returns a {@link LayoutLibrary} object possibly containing a {@link LayoutBridge} object.
- * <p/>If {@link LayoutLibrary#getBridge()} is <code>null</code>,
- * {@link LayoutBridge#getStatus()} will contain the reason (either {@link LoadStatus#LOADING}
- * or {@link LoadStatus#FAILED}).
- * <p/>Valid {@link LayoutBridge} objects are always initialized before being returned.
- */
- public synchronized LayoutLibrary getLayoutLibrary() {
- if (mLayoutBridgeInit == false && mLayoutLibrary.getStatus() == LoadStatus.LOADED) {
- boolean ok = mLayoutLibrary.init(
- mTarget.getProperties(),
- new File(mTarget.getPath(IAndroidTarget.FONTS)),
- getEnumValueMap(),
- new LayoutLog() {
-
- @Override
- public void error(String tag, String message, Throwable throwable,
- Object data) {
- AdtPlugin.log(throwable, message);
- }
-
- @Override
- public void error(String tag, String message, Object data) {
- AdtPlugin.log(IStatus.ERROR, message);
- }
-
- @Override
- public void warning(String tag, String message, Object data) {
- AdtPlugin.log(IStatus.WARNING, message);
- }
- });
- if (!ok) {
- AdtPlugin.log(IStatus.ERROR,
- "LayoutLibrary initialization failed");
- }
- mLayoutBridgeInit = true;
- }
-
- return mLayoutLibrary;
- }
-
- /**
- * Sets the permission values
- * @param permissionValues the list of permissions
- */
- private void setPermissions(String[] permissionValues) {
- setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
- setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
- }
-
- private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
- String[] broadcastIntentActions, String[] serviceIntentActions,
- String[] intentCategoryValues) {
- setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
- setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
- setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
- setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
- }
-
- private void setOptionalLibraries(String[] platformLibraries,
- IOptionalLibrary[] optionalLibraries) {
-
- ArrayList<String> libs = new ArrayList<String>();
-
- if (platformLibraries != null) {
- for (String name : platformLibraries) {
- libs.add(name);
- }
- }
-
- if (optionalLibraries != null) {
- for (int i = 0; i < optionalLibraries.length; i++) {
- libs.add(optionalLibraries[i].getName());
- }
- }
- setValues("(uses-library,android:name)", libs.toArray(new String[libs.size()]));
- }
-
- /**
- * Sets a (name, values) pair in the hash map.
- * <p/>
- * If the name is already present in the map, it is first removed.
- * @param name the name associated with the values.
- * @param values The values to add.
- */
- private void setValues(String name, String[] values) {
- mAttributeValues.remove(name);
- mAttributeValues.put(name, values);
- }
-
- public void dispose() {
- if (mLayoutLibrary != null) {
- mLayoutLibrary.dispose();
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
deleted file mode 100644
index 9a1fd3dc9..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright (C) 2008 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.android.ide.common.rendering.LayoutLibrary;
-import com.android.ide.common.resources.ResourceRepository;
-import com.android.ide.common.resources.platform.AttrsXmlParser;
-import com.android.ide.common.resources.platform.DeclareStyleableInfo;
-import com.android.ide.common.resources.platform.ViewClassInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
-import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.sdklib.IAndroidTarget;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubMonitor;
-
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.management.InvalidAttributeValueException;
-
-/**
- * Parser for the platform data in an SDK.
- * <p/>
- * This gather the following information:
- * <ul>
- * <li>Resource ID from <code>android.R</code></li>
- * <li>The list of permissions values from <code>android.Manifest$permission</code></li>
- * <li></li>
- * </ul>
- */
-public final class AndroidTargetParser {
-
- private static final String TAG = "Framework Resource Parser";
- private final IAndroidTarget mAndroidTarget;
-
- /**
- * Creates a platform data parser.
- */
- public AndroidTargetParser(IAndroidTarget platformTarget) {
- mAndroidTarget = platformTarget;
- }
-
- /**
- * Parses the framework, collects all interesting information and stores them in the
- * {@link IAndroidTarget} given to the constructor.
- *
- * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
- * @return True if the SDK path was valid and parsing has been attempted.
- */
- public IStatus run(IProgressMonitor monitor) {
- try {
- SubMonitor progress = SubMonitor.convert(monitor,
- String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
- 16);
-
- AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget);
-
- // parse the rest of the data.
-
- AndroidJarLoader classLoader =
- new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
-
- preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- // get the permissions
- progress.subTask("Permissions");
- String[] permissionValues = collectPermissions(classLoader);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- // get the action and category values for the Intents.
- progress.subTask("Intents");
- ArrayList<String> activity_actions = new ArrayList<String>();
- ArrayList<String> broadcast_actions = new ArrayList<String>();
- ArrayList<String> service_actions = new ArrayList<String>();
- ArrayList<String> categories = new ArrayList<String>();
- collectIntentFilterActionsAndCategories(activity_actions, broadcast_actions,
- service_actions, categories);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- // gather the attribute definition
- progress.subTask("Attributes definitions");
- AttrsXmlParser attrsXmlParser = new AttrsXmlParser(
- mAndroidTarget.getPath(IAndroidTarget.ATTRIBUTES),
- AdtPlugin.getDefault(),
- 1000);
- attrsXmlParser.preload();
-
- progress.worked(1);
-
- progress.subTask("Manifest definitions");
- AttrsXmlParser attrsManifestXmlParser = new AttrsXmlParser(
- mAndroidTarget.getPath(IAndroidTarget.MANIFEST_ATTRIBUTES),
- attrsXmlParser,
- AdtPlugin.getDefault(), 1100);
- attrsManifestXmlParser.preload();
- progress.worked(1);
-
- Collection<ViewClassInfo> mainList = new ArrayList<ViewClassInfo>();
- Collection<ViewClassInfo> groupList = new ArrayList<ViewClassInfo>();
-
- // collect the layout/widgets classes
- progress.subTask("Widgets and layouts");
- collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
- progress.newChild(1));
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- ViewClassInfo[] layoutViewsInfo = mainList.toArray(
- new ViewClassInfo[mainList.size()]);
- ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
- new ViewClassInfo[groupList.size()]);
- mainList.clear();
- groupList.clear();
-
- // collect the preferences classes.
- collectPreferenceClasses(classLoader, attrsXmlParser, mainList, groupList,
- progress.newChild(1));
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- ViewClassInfo[] preferencesInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
- ViewClassInfo[] preferenceGroupsInfo = groupList.toArray(
- new ViewClassInfo[groupList.size()]);
-
- Map<String, DeclareStyleableInfo> xmlMenuMap = collectMenuDefinitions(attrsXmlParser);
- Map<String, DeclareStyleableInfo> xmlSearchableMap = collectSearchableDefinitions(
- attrsXmlParser);
- Map<String, DeclareStyleableInfo> manifestMap = collectManifestDefinitions(
- attrsManifestXmlParser);
- Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
-
- Map<String, DeclareStyleableInfo> xmlAppWidgetMap = null;
- if (mAndroidTarget.getVersion().getApiLevel() >= 3) {
- xmlAppWidgetMap = collectAppWidgetDefinitions(attrsXmlParser);
- }
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- // From the information that was collected, create the pieces that will be put in
- // the PlatformData object.
- AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
- manifestDescriptors.updateDescriptors(manifestMap);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- LayoutDescriptors layoutDescriptors = new LayoutDescriptors();
- layoutDescriptors.updateDescriptors(layoutViewsInfo, layoutGroupsInfo,
- attrsXmlParser.getDeclareStyleableList(), mAndroidTarget);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- MenuDescriptors menuDescriptors = new MenuDescriptors();
- menuDescriptors.updateDescriptors(xmlMenuMap);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- OtherXmlDescriptors otherXmlDescriptors = new OtherXmlDescriptors();
- otherXmlDescriptors.updateDescriptors(
- xmlSearchableMap,
- xmlAppWidgetMap,
- preferencesInfo,
- preferenceGroupsInfo);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- DrawableDescriptors drawableDescriptors = new DrawableDescriptors();
- Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
- drawableDescriptors.updateDescriptors(map);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- AnimatorDescriptors animatorDescriptors = new AnimatorDescriptors();
- animatorDescriptors.updateDescriptors(map);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- AnimDescriptors animDescriptors = new AnimDescriptors();
- animDescriptors.updateDescriptors(map);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- ColorDescriptors colorDescriptors = new ColorDescriptors();
- colorDescriptors.updateDescriptors(map);
- progress.worked(1);
-
- // load the framework resources.
- ResourceRepository frameworkResources =
- ResourceManager.getInstance().loadFrameworkResources(mAndroidTarget);
- progress.worked(1);
-
- // now load the layout lib bridge
- LayoutLibrary layoutBridge = LayoutLibrary.load(
- mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB),
- AdtPlugin.getDefault(),
- "ADT plug-in");
-
- progress.worked(1);
-
- // and finally create the PlatformData with all that we loaded.
- targetData.setExtraData(
- manifestDescriptors,
- layoutDescriptors,
- menuDescriptors,
- otherXmlDescriptors,
- drawableDescriptors,
- animatorDescriptors,
- animDescriptors,
- colorDescriptors,
- enumValueMap,
- permissionValues,
- activity_actions.toArray(new String[activity_actions.size()]),
- broadcast_actions.toArray(new String[broadcast_actions.size()]),
- service_actions.toArray(new String[service_actions.size()]),
- categories.toArray(new String[categories.size()]),
- mAndroidTarget.getPlatformLibraries(),
- mAndroidTarget.getOptionalLibraries(),
- frameworkResources,
- layoutBridge);
-
- targetData.setAttributeMap(attrsXmlParser.getAttributeMap());
-
- Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
-
- return Status.OK_STATUS;
- } catch (Exception e) {
- AdtPlugin.logAndPrintError(e, TAG, "SDK parser failed"); //$NON-NLS-1$
- AdtPlugin.printToConsole("SDK parser failed", e.getMessage());
- return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "SDK parser failed", e);
- }
- }
-
- /**
- * Preloads all "interesting" classes from the framework SDK jar.
- * <p/>
- * Currently this preloads all classes from the framework jar
- *
- * @param classLoader The framework SDK jar classloader
- * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
- */
- private void preload(AndroidJarLoader classLoader, IProgressMonitor monitor) {
- try {
- classLoader.preLoadClasses("" /* all classes */, //$NON-NLS-1$
- mAndroidTarget.getName(), // monitor task label
- monitor);
- } catch (InvalidAttributeValueException e) {
- AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
- } catch (IOException e) {
- AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
- }
- }
-
- /**
- * Loads, collects and returns the list of default permissions from the framework.
- *
- * @param classLoader The framework SDK jar classloader
- * @return a non null (but possibly empty) array containing the permission values.
- */
- private String[] collectPermissions(AndroidJarLoader classLoader) {
- try {
- Class<?> permissionClass =
- classLoader.loadClass(SdkConstants.CLASS_MANIFEST_PERMISSION);
-
- if (permissionClass != null) {
- ArrayList<String> list = new ArrayList<String>();
-
- Field[] fields = permissionClass.getFields();
-
- for (Field f : fields) {
- int modifiers = f.getModifiers();
- if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) &&
- Modifier.isPublic(modifiers)) {
- try {
- Object value = f.get(null);
- if (value instanceof String) {
- list.add((String)value);
- }
- } catch (IllegalArgumentException e) {
- // since we provide null this should not happen
- } catch (IllegalAccessException e) {
- // if the field is inaccessible we ignore it.
- } catch (NullPointerException npe) {
- // looks like this is not a static field. we can ignore.
- } catch (ExceptionInInitializerError eiie) {
- // lets just ignore the field again
- }
- }
- }
-
- return list.toArray(new String[list.size()]);
- }
- } catch (ClassNotFoundException e) {
- AdtPlugin.logAndPrintError(e, TAG,
- "Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
- SdkConstants.CLASS_MANIFEST_PERMISSION,
- mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
- }
-
- return new String[0];
- }
-
- /**
- * Loads and collects the action and category default values from the framework.
- * The values are added to the <code>actions</code> and <code>categories</code> lists.
- *
- * @param activityActions the list which will receive the activity action values.
- * @param broadcastActions the list which will receive the broadcast action values.
- * @param serviceActions the list which will receive the service action values.
- * @param categories the list which will receive the category values.
- */
- private void collectIntentFilterActionsAndCategories(ArrayList<String> activityActions,
- ArrayList<String> broadcastActions,
- ArrayList<String> serviceActions, ArrayList<String> categories) {
- collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_ACTIVITY),
- activityActions);
- collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_BROADCAST),
- broadcastActions);
- collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_SERVICE),
- serviceActions);
- collectValues(mAndroidTarget.getPath(IAndroidTarget.CATEGORIES),
- categories);
- }
-
- /**
- * Collects values from a text file located in the SDK
- * @param osFilePath The path to the text file.
- * @param values the {@link ArrayList} to fill with the values.
- */
- private void collectValues(String osFilePath, ArrayList<String> values) {
- FileReader fr = null;
- BufferedReader reader = null;
- try {
- fr = new FileReader(osFilePath);
- reader = new BufferedReader(fr);
-
- String line;
- while ((line = reader.readLine()) != null) {
- line = line.trim();
- if (line.length() > 0 && line.startsWith("#") == false) { //$NON-NLS-1$
- values.add(line);
- }
- }
- } catch (IOException e) {
- AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
- }
-
- try {
- if (fr != null) {
- fr.close();
- }
- } catch (IOException e) {
- AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
- }
- }
- }
-
- /**
- * Collects all layout classes information from the class loader and the
- * attrs.xml and sets the corresponding structures in the resource manager.
- *
- * @param classLoader The framework SDK jar classloader in case we cannot get the widget from
- * the platform directly
- * @param attrsXmlParser The parser of the attrs.xml file
- * @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
- * @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
- * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
- */
- private void collectLayoutClasses(AndroidJarLoader classLoader,
- AttrsXmlParser attrsXmlParser,
- Collection<ViewClassInfo> mainList,
- Collection<ViewClassInfo> groupList,
- IProgressMonitor monitor) {
- LayoutParamsParser ldp = null;
- try {
- WidgetClassLoader loader = new WidgetClassLoader(
- mAndroidTarget.getPath(IAndroidTarget.WIDGETS));
- if (loader.parseWidgetList(monitor)) {
- ldp = new LayoutParamsParser(loader, attrsXmlParser);
- }
- // if the parsing failed, we'll use the old loader below.
- } catch (FileNotFoundException e) {
- AdtPlugin.log(e, "Android Framework Parser"); //$NON-NLS-1$
- // the file does not exist, we'll use the old loader below.
- }
-
- if (ldp == null) {
- ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
- }
- ldp.parseLayoutClasses(monitor);
-
- List<ViewClassInfo> views = ldp.getViews();
- List<ViewClassInfo> groups = ldp.getGroups();
-
- if (views != null && groups != null) {
- mainList.addAll(views);
- groupList.addAll(groups);
- }
- }
-
- /**
- * Collects all preferences definition information from the attrs.xml and
- * sets the corresponding structures in the resource manager.
- *
- * @param classLoader The framework SDK jar classloader
- * @param attrsXmlParser The parser of the attrs.xml file
- * @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
- * @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
- * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
- */
- private void collectPreferenceClasses(AndroidJarLoader classLoader,
- AttrsXmlParser attrsXmlParser, Collection<ViewClassInfo> mainList,
- Collection<ViewClassInfo> groupList, IProgressMonitor monitor) {
- LayoutParamsParser ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
-
- try {
- ldp.parsePreferencesClasses(monitor);
-
- List<ViewClassInfo> prefs = ldp.getViews();
- List<ViewClassInfo> groups = ldp.getGroups();
-
- if (prefs != null && groups != null) {
- mainList.addAll(prefs);
- groupList.addAll(groups);
- }
- } catch (NoClassDefFoundError e) {
- AdtPlugin.logAndPrintError(e, TAG,
- "Collect preferences failed, class %1$s not found in %2$s",
- e.getMessage(),
- classLoader.getSource());
- } catch (Throwable e) {
- AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
- AdtPlugin.printErrorToConsole("Android Framework Parser",
- "failed to collect preference classes");
- }
- }
-
- /**
- * Collects all menu definition information from the attrs.xml and returns it.
- *
- * @param attrsXmlParser The parser of the attrs.xml file
- */
- private Map<String, DeclareStyleableInfo> collectMenuDefinitions(
- AttrsXmlParser attrsXmlParser) {
- Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
- Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
- for (String key : new String[] { "Menu", //$NON-NLS-1$
- "MenuItem", //$NON-NLS-1$
- "MenuGroup" }) { //$NON-NLS-1$
- if (map.containsKey(key)) {
- map2.put(key, map.get(key));
- } else {
- AdtPlugin.log(IStatus.WARNING,
- "Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
- key, attrsXmlParser.getOsAttrsXmlPath());
- AdtPlugin.printErrorToConsole("Android Framework Parser",
- String.format("Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
- key, attrsXmlParser.getOsAttrsXmlPath()));
- }
- }
-
- return Collections.unmodifiableMap(map2);
- }
-
- /**
- * Collects all searchable definition information from the attrs.xml and returns it.
- *
- * @param attrsXmlParser The parser of the attrs.xml file
- */
- private Map<String, DeclareStyleableInfo> collectSearchableDefinitions(
- AttrsXmlParser attrsXmlParser) {
- Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
- Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
- for (String key : new String[] { "Searchable", //$NON-NLS-1$
- "SearchableActionKey" }) { //$NON-NLS-1$
- if (map.containsKey(key)) {
- map2.put(key, map.get(key));
- } else {
- AdtPlugin.log(IStatus.WARNING,
- "Searchable declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
- key, attrsXmlParser.getOsAttrsXmlPath());
- AdtPlugin.printErrorToConsole("Android Framework Parser",
- String.format("Searchable declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
- key, attrsXmlParser.getOsAttrsXmlPath()));
- }
- }
-
- return Collections.unmodifiableMap(map2);
- }
-
- /**
- * Collects all appWidgetProviderInfo definition information from the attrs.xml and returns it.
- *
- * @param attrsXmlParser The parser of the attrs.xml file
- */
- private Map<String, DeclareStyleableInfo> collectAppWidgetDefinitions(
- AttrsXmlParser attrsXmlParser) {
- Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
- Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
- for (String key : new String[] { "AppWidgetProviderInfo" }) { //$NON-NLS-1$
- if (map.containsKey(key)) {
- map2.put(key, map.get(key));
- } else {
- AdtPlugin.log(IStatus.WARNING,
- "AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
- key, attrsXmlParser.getOsAttrsXmlPath());
- AdtPlugin.printErrorToConsole("Android Framework Parser",
- String.format("AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
- key, attrsXmlParser.getOsAttrsXmlPath()));
- }
- }
-
- return Collections.unmodifiableMap(map2);
- }
-
- /**
- * Collects all manifest definition information from the attrs_manifest.xml and returns it.
- */
- private Map<String, DeclareStyleableInfo> collectManifestDefinitions(
- AttrsXmlParser attrsXmlParser) {
-
- return attrsXmlParser.getDeclareStyleableList();
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/IAndroidClassLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/IAndroidClassLoader.java
deleted file mode 100644
index ab78d2a9b..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/IAndroidClassLoader.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2008 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 java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import javax.management.InvalidAttributeValueException;
-
-/**
- * Classes which implements this interface provide methods to access framework resource
- * data loaded from the SDK.
- */
-interface IAndroidClassLoader {
-
- /**
- * Classes which implement this interface provide methods to describe a class.
- */
- public interface IClassDescriptor {
-
- String getFullClassName();
-
- IClassDescriptor getSuperclass();
-
- String getSimpleName();
-
- IClassDescriptor getEnclosingClass();
-
- IClassDescriptor[] getDeclaredClasses();
-
- boolean isInstantiable();
- }
-
- /**
- * Finds and loads all classes that derive from a given set of super classes.
- *
- * @param rootPackage Root 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
- */
- public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
- String rootPackage, String[] superClasses)
- throws IOException, InvalidAttributeValueException, ClassFormatError;
-
- /**
- * Returns a {@link IClassDescriptor} by its fully-qualified name.
- * @param className the fully-qualified name of the class to return.
- * @throws ClassNotFoundException
- */
- public IClassDescriptor getClass(String className) throws ClassNotFoundException;
-
- /**
- * Returns a string indicating the source of the classes, typically for debugging
- * or in error messages. This would typically be a JAR file name or some kind of
- * identifier that would mean something to the user when looking at error messages.
- *
- * @return An informal string representing the source of the classes.
- */
- public String getSource();
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutParamsParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutParamsParser.java
deleted file mode 100644
index d05c12a9e..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutParamsParser.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2008 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.android.ide.common.resources.platform.AttrsXmlParser;
-import com.android.ide.common.resources.platform.ViewClassInfo;
-import com.android.ide.common.resources.platform.ViewClassInfo.LayoutParamsInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.sdk.IAndroidClassLoader.IClassDescriptor;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.SubMonitor;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import javax.management.InvalidAttributeValueException;
-
-/*
- * TODO: refactor this. Could use some cleanup.
- */
-
-/**
- * Parser for the framework library.
- * <p/>
- * This gather the following information:
- * <ul>
- * <li>Resource ID from <code>android.R</code></li>
- * <li>The list of permissions values from <code>android.Manifest$permission</code></li>
- * <li></li>
- * </ul>
- */
-public class LayoutParamsParser {
-
- /**
- * Class extending {@link ViewClassInfo} by adding the notion of instantiability.
- * {@link LayoutParamsParser#getViews()} and {@link LayoutParamsParser#getGroups()} should
- * only return classes that can be instantiated.
- */
- final static class ExtViewClassInfo extends ViewClassInfo {
-
- private boolean mIsInstantiable;
-
- ExtViewClassInfo(boolean instantiable, boolean isLayout, String canonicalClassName,
- String shortClassName) {
- super(isLayout, canonicalClassName, shortClassName);
- mIsInstantiable = instantiable;
- }
-
- boolean isInstantiable() {
- return mIsInstantiable;
- }
- }
-
- /* Note: protected members/methods are overridden in unit tests */
-
- /** Reference to android.view.View */
- protected IClassDescriptor mTopViewClass;
- /** Reference to android.view.ViewGroup */
- protected IClassDescriptor mTopGroupClass;
- /** Reference to android.view.ViewGroup$LayoutParams */
- protected IClassDescriptor mTopLayoutParamsClass;
-
- /** Input list of all classes deriving from android.view.View */
- protected ArrayList<IClassDescriptor> mViewList;
- /** Input list of all classes deriving from android.view.ViewGroup */
- protected ArrayList<IClassDescriptor> mGroupList;
-
- /** Output map of FQCN => info on View classes */
- protected TreeMap<String, ExtViewClassInfo> mViewMap;
- /** Output map of FQCN => info on ViewGroup classes */
- protected TreeMap<String, ExtViewClassInfo> mGroupMap;
- /** Output map of FQCN => info on LayoutParams classes */
- protected HashMap<String, LayoutParamsInfo> mLayoutParamsMap;
-
- /** The attrs.xml parser */
- protected AttrsXmlParser mAttrsXmlParser;
-
- /** The android.jar class loader */
- protected IAndroidClassLoader mClassLoader;
-
- /**
- * Instantiate a new LayoutParamsParser.
- * @param classLoader The android.jar class loader
- * @param attrsXmlParser The parser of the attrs.xml file
- */
- public LayoutParamsParser(IAndroidClassLoader classLoader,
- AttrsXmlParser attrsXmlParser) {
- mClassLoader = classLoader;
- mAttrsXmlParser = attrsXmlParser;
- }
-
- /** Returns the map of FQCN => info on View classes */
- public List<ViewClassInfo> getViews() {
- return getInstantiables(mViewMap);
- }
-
- /** Returns the map of FQCN => info on ViewGroup classes */
- public List<ViewClassInfo> getGroups() {
- return getInstantiables(mGroupMap);
- }
-
- /**
- * TODO: doc here.
- * <p/>
- * Note: on output we should have NO dependency on {@link IClassDescriptor},
- * otherwise we wouldn't be able to unload the class loader later.
- * <p/>
- * Note on Vocabulary: FQCN=Fully Qualified Class Name (e.g. "my.package.class$innerClass")
- * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
- */
- public void parseLayoutClasses(IProgressMonitor monitor) {
- parseClasses(monitor,
- SdkConstants.CLASS_VIEW,
- SdkConstants.CLASS_VIEWGROUP,
- SdkConstants.CLASS_VIEWGROUP_LAYOUTPARAMS);
- }
-
- public void parsePreferencesClasses(IProgressMonitor monitor) {
- parseClasses(monitor,
- SdkConstants.CLASS_PREFERENCE,
- SdkConstants.CLASS_PREFERENCEGROUP,
- null /* paramsClassName */ );
- }
-
- private void parseClasses(IProgressMonitor monitor,
- String rootClassName,
- String groupClassName,
- String paramsClassName) {
- try {
- SubMonitor progress = SubMonitor.convert(monitor, 100);
-
- String[] superClasses = new String[2 + (paramsClassName == null ? 0 : 1)];
- superClasses[0] = groupClassName;
- superClasses[1] = rootClassName;
- if (paramsClassName != null) {
- superClasses[2] = paramsClassName;
- }
- HashMap<String, ArrayList<IClassDescriptor>> found =
- mClassLoader.findClassesDerivingFrom("android.", superClasses); //$NON-NLS-1$
- mTopViewClass = mClassLoader.getClass(rootClassName);
- mTopGroupClass = mClassLoader.getClass(groupClassName);
- if (paramsClassName != null) {
- mTopLayoutParamsClass = mClassLoader.getClass(paramsClassName);
- }
-
- mViewList = found.get(rootClassName);
- mGroupList = found.get(groupClassName);
-
- mViewMap = new TreeMap<String, ExtViewClassInfo>();
- mGroupMap = new TreeMap<String, ExtViewClassInfo>();
- if (mTopLayoutParamsClass != null) {
- mLayoutParamsMap = new HashMap<String, LayoutParamsInfo>();
- }
-
- // Add top classes to the maps since by design they are not listed in classes deriving
- // from themselves.
- if (mTopGroupClass != null) {
- addGroup(mTopGroupClass);
- }
- if (mTopViewClass != null) {
- addView(mTopViewClass);
- }
-
- // ViewGroup derives from View
- ExtViewClassInfo vg = mGroupMap.get(groupClassName);
- if (vg != null) {
- vg.setSuperClass(mViewMap.get(rootClassName));
- }
-
- progress.setWorkRemaining(mGroupList.size() + mViewList.size());
-
- for (IClassDescriptor groupChild : mGroupList) {
- addGroup(groupChild);
- progress.worked(1);
- }
-
- for (IClassDescriptor viewChild : mViewList) {
- if (viewChild != mTopGroupClass) {
- addView(viewChild);
- }
- progress.worked(1);
- }
- } catch (ClassNotFoundException e) {
- AdtPlugin.log(e, "Problem loading class %1$s or %2$s", //$NON-NLS-1$
- rootClassName, groupClassName);
- } catch (InvalidAttributeValueException e) {
- AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
- } catch (ClassFormatError e) {
- AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
- } catch (IOException e) {
- AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
- }
- }
-
- /**
- * Parses a View class and adds a ExtViewClassInfo for it in mViewMap.
- * It calls itself recursively to handle super classes which are also Views.
- */
- private ExtViewClassInfo addView(IClassDescriptor viewClass) {
- String fqcn = viewClass.getFullClassName();
- if (mViewMap.containsKey(fqcn)) {
- return mViewMap.get(fqcn);
- } else if (mGroupMap.containsKey(fqcn)) {
- return mGroupMap.get(fqcn);
- }
-
- ExtViewClassInfo info = new ExtViewClassInfo(viewClass.isInstantiable(),
- false /* layout */, fqcn, viewClass.getSimpleName());
- mViewMap.put(fqcn, info);
-
- // All view classes derive from mTopViewClass by design.
- // Do not lookup the super class for mTopViewClass itself.
- if (viewClass.equals(mTopViewClass) == false) {
- IClassDescriptor superClass = viewClass.getSuperclass();
- ExtViewClassInfo superClassInfo = addView(superClass);
- info.setSuperClass(superClassInfo);
- }
-
- mAttrsXmlParser.loadViewAttributes(info);
- return info;
- }
-
- /**
- * Parses a ViewGroup class and adds a ExtViewClassInfo for it in mGroupMap.
- * It calls itself recursively to handle super classes which are also ViewGroups.
- */
- private ExtViewClassInfo addGroup(IClassDescriptor groupClass) {
- String fqcn = groupClass.getFullClassName();
- if (mGroupMap.containsKey(fqcn)) {
- return mGroupMap.get(fqcn);
- }
-
- ExtViewClassInfo info = new ExtViewClassInfo(groupClass.isInstantiable(),
- true /* layout */, fqcn, groupClass.getSimpleName());
- mGroupMap.put(fqcn, info);
-
- // All groups derive from android.view.ViewGroup, which in turns derives from
- // android.view.View (i.e. mTopViewClass here). So the only group that can have View as
- // its super class is the ViewGroup base class and we don't try to resolve it since groups
- // are loaded before views.
- IClassDescriptor superClass = groupClass.getSuperclass();
-
- // Assertion: at this point, we should have
- // superClass != mTopViewClass || fqcn.equals(SdkConstants.CLASS_VIEWGROUP);
-
- if (superClass != null && superClass.equals(mTopViewClass) == false) {
- ExtViewClassInfo superClassInfo = addGroup(superClass);
-
- // Assertion: we should have superClassInfo != null && superClassInfo != info;
- if (superClassInfo != null && superClassInfo != info) {
- info.setSuperClass(superClassInfo);
- }
- }
-
- mAttrsXmlParser.loadViewAttributes(info);
- if (mTopLayoutParamsClass != null) {
- info.setLayoutParams(addLayoutParams(groupClass));
- }
- return info;
- }
-
- /**
- * Parses a ViewGroup class and returns an info object on its inner LayoutParams.
- *
- * @return The {@link LayoutParamsInfo} for the ViewGroup class or null.
- */
- private LayoutParamsInfo addLayoutParams(IClassDescriptor groupClass) {
-
- // Is there a LayoutParams in this group class?
- IClassDescriptor layoutParamsClass = findLayoutParams(groupClass);
-
- // if there's no layout data in the group class, link to the one from the
- // super class.
- if (layoutParamsClass == null) {
- for (IClassDescriptor superClass = groupClass.getSuperclass();
- layoutParamsClass == null &&
- superClass != null &&
- superClass.equals(mTopViewClass) == false;
- superClass = superClass.getSuperclass()) {
- layoutParamsClass = findLayoutParams(superClass);
- }
- }
-
- if (layoutParamsClass != null) {
- return getLayoutParamsInfo(layoutParamsClass);
- }
-
- return null;
- }
-
- /**
- * Parses a LayoutParams class and returns a LayoutParamsInfo object for it.
- * It calls itself recursively to handle the super class of the LayoutParams.
- */
- private LayoutParamsInfo getLayoutParamsInfo(IClassDescriptor layoutParamsClass) {
- String fqcn = layoutParamsClass.getFullClassName();
- LayoutParamsInfo layoutParamsInfo = mLayoutParamsMap.get(fqcn);
-
- if (layoutParamsInfo != null) {
- return layoutParamsInfo;
- }
-
- // Find the link on the LayoutParams super class
- LayoutParamsInfo superClassInfo = null;
- if (layoutParamsClass.equals(mTopLayoutParamsClass) == false) {
- IClassDescriptor superClass = layoutParamsClass.getSuperclass();
- superClassInfo = getLayoutParamsInfo(superClass);
- }
-
- // Find the link on the enclosing ViewGroup
- ExtViewClassInfo enclosingGroupInfo = addGroup(layoutParamsClass.getEnclosingClass());
-
- layoutParamsInfo = new ExtViewClassInfo.LayoutParamsInfo(
- enclosingGroupInfo, layoutParamsClass.getSimpleName(), superClassInfo);
- mLayoutParamsMap.put(fqcn, layoutParamsInfo);
-
- mAttrsXmlParser.loadLayoutParamsAttributes(layoutParamsInfo);
-
- return layoutParamsInfo;
- }
-
- /**
- * Given a ViewGroup-derived class, looks for an inner class named LayoutParams
- * and if found returns its class definition.
- * <p/>
- * This uses the actual defined inner classes and does not look at inherited classes.
- *
- * @param groupClass The ViewGroup derived class
- * @return The Class of the inner LayoutParams or null if none is declared.
- */
- private IClassDescriptor findLayoutParams(IClassDescriptor groupClass) {
- IClassDescriptor[] innerClasses = groupClass.getDeclaredClasses();
- for (IClassDescriptor innerClass : innerClasses) {
- if (innerClass.getSimpleName().equals(SdkConstants.CLASS_NAME_LAYOUTPARAMS)) {
- return innerClass;
- }
- }
- return null;
- }
-
- /**
- * Computes and return a list of ViewClassInfo from a map by filtering out the class that
- * cannot be instantiated.
- */
- private List<ViewClassInfo> getInstantiables(SortedMap<String, ExtViewClassInfo> map) {
- Collection<ExtViewClassInfo> values = map.values();
- ArrayList<ViewClassInfo> list = new ArrayList<ViewClassInfo>();
-
- for (ExtViewClassInfo info : values) {
- if (info.isInstantiable()) {
- list.add(info);
- }
- }
-
- return list;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
deleted file mode 100644
index 74c985784..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Copyright (C) 2010 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.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-
-/**
- * Centralized state for Android Eclipse project.
- * <p>This gives raw access to the properties (from <code>project.properties</code>), as well
- * as direct access to target and library information.
- *
- * This also gives access to library information.
- *
- * {@link #isLibrary()} indicates if the project is a library.
- * {@link #hasLibraries()} and {@link #getLibraries()} give access to the libraries through
- * instances of {@link LibraryState}. A {@link LibraryState} instance is a link between a main
- * project and its library. Theses instances are owned by the {@link ProjectState}.
- *
- * {@link #isMissingLibraries()} will indicate if the project has libraries that are not resolved.
- * Unresolved libraries are libraries that do not have any matching opened Eclipse project.
- * When there are missing libraries, the {@link LibraryState} instance for them will return null
- * for {@link LibraryState#getProjectState()}.
- *
- */
-public final class ProjectState {
-
- /**
- * A class that represents a library linked to a project.
- * <p/>It does not represent the library uniquely. Instead the {@link LibraryState} is linked
- * to the main project which is accessible through {@link #getMainProjectState()}.
- * <p/>If a library is used by two different projects, then there will be two different
- * instances of {@link LibraryState} for the library.
- *
- * @see ProjectState#getLibrary(IProject)
- */
- public final class LibraryState {
- private String mRelativePath;
- private ProjectState mProjectState;
- private String mPath;
-
- private LibraryState(String relativePath) {
- mRelativePath = relativePath;
- }
-
- /**
- * Returns the {@link ProjectState} of the main project using this library.
- */
- public ProjectState getMainProjectState() {
- return ProjectState.this;
- }
-
- /**
- * Closes the library. This resets the IProject from this object ({@link #getProjectState()} will
- * return <code>null</code>), and updates the main project data so that the library
- * {@link IProject} object does not show up in the return value of
- * {@link ProjectState#getFullLibraryProjects()}.
- */
- public void close() {
- mProjectState.removeParentProject(getMainProjectState());
- mProjectState = null;
- mPath = null;
-
- getMainProjectState().updateFullLibraryList();
- }
-
- private void setRelativePath(String relativePath) {
- mRelativePath = relativePath;
- }
-
- private void setProject(ProjectState project) {
- mProjectState = project;
- mPath = project.getProject().getLocation().toOSString();
- mProjectState.addParentProject(getMainProjectState());
-
- getMainProjectState().updateFullLibraryList();
- }
-
- /**
- * Returns the relative path of the library from the main project.
- * <p/>This is identical to the value defined in the main project's project.properties.
- */
- public String getRelativePath() {
- return mRelativePath;
- }
-
- /**
- * Returns the {@link ProjectState} item for the library. This can be null if the project
- * is not actually opened in Eclipse.
- */
- public ProjectState getProjectState() {
- return mProjectState;
- }
-
- /**
- * Returns the OS-String location of the library project.
- * <p/>This is based on location of the Eclipse project that matched
- * {@link #getRelativePath()}.
- *
- * @return The project location, or null if the project is not opened in Eclipse.
- */
- public String getProjectLocation() {
- return mPath;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof LibraryState) {
- // the only thing that's always non-null is the relative path.
- LibraryState objState = (LibraryState)obj;
- return mRelativePath.equals(objState.mRelativePath) &&
- getMainProjectState().equals(objState.getMainProjectState());
- } else if (obj instanceof ProjectState || obj instanceof IProject) {
- return mProjectState != null && mProjectState.equals(obj);
- } else if (obj instanceof String) {
- return normalizePath(mRelativePath).equals(normalizePath((String) obj));
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return normalizePath(mRelativePath).hashCode();
- }
- }
-
- private final IProject mProject;
- private final ProjectProperties mProperties;
- private IAndroidTarget mTarget;
- private BuildToolInfo mBuildToolInfo;
-
- /**
- * list of libraries. Access to this list must be protected by
- * <code>synchronized(mLibraries)</code>, but it is important that such code do not call
- * out to other classes (especially those protected by {@link Sdk#getLock()}.)
- */
- private final ArrayList<LibraryState> mLibraries = new ArrayList<LibraryState>();
- /** Cached list of all IProject instances representing the resolved libraries, including
- * indirect dependencies. This must never be null. */
- private List<IProject> mLibraryProjects = Collections.emptyList();
- /**
- * List of parent projects. When this instance is a library ({@link #isLibrary()} returns
- * <code>true</code>) then this is filled with projects that depends on this project.
- */
- private final ArrayList<ProjectState> mParentProjects = new ArrayList<ProjectState>();
-
- ProjectState(IProject project, ProjectProperties properties) {
- if (project == null || properties == null) {
- throw new NullPointerException();
- }
-
- mProject = project;
- mProperties = properties;
-
- // load the libraries
- synchronized (mLibraries) {
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = mProperties.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- mLibraries.add(new LibraryState(convertPath(rootPath)));
- }
- }
- }
-
- public IProject getProject() {
- return mProject;
- }
-
- public ProjectProperties getProperties() {
- return mProperties;
- }
-
- public @Nullable String getProperty(@NonNull String name) {
- if (mProperties != null) {
- return mProperties.getProperty(name);
- }
-
- return null;
- }
-
- public void setTarget(IAndroidTarget target) {
- mTarget = target;
- }
-
- /**
- * Returns the project's target's hash string.
- * <p/>If {@link #getTarget()} returns a valid object, then this returns the value of
- * {@link IAndroidTarget#hashString()}.
- * <p/>Otherwise this will return the value of the property
- * {@link ProjectProperties#PROPERTY_TARGET} from {@link #getProperties()} (if valid).
- * @return the target hash string or null if not found.
- */
- public String getTargetHashString() {
- if (mTarget != null) {
- return mTarget.hashString();
- }
-
- return mProperties.getProperty(ProjectProperties.PROPERTY_TARGET);
- }
-
- public IAndroidTarget getTarget() {
- return mTarget;
- }
-
- public void setBuildToolInfo(BuildToolInfo buildToolInfo) {
- mBuildToolInfo = buildToolInfo;
- }
-
- public BuildToolInfo getBuildToolInfo() {
- return mBuildToolInfo;
- }
-
- /**
- * Returns the build tools version from the project's properties.
- * @return the value or null
- */
- @Nullable
- public String getBuildToolInfoVersion() {
- return mProperties.getProperty(ProjectProperties.PROPERTY_BUILD_TOOLS);
- }
-
- public boolean getRenderScriptSupportMode() {
- String supportModeValue = mProperties.getProperty(ProjectProperties.PROPERTY_RS_SUPPORT);
- if (supportModeValue != null) {
- return Boolean.parseBoolean(supportModeValue);
- }
-
- return false;
- }
-
- public static class LibraryDifference {
- public boolean removed = false;
- public boolean added = false;
-
- public boolean hasDiff() {
- return removed || added;
- }
- }
-
- /**
- * Reloads the content of the properties.
- * <p/>This also reset the reference to the target as it may have changed, therefore this
- * should be followed by a call to {@link Sdk#loadTarget(ProjectState)}.
- *
- * <p/>If the project libraries changes, they are updated to a certain extent.<br>
- * Removed libraries are removed from the state list, and added to the {@link LibraryDifference}
- * object that is returned so that they can be processed.<br>
- * Added libraries are added to the state (as new {@link LibraryState} objects), but their
- * IProject is not resolved. {@link ProjectState#needs(ProjectState)} should be called
- * afterwards to properly initialize the libraries.
- *
- * @return an instance of {@link LibraryDifference} describing the change in libraries.
- */
- public LibraryDifference reloadProperties() {
- mTarget = null;
- mProperties.reload();
-
- // compare/reload the libraries.
-
- // if the order change it won't impact the java part, so instead try to detect removed/added
- // libraries.
-
- LibraryDifference diff = new LibraryDifference();
-
- synchronized (mLibraries) {
- List<LibraryState> oldLibraries = new ArrayList<LibraryState>(mLibraries);
- mLibraries.clear();
-
- // load the libraries
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = mProperties.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- // search for a library with the same path (not exact same string, but going
- // to the same folder).
- String convertedPath = convertPath(rootPath);
- boolean found = false;
- for (int i = 0 ; i < oldLibraries.size(); i++) {
- LibraryState libState = oldLibraries.get(i);
- if (libState.equals(convertedPath)) {
- // it's a match. move it back to mLibraries and remove it from the
- // old library list.
- found = true;
- mLibraries.add(libState);
- oldLibraries.remove(i);
- break;
- }
- }
-
- if (found == false) {
- diff.added = true;
- mLibraries.add(new LibraryState(convertedPath));
- }
- }
-
- // whatever's left in oldLibraries is removed.
- diff.removed = oldLibraries.size() > 0;
-
- // update the library with what IProjet are known at the time.
- updateFullLibraryList();
- }
-
- return diff;
- }
-
- /**
- * Returns the list of {@link LibraryState}.
- */
- public List<LibraryState> getLibraries() {
- synchronized (mLibraries) {
- return Collections.unmodifiableList(mLibraries);
- }
- }
-
- /**
- * Returns all the <strong>resolved</strong> library projects, including indirect dependencies.
- * The list is ordered to match the library priority order for resource processing with
- * <code>aapt</code>.
- * <p/>If some dependencies are not resolved (or their projects is not opened in Eclipse),
- * they will not show up in this list.
- * @return the resolved projects as an unmodifiable list. May be an empty.
- */
- public List<IProject> getFullLibraryProjects() {
- return mLibraryProjects;
- }
-
- /**
- * Returns whether this is a library project.
- */
- public boolean isLibrary() {
- String value = mProperties.getProperty(ProjectProperties.PROPERTY_LIBRARY);
- return value != null && Boolean.valueOf(value);
- }
-
- /**
- * Returns whether the project depends on one or more libraries.
- */
- public boolean hasLibraries() {
- synchronized (mLibraries) {
- return mLibraries.size() > 0;
- }
- }
-
- /**
- * Returns whether the project is missing some required libraries.
- */
- public boolean isMissingLibraries() {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state.getProjectState() == null) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Returns the {@link LibraryState} object for a given {@link IProject}.
- * </p>This can only return a non-null object if the link between the main project's
- * {@link IProject} and the library's {@link IProject} was done.
- *
- * @return the matching LibraryState or <code>null</code>
- *
- * @see #needs(ProjectState)
- */
- public LibraryState getLibrary(IProject library) {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- ProjectState ps = state.getProjectState();
- if (ps != null && ps.getProject().equals(library)) {
- return state;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns the {@link LibraryState} object for a given <var>name</var>.
- * </p>This can only return a non-null object if the link between the main project's
- * {@link IProject} and the library's {@link IProject} was done.
- *
- * @return the matching LibraryState or <code>null</code>
- *
- * @see #needs(IProject)
- */
- public LibraryState getLibrary(String name) {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- ProjectState ps = state.getProjectState();
- if (ps != null && ps.getProject().getName().equals(name)) {
- return state;
- }
- }
- }
-
- return null;
- }
-
-
- /**
- * Returns whether a given library project is needed by the receiver.
- * <p/>If the library is needed, this finds the matching {@link LibraryState}, initializes it
- * so that it contains the library's {@link IProject} object (so that
- * {@link LibraryState#getProjectState()} does not return null) and then returns it.
- *
- * @param libraryProject the library project to check.
- * @return a non null object if the project is a library dependency,
- * <code>null</code> otherwise.
- *
- * @see LibraryState#getProjectState()
- */
- public LibraryState needs(ProjectState libraryProject) {
- // compute current location
- File projectFile = mProject.getLocation().toFile();
-
- // get the location of the library.
- File libraryFile = libraryProject.getProject().getLocation().toFile();
-
- // loop on all libraries and check if the path match
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state.getProjectState() == null) {
- File library = new File(projectFile, state.getRelativePath());
- try {
- File absPath = library.getCanonicalFile();
- if (absPath.equals(libraryFile)) {
- state.setProject(libraryProject);
- return state;
- }
- } catch (IOException e) {
- // ignore this library
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns whether the project depends on a given <var>library</var>
- * @param library the library to check.
- * @return true if the project depends on the library. This is not affected by whether the link
- * was done through {@link #needs(ProjectState)}.
- */
- public boolean dependsOn(ProjectState library) {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state != null && state.getProjectState() != null &&
- library.getProject().equals(state.getProjectState().getProject())) {
- return true;
- }
- }
- }
-
- return false;
- }
-
-
- /**
- * Updates a library with a new path.
- * <p/>This method acts both as a check and an action. If the project does not depend on the
- * given <var>oldRelativePath</var> then no action is done and <code>null</code> is returned.
- * <p/>If the project depends on the library, then the project is updated with the new path,
- * and the {@link LibraryState} for the library is returned.
- * <p/>Updating the project does two things:<ul>
- * <li>Update LibraryState with new relative path and new {@link IProject} object.</li>
- * <li>Update the main project's <code>project.properties</code> with the new relative path
- * for the changed library.</li>
- * </ul>
- *
- * @param oldRelativePath the old library path relative to this project
- * @param newRelativePath the new library path relative to this project
- * @param newLibraryState the new {@link ProjectState} object.
- * @return a non null object if the project depends on the library.
- *
- * @see LibraryState#getProjectState()
- */
- public LibraryState updateLibrary(String oldRelativePath, String newRelativePath,
- ProjectState newLibraryState) {
- // compute current location
- File projectFile = mProject.getLocation().toFile();
-
- // loop on all libraries and check if the path matches
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state.getProjectState() == null) {
- try {
- // oldRelativePath may not be the same exact string as the
- // one in the project properties (trailing separator could be different
- // for instance).
- // Use java.io.File to deal with this and also do a platform-dependent
- // path comparison
- File library1 = new File(projectFile, oldRelativePath);
- File library2 = new File(projectFile, state.getRelativePath());
- if (library1.getCanonicalPath().equals(library2.getCanonicalPath())) {
- // save the exact property string to replace.
- String oldProperty = state.getRelativePath();
-
- // then update the LibraryPath.
- state.setRelativePath(newRelativePath);
- state.setProject(newLibraryState);
-
- // update the project.properties file
- IStatus status = replaceLibraryProperty(oldProperty, newRelativePath);
- if (status != null) {
- if (status.getSeverity() != IStatus.OK) {
- // log the error somehow.
- }
- } else {
- // This should not happen since the library wouldn't be here in the
- // first place
- }
-
- // return the LibraryState object.
- return state;
- }
- } catch (IOException e) {
- // ignore this library
- }
- }
- }
- }
-
- return null;
- }
-
-
- private void addParentProject(ProjectState parentState) {
- mParentProjects.add(parentState);
- }
-
- private void removeParentProject(ProjectState parentState) {
- mParentProjects.remove(parentState);
- }
-
- public List<ProjectState> getParentProjects() {
- return Collections.unmodifiableList(mParentProjects);
- }
-
- /**
- * Computes the transitive closure of projects referencing this project as a
- * library project
- *
- * @return a collection (in any order) of project states for projects that
- * directly or indirectly include this project state's project as a
- * library project
- */
- public Collection<ProjectState> getFullParentProjects() {
- Set<ProjectState> result = new HashSet<ProjectState>();
- addParentProjects(result, this);
- return result;
- }
-
- /** Adds all parent projects of the given project, transitively, into the given parent set */
- private static void addParentProjects(Set<ProjectState> parents, ProjectState state) {
- for (ProjectState s : state.mParentProjects) {
- if (!parents.contains(s)) {
- parents.add(s);
- addParentProjects(parents, s);
- }
- }
- }
-
- /**
- * Update the value of a library dependency.
- * <p/>This loops on all current dependency looking for the value to replace and then replaces
- * it.
- * <p/>This both updates the in-memory {@link #mProperties} values and on-disk
- * project.properties file.
- * @param oldValue the old value to replace
- * @param newValue the new value to set.
- * @return the status of the replacement. If null, no replacement was done (value not found).
- */
- private IStatus replaceLibraryProperty(String oldValue, String newValue) {
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = mProperties.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- if (rootPath.equals(oldValue)) {
- // need to update the properties. Get a working copy to change it and save it on
- // disk since ProjectProperties is read-only.
- ProjectPropertiesWorkingCopy workingCopy = mProperties.makeWorkingCopy();
- workingCopy.setProperty(propName, newValue);
- try {
- workingCopy.save();
-
- // reload the properties with the new values from the disk.
- mProperties.reload();
- } catch (Exception e) {
- return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, String.format(
- "Failed to save %1$s for project %2$s",
- mProperties.getType() .getFilename(), mProject.getName()),
- e);
-
- }
- return Status.OK_STATUS;
- }
- }
-
- return null;
- }
-
- /**
- * Update the full library list, including indirect dependencies. The result is returned by
- * {@link #getFullLibraryProjects()}.
- */
- void updateFullLibraryList() {
- ArrayList<IProject> list = new ArrayList<IProject>();
- synchronized (mLibraries) {
- buildFullLibraryDependencies(mLibraries, list);
- }
-
- mLibraryProjects = Collections.unmodifiableList(list);
- }
-
- /**
- * Resolves a given list of libraries, finds out if they depend on other libraries, and
- * returns a full list of all the direct and indirect dependencies in the proper order (first
- * is higher priority when calling aapt).
- * @param inLibraries the libraries to resolve
- * @param outLibraries where to store all the libraries.
- */
- private void buildFullLibraryDependencies(List<LibraryState> inLibraries,
- ArrayList<IProject> outLibraries) {
- // loop in the inverse order to resolve dependencies on the libraries, so that if a library
- // is required by two higher level libraries it can be inserted in the correct place
- for (int i = inLibraries.size() - 1 ; i >= 0 ; i--) {
- LibraryState library = inLibraries.get(i);
-
- // get its libraries if possible
- ProjectState libProjectState = library.getProjectState();
- if (libProjectState != null) {
- List<LibraryState> dependencies = libProjectState.getLibraries();
-
- // build the dependencies for those libraries
- buildFullLibraryDependencies(dependencies, outLibraries);
-
- // and add the current library (if needed) in front (higher priority)
- if (outLibraries.contains(libProjectState.getProject()) == false) {
- outLibraries.add(0, libProjectState.getProject());
- }
- }
- }
- }
-
-
- /**
- * Converts a path containing only / by the proper platform separator.
- */
- private String convertPath(String path) {
- return path.replaceAll("/", Matcher.quoteReplacement(File.separator)); //$NON-NLS-1$
- }
-
- /**
- * Normalizes a relative path.
- */
- private String normalizePath(String path) {
- path = convertPath(path);
- if (path.endsWith("/")) { //$NON-NLS-1$
- path = path.substring(0, path.length() - 1);
- }
- return path;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof ProjectState) {
- return mProject.equals(((ProjectState) obj).mProject);
- } else if (obj instanceof IProject) {
- return mProject.equals(obj);
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return mProject.hashCode();
- }
-
- @Override
- public String toString() {
- return mProject.getName();
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
deleted file mode 100644
index 7ff06fc40..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
+++ /dev/null
@@ -1,1620 +0,0 @@
-/*
- * Copyright (C) 2008 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 static com.android.SdkConstants.DOT_XML;
-import static com.android.SdkConstants.EXT_JAR;
-import static com.android.SdkConstants.FD_RES;
-
-import com.android.SdkConstants;
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ddmlib.IDevice;
-import com.android.ide.common.rendering.LayoutLibrary;
-import com.android.ide.common.sdk.LoadStatus;
-import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.DexWrapper;
-import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
-import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.LibraryClasspathContainerInitializer;
-import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IProjectListener;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IResourceEventListener;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryDifference;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState;
-import com.android.io.StreamException;
-import com.android.prefs.AndroidLocation.AndroidLocationException;
-import com.android.sdklib.AndroidVersion;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.SdkManager;
-import com.android.sdklib.devices.DeviceManager;
-import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
-import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy;
-import com.android.sdklib.repository.FullRevision;
-import com.android.utils.ILogger;
-import com.google.common.collect.Maps;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.IMarkerDelta;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IncrementalProjectBuilder;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.ui.IEditorDescriptor;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IEditorReference;
-import org.eclipse.ui.IFileEditorInput;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.IWorkbenchPartSite;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.ide.IDE;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
- * at the same time.
- *
- * To start using an SDK, call {@link #loadSdk(String)} which returns the instance of
- * the Sdk object.
- *
- * To get the list of platforms or add-ons present in the SDK, call {@link #getTargets()}.
- */
-public final class Sdk {
- private final static boolean DEBUG = false;
-
- private final static Object LOCK = new Object();
-
- private static Sdk sCurrentSdk = null;
-
- /**
- * Map associating {@link IProject} and their state {@link ProjectState}.
- * <p/>This <b>MUST NOT</b> be accessed directly. Instead use {@link #getProjectState(IProject)}.
- */
- private final static HashMap<IProject, ProjectState> sProjectStateMap =
- new HashMap<IProject, ProjectState>();
-
- /**
- * Data bundled using during the load of Target data.
- * <p/>This contains the {@link LoadStatus} and a list of projects that attempted
- * to compile before the loading was finished. Those projects will be recompiled
- * at the end of the loading.
- */
- private final static class TargetLoadBundle {
- LoadStatus status;
- final HashSet<IJavaProject> projectsToReload = new HashSet<IJavaProject>();
- }
-
- private final SdkManager mManager;
- private final Map<String, DexWrapper> mDexWrappers = Maps.newHashMap();
- private final AvdManager mAvdManager;
- private final DeviceManager mDeviceManager;
-
- /** Map associating an {@link IAndroidTarget} to an {@link AndroidTargetData} */
- private final HashMap<IAndroidTarget, AndroidTargetData> mTargetDataMap =
- new HashMap<IAndroidTarget, AndroidTargetData>();
- /** Map associating an {@link IAndroidTarget} and its {@link TargetLoadBundle}. */
- private final HashMap<IAndroidTarget, TargetLoadBundle> mTargetDataStatusMap =
- new HashMap<IAndroidTarget, TargetLoadBundle>();
-
- /**
- * If true the target data will never load anymore. The only way to reload them is to
- * completely reload the SDK with {@link #loadSdk(String)}
- */
- private boolean mDontLoadTargetData = false;
-
- private final String mDocBaseUrl;
-
- /**
- * Classes implementing this interface will receive notification when targets are changed.
- */
- public interface ITargetChangeListener {
- /**
- * Sent when project has its target changed.
- */
- void onProjectTargetChange(IProject changedProject);
-
- /**
- * Called when the targets are loaded (either the SDK finished loading when Eclipse starts,
- * or the SDK is changed).
- */
- void onTargetLoaded(IAndroidTarget target);
-
- /**
- * Called when the base content of the SDK is parsed.
- */
- void onSdkLoaded();
- }
-
- /**
- * Basic abstract implementation of the ITargetChangeListener for the case where both
- * {@link #onProjectTargetChange(IProject)} and {@link #onTargetLoaded(IAndroidTarget)}
- * use the same code based on a simple test requiring to know the current IProject.
- */
- public static abstract class TargetChangeListener implements ITargetChangeListener {
- /**
- * Returns the {@link IProject} associated with the listener.
- */
- public abstract IProject getProject();
-
- /**
- * Called when the listener needs to take action on the event. This is only called
- * if {@link #getProject()} and the {@link IAndroidTarget} associated with the project
- * match the values received in {@link #onProjectTargetChange(IProject)} and
- * {@link #onTargetLoaded(IAndroidTarget)}.
- */
- public abstract void reload();
-
- @Override
- public void onProjectTargetChange(IProject changedProject) {
- if (changedProject != null && changedProject.equals(getProject())) {
- reload();
- }
- }
-
- @Override
- public void onTargetLoaded(IAndroidTarget target) {
- IProject project = getProject();
- if (target != null && target.equals(Sdk.getCurrent().getTarget(project))) {
- reload();
- }
- }
-
- @Override
- public void onSdkLoaded() {
- // do nothing;
- }
- }
-
- /**
- * Returns the lock object used to synchronize all operations dealing with SDK, targets and
- * projects.
- */
- @NonNull
- public static final Object getLock() {
- return LOCK;
- }
-
- /**
- * Loads an SDK and returns an {@link Sdk} object if success.
- * <p/>If the SDK failed to load, it displays an error to the user.
- * @param sdkLocation the OS path to the SDK.
- */
- @Nullable
- public static Sdk loadSdk(String sdkLocation) {
- synchronized (LOCK) {
- if (sCurrentSdk != null) {
- sCurrentSdk.dispose();
- sCurrentSdk = null;
- }
-
- final AtomicBoolean hasWarning = new AtomicBoolean();
- final AtomicBoolean hasError = new AtomicBoolean();
- final ArrayList<String> logMessages = new ArrayList<String>();
- ILogger log = new ILogger() {
- @Override
- public void error(@Nullable Throwable throwable, @Nullable String errorFormat,
- Object... arg) {
- hasError.set(true);
- if (errorFormat != null) {
- logMessages.add(String.format("Error: " + errorFormat, arg));
- }
-
- if (throwable != null) {
- logMessages.add(throwable.getMessage());
- }
- }
-
- @Override
- public void warning(@NonNull String warningFormat, Object... arg) {
- hasWarning.set(true);
- logMessages.add(String.format("Warning: " + warningFormat, arg));
- }
-
- @Override
- public void info(@NonNull String msgFormat, Object... arg) {
- logMessages.add(String.format(msgFormat, arg));
- }
-
- @Override
- public void verbose(@NonNull String msgFormat, Object... arg) {
- info(msgFormat, arg);
- }
- };
-
- // get an SdkManager object for the location
- SdkManager manager = SdkManager.createManager(sdkLocation, log);
- try {
- if (manager == null) {
- hasError.set(true);
- } else {
- // create the AVD Manager
- AvdManager avdManager = null;
- try {
- avdManager = AvdManager.getInstance(manager.getLocalSdk(), log);
- } catch (AndroidLocationException e) {
- log.error(e, "Error parsing the AVDs");
- }
- sCurrentSdk = new Sdk(manager, avdManager);
- return sCurrentSdk;
- }
- } finally {
- if (hasError.get() || hasWarning.get()) {
- StringBuilder sb = new StringBuilder(
- String.format("%s when loading the SDK:\n",
- hasError.get() ? "Error" : "Warning"));
- for (String msg : logMessages) {
- sb.append('\n');
- sb.append(msg);
- }
- if (hasError.get()) {
- AdtPlugin.printErrorToConsole("Android SDK", sb.toString());
- AdtPlugin.displayError("Android SDK", sb.toString());
- } else {
- AdtPlugin.printToConsole("Android SDK", sb.toString());
- }
- }
- }
- return null;
- }
- }
-
- /**
- * Returns the current {@link Sdk} object.
- */
- @Nullable
- public static Sdk getCurrent() {
- synchronized (LOCK) {
- return sCurrentSdk;
- }
- }
-
- /**
- * Returns the location of the current SDK as an OS path string.
- * Guaranteed to be terminated by a platform-specific path separator.
- * <p/>
- * Due to {@link File} canonicalization, this MAY differ from the string used to initialize
- * the SDK path.
- *
- * @return The SDK OS path or null if no SDK is setup.
- * @deprecated Consider using {@link #getSdkFileLocation()} instead.
- * @see #getSdkFileLocation()
- */
- @Deprecated
- @Nullable
- public String getSdkOsLocation() {
- String path = mManager == null ? null : mManager.getLocation();
- if (path != null) {
- // For backward compatibility make sure it ends with a separator.
- // This used to be the case when the SDK Manager was created from a String path
- // but now that a File is internally used the trailing dir separator is lost.
- if (path.length() > 0 && !path.endsWith(File.separator)) {
- path = path + File.separator;
- }
- }
- return path;
- }
-
- /**
- * Returns the location of the current SDK as a {@link File} or null.
- *
- * @return The SDK OS path or null if no SDK is setup.
- */
- @Nullable
- public File getSdkFileLocation() {
- if (mManager == null || mManager.getLocalSdk() == null) {
- return null;
- }
- return mManager.getLocalSdk().getLocation();
- }
-
- /**
- * Returns a <em>new</em> {@link SdkManager} that can parse the SDK located
- * at the current {@link #getSdkOsLocation()}.
- * <p/>
- * Implementation detail: The {@link Sdk} has its own internal manager with
- * a custom logger which is not designed to be useful for outsiders. Callers
- * who need their own {@link SdkManager} for parsing will often want to control
- * the logger for their own need.
- * <p/>
- * This is just a convenient method equivalent to writing:
- * <pre>SdkManager.createManager(Sdk.getCurrent().getSdkLocation(), log);</pre>
- *
- * @param log The logger for the {@link SdkManager}.
- * @return A new {@link SdkManager} parsing the same location.
- */
- public @Nullable SdkManager getNewSdkManager(@NonNull ILogger log) {
- return SdkManager.createManager(getSdkOsLocation(), log);
- }
-
- /**
- * Returns the URL to the local documentation.
- * Can return null if no documentation is found in the current SDK.
- *
- * @return A file:// URL on the local documentation folder if it exists or null.
- */
- @Nullable
- public String getDocumentationBaseUrl() {
- return mDocBaseUrl;
- }
-
- /**
- * Returns the list of targets that are available in the SDK.
- */
- public IAndroidTarget[] getTargets() {
- return mManager.getTargets();
- }
-
- /**
- * Queries the underlying SDK Manager to check whether the platforms or addons
- * directories have changed on-disk. Does not reload the SDK.
- * <p/>
- * This is a quick test based on the presence of the directories, their timestamps
- * and a quick checksum of the source.properties files. It's possible to have
- * false positives (e.g. if a file is manually modified in a platform) or false
- * negatives (e.g. if a platform data file is changed manually in a 2nd level
- * directory without altering the source.properties.)
- */
- public boolean haveTargetsChanged() {
- return mManager.hasChanged();
- }
-
- /**
- * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
- *
- * @param hash the {@link IAndroidTarget} hash string.
- * @return The matching {@link IAndroidTarget} or null.
- */
- @Nullable
- public IAndroidTarget getTargetFromHashString(@NonNull String hash) {
- return mManager.getTargetFromHashString(hash);
- }
-
- @Nullable
- public BuildToolInfo getBuildToolInfo(@Nullable String buildToolVersion) {
- if (buildToolVersion != null) {
- try {
- return mManager.getBuildTool(FullRevision.parseRevision(buildToolVersion));
- } catch (Exception e) {
- // ignore, return null below.
- }
- }
-
- return null;
- }
-
- @Nullable
- public BuildToolInfo getLatestBuildTool() {
- return mManager.getLatestBuildTool();
- }
-
- /**
- * Initializes a new project with a target. This creates the <code>project.properties</code>
- * file.
- * @param project the project to initialize
- * @param target the project's target.
- * @throws IOException if creating the file failed in any way.
- * @throws StreamException if processing the project property file fails
- */
- public void initProject(@Nullable IProject project, @Nullable IAndroidTarget target)
- throws IOException, StreamException {
- if (project == null || target == null) {
- return;
- }
-
- synchronized (LOCK) {
- // check if there's already a state?
- ProjectState state = getProjectState(project);
-
- ProjectPropertiesWorkingCopy properties = null;
-
- if (state != null) {
- properties = state.getProperties().makeWorkingCopy();
- }
-
- if (properties == null) {
- IPath location = project.getLocation();
- if (location == null) { // can return null when the project is being deleted.
- // do nothing and return null;
- return;
- }
-
- properties = ProjectProperties.create(location.toOSString(), PropertyType.PROJECT);
- }
-
- // save the target hash string in the project persistent property
- properties.setProperty(ProjectProperties.PROPERTY_TARGET, target.hashString());
- properties.save();
- }
- }
-
- /**
- * Returns the {@link ProjectState} object associated with a given project.
- * <p/>
- * This method is the only way to properly get the project's {@link ProjectState}
- * If the project has not yet been loaded, then it is loaded.
- * <p/>Because this methods deals with projects, it's not linked to an actual {@link Sdk}
- * objects, and therefore is static.
- * <p/>The value returned by {@link ProjectState#getTarget()} will change as {@link Sdk} objects
- * are replaced.
- * @param project the request project
- * @return the ProjectState for the project.
- */
- @Nullable
- @SuppressWarnings("deprecation")
- public static ProjectState getProjectState(IProject project) {
- if (project == null) {
- return null;
- }
-
- synchronized (LOCK) {
- ProjectState state = sProjectStateMap.get(project);
- if (state == null) {
- // load the project.properties from the project folder.
- IPath location = project.getLocation();
- if (location == null) { // can return null when the project is being deleted.
- // do nothing and return null;
- return null;
- }
-
- String projectLocation = location.toOSString();
-
- ProjectProperties properties = ProjectProperties.load(projectLocation,
- PropertyType.PROJECT);
- if (properties == null) {
- // legacy support: look for default.properties and rename it if needed.
- properties = ProjectProperties.load(projectLocation,
- PropertyType.LEGACY_DEFAULT);
-
- if (properties == null) {
- AdtPlugin.log(IStatus.ERROR,
- "Failed to load properties file for project '%s'",
- project.getName());
- return null;
- } else {
- //legacy mode.
- // get a working copy with the new type "project"
- ProjectPropertiesWorkingCopy wc = properties.makeWorkingCopy(
- PropertyType.PROJECT);
- // and save it
- try {
- wc.save();
-
- // delete the old file.
- ProjectProperties.delete(projectLocation, PropertyType.LEGACY_DEFAULT);
-
- // make sure to use the new properties
- properties = ProjectProperties.load(projectLocation,
- PropertyType.PROJECT);
- } catch (Exception e) {
- AdtPlugin.log(IStatus.ERROR,
- "Failed to rename properties file to %1$s for project '%s2$'",
- PropertyType.PROJECT.getFilename(), project.getName());
- }
- }
- }
-
- state = new ProjectState(project, properties);
- sProjectStateMap.put(project, state);
-
- // try to resolve the target
- if (AdtPlugin.getDefault().getSdkLoadStatus() == LoadStatus.LOADED) {
- sCurrentSdk.loadTargetAndBuildTools(state);
- }
- }
-
- return state;
- }
- }
-
- /**
- * Returns the {@link IAndroidTarget} object associated with the given {@link IProject}.
- */
- @Nullable
- public IAndroidTarget getTarget(IProject project) {
- if (project == null) {
- return null;
- }
-
- ProjectState state = getProjectState(project);
- if (state != null) {
- return state.getTarget();
- }
-
- return null;
- }
-
- /**
- * Loads the {@link IAndroidTarget} and BuildTools for a given project.
- * <p/>This method will get the target hash string from the project properties, and resolve
- * it to an {@link IAndroidTarget} object and store it inside the {@link ProjectState}.
- * @param state the state representing the project to load.
- * @return the target that was loaded.
- */
- @Nullable
- public IAndroidTarget loadTargetAndBuildTools(ProjectState state) {
- IAndroidTarget target = null;
- if (state != null) {
- String hash = state.getTargetHashString();
- if (hash != null) {
- state.setTarget(target = getTargetFromHashString(hash));
- }
-
- String markerMessage = null;
- String buildToolInfoVersion = state.getBuildToolInfoVersion();
- if (buildToolInfoVersion != null) {
- BuildToolInfo buildToolsInfo = getBuildToolInfo(buildToolInfoVersion);
-
- if (buildToolsInfo != null) {
- state.setBuildToolInfo(buildToolsInfo);
- } else {
- markerMessage = String.format("Unable to resolve %s property value '%s'",
- ProjectProperties.PROPERTY_BUILD_TOOLS,
- buildToolInfoVersion);
- }
- } else {
- // this is ok, we'll use the latest one automatically.
- state.setBuildToolInfo(null);
- }
-
- handleBuildToolsMarker(state.getProject(), markerMessage);
- }
-
- return target;
- }
-
- /**
- * Adds or edit a build tools marker from the given project. This is done through a Job.
- * @param project the project
- * @param markerMessage the message. if null the marker is removed.
- */
- private void handleBuildToolsMarker(final IProject project, final String markerMessage) {
- Job markerJob = new Job("Android SDK: Build Tools Marker") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- if (project.isAccessible()) {
- // always delete existing marker first
- project.deleteMarkers(AdtConstants.MARKER_BUILD_TOOLS, true,
- IResource.DEPTH_ZERO);
-
- // add the new one if needed.
- if (markerMessage != null) {
- BaseProjectHelper.markProject(project,
- AdtConstants.MARKER_BUILD_TOOLS,
- markerMessage, IMarker.SEVERITY_ERROR,
- IMarker.PRIORITY_HIGH);
- }
- }
- } catch (CoreException e2) {
- AdtPlugin.log(e2, null);
- // Don't return e2.getStatus(); the job control will then produce
- // a popup with this error, which isn't very interesting for the
- // user.
- }
-
- return Status.OK_STATUS;
- }
- };
-
- // build jobs are run after other interactive jobs
- markerJob.setPriority(Job.BUILD);
- markerJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
- markerJob.schedule();
- }
-
- /**
- * Checks and loads (if needed) the data for a given target.
- * <p/> The data is loaded in a separate {@link Job}, and opened editors will be notified
- * through their implementation of {@link ITargetChangeListener#onTargetLoaded(IAndroidTarget)}.
- * <p/>An optional project as second parameter can be given to be recompiled once the target
- * data is finished loading.
- * <p/>The return value is non-null only if the target data has already been loaded (and in this
- * case is the status of the load operation)
- * @param target the target to load.
- * @param project an optional project to be recompiled when the target data is loaded.
- * If the target is already loaded, nothing happens.
- * @return The load status if the target data is already loaded.
- */
- @NonNull
- public LoadStatus checkAndLoadTargetData(final IAndroidTarget target, IJavaProject project) {
- boolean loadData = false;
-
- synchronized (LOCK) {
- if (mDontLoadTargetData) {
- return LoadStatus.FAILED;
- }
-
- TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
- if (bundle == null) {
- bundle = new TargetLoadBundle();
- mTargetDataStatusMap.put(target,bundle);
-
- // set status to loading
- bundle.status = LoadStatus.LOADING;
-
- // add project to bundle
- if (project != null) {
- bundle.projectsToReload.add(project);
- }
-
- // and set the flag to start the loading below
- loadData = true;
- } else if (bundle.status == LoadStatus.LOADING) {
- // add project to bundle
- if (project != null) {
- bundle.projectsToReload.add(project);
- }
-
- return bundle.status;
- } else if (bundle.status == LoadStatus.LOADED || bundle.status == LoadStatus.FAILED) {
- return bundle.status;
- }
- }
-
- if (loadData) {
- Job job = new Job(String.format("Loading data for %1$s", target.getFullName())) {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- AdtPlugin plugin = AdtPlugin.getDefault();
- try {
- IStatus status = new AndroidTargetParser(target).run(monitor);
-
- IJavaProject[] javaProjectArray = null;
-
- synchronized (LOCK) {
- TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
-
- if (status.getCode() != IStatus.OK) {
- bundle.status = LoadStatus.FAILED;
- bundle.projectsToReload.clear();
- } else {
- bundle.status = LoadStatus.LOADED;
-
- // Prepare the array of project to recompile.
- // The call is done outside of the synchronized block.
- javaProjectArray = bundle.projectsToReload.toArray(
- new IJavaProject[bundle.projectsToReload.size()]);
-
- // and update the UI of the editors that depend on the target data.
- plugin.updateTargetListeners(target);
- }
- }
-
- if (javaProjectArray != null) {
- ProjectHelper.updateProjects(javaProjectArray);
- }
-
- return status;
- } catch (Throwable t) {
- synchronized (LOCK) {
- TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
- bundle.status = LoadStatus.FAILED;
- }
-
- AdtPlugin.log(t, "Exception in checkAndLoadTargetData."); //$NON-NLS-1$
- String message = String.format("Parsing Data for %1$s failed", target.hashString());
- if (t instanceof UnsupportedClassVersionError) {
- message = "To use this platform, run Eclipse with JDK 7 or later. (" + message + ")";
- }
- return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message, t);
- }
- }
- };
- job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
- job.setRule(ResourcesPlugin.getWorkspace().getRoot());
- job.schedule();
- }
-
- // The only way to go through here is when the loading starts through the Job.
- // Therefore the current status of the target is LOADING.
- return LoadStatus.LOADING;
- }
-
- /**
- * Return the {@link AndroidTargetData} for a given {@link IAndroidTarget}.
- */
- @Nullable
- public AndroidTargetData getTargetData(IAndroidTarget target) {
- synchronized (LOCK) {
- return mTargetDataMap.get(target);
- }
- }
-
- /**
- * Return the {@link AndroidTargetData} for a given {@link IProject}.
- */
- @Nullable
- public AndroidTargetData getTargetData(IProject project) {
- synchronized (LOCK) {
- IAndroidTarget target = getTarget(project);
- if (target != null) {
- return getTargetData(target);
- }
- }
-
- return null;
- }
-
- /**
- * Returns a {@link DexWrapper} object to be used to execute dx commands. If dx.jar was not
- * loaded properly, then this will return <code>null</code>.
- */
- @Nullable
- public DexWrapper getDexWrapper(@Nullable BuildToolInfo buildToolInfo) {
- if (buildToolInfo == null) {
- return null;
- }
- synchronized (LOCK) {
- String dexLocation = buildToolInfo.getPath(BuildToolInfo.PathId.DX_JAR);
- DexWrapper dexWrapper = mDexWrappers.get(dexLocation);
-
- if (dexWrapper == null) {
- // load DX.
- dexWrapper = new DexWrapper();
- IStatus res = dexWrapper.loadDex(dexLocation);
- if (res != Status.OK_STATUS) {
- AdtPlugin.log(null, res.getMessage());
- dexWrapper = null;
- } else {
- mDexWrappers.put(dexLocation, dexWrapper);
- }
- }
-
- return dexWrapper;
- }
- }
-
- public void unloadDexWrappers() {
- synchronized (LOCK) {
- for (DexWrapper wrapper : mDexWrappers.values()) {
- wrapper.unload();
- }
- mDexWrappers.clear();
- }
- }
-
- /**
- * Returns the {@link AvdManager}. If the AvdManager failed to parse the AVD folder, this could
- * be <code>null</code>.
- */
- @Nullable
- public AvdManager getAvdManager() {
- return mAvdManager;
- }
-
- @Nullable
- public static AndroidVersion getDeviceVersion(@NonNull IDevice device) {
- try {
- Map<String, String> props = device.getProperties();
- String apiLevel = props.get(IDevice.PROP_BUILD_API_LEVEL);
- if (apiLevel == null) {
- return null;
- }
-
- return new AndroidVersion(Integer.parseInt(apiLevel),
- props.get((IDevice.PROP_BUILD_CODENAME)));
- } catch (NumberFormatException e) {
- return null;
- }
- }
-
- @NonNull
- public DeviceManager getDeviceManager() {
- return mDeviceManager;
- }
-
- /**
- * Returns a list of {@link ProjectState} representing projects depending, directly or
- * indirectly on a given library project.
- * @param project the library project.
- * @return a possibly empty list of ProjectState.
- */
- @NonNull
- public static Set<ProjectState> getMainProjectsFor(IProject project) {
- synchronized (LOCK) {
- // first get the project directly depending on this.
- Set<ProjectState> list = new HashSet<ProjectState>();
-
- // loop on all project and see if ProjectState.getLibrary returns a non null
- // project.
- for (Entry<IProject, ProjectState> entry : sProjectStateMap.entrySet()) {
- if (project != entry.getKey()) {
- LibraryState library = entry.getValue().getLibrary(project);
- if (library != null) {
- list.add(entry.getValue());
- }
- }
- }
-
- // now look for projects depending on the projects directly depending on the library.
- HashSet<ProjectState> result = new HashSet<ProjectState>(list);
- for (ProjectState p : list) {
- if (p.isLibrary()) {
- Set<ProjectState> set = getMainProjectsFor(p.getProject());
- result.addAll(set);
- }
- }
-
- return result;
- }
- }
-
- /**
- * Unload the SDK's target data.
- *
- * If <var>preventReload</var>, this effect is final until the SDK instance is changed
- * through {@link #loadSdk(String)}.
- *
- * The goal is to unload the targets to be able to replace existing targets with new ones,
- * before calling {@link #loadSdk(String)} to fully reload the SDK.
- *
- * @param preventReload prevent the data from being loaded again for the remaining live of
- * this {@link Sdk} instance.
- */
- public void unloadTargetData(boolean preventReload) {
- synchronized (LOCK) {
- mDontLoadTargetData = preventReload;
-
- // dispose of the target data.
- for (AndroidTargetData data : mTargetDataMap.values()) {
- data.dispose();
- }
-
- mTargetDataMap.clear();
- }
- }
-
- private Sdk(SdkManager manager, AvdManager avdManager) {
- mManager = manager;
- mAvdManager = avdManager;
-
- // listen to projects closing
- GlobalProjectMonitor monitor = GlobalProjectMonitor.getMonitor();
- // need to register the resource event listener first because the project listener
- // is called back during registration with project opened in the workspace.
- monitor.addResourceEventListener(mResourceEventListener);
- monitor.addProjectListener(mProjectListener);
- monitor.addFileListener(mFileListener,
- IResourceDelta.CHANGED | IResourceDelta.ADDED | IResourceDelta.REMOVED);
-
- // pre-compute some paths
- mDocBaseUrl = getDocumentationBaseUrl(manager.getLocation() +
- SdkConstants.OS_SDK_DOCS_FOLDER);
-
- mDeviceManager = DeviceManager.createInstance(manager.getLocalSdk().getLocation(),
- AdtPlugin.getDefault());
-
- // update whatever ProjectState is already present with new IAndroidTarget objects.
- synchronized (LOCK) {
- for (Entry<IProject, ProjectState> entry: sProjectStateMap.entrySet()) {
- loadTargetAndBuildTools(entry.getValue());
- }
- }
- }
-
- /**
- * Cleans and unloads the SDK.
- */
- private void dispose() {
- GlobalProjectMonitor monitor = GlobalProjectMonitor.getMonitor();
- monitor.removeProjectListener(mProjectListener);
- monitor.removeFileListener(mFileListener);
- monitor.removeResourceEventListener(mResourceEventListener);
-
- // the IAndroidTarget objects are now obsolete so update the project states.
- synchronized (LOCK) {
- for (Entry<IProject, ProjectState> entry: sProjectStateMap.entrySet()) {
- entry.getValue().setTarget(null);
- }
-
- // dispose of the target data.
- for (AndroidTargetData data : mTargetDataMap.values()) {
- data.dispose();
- }
-
- mTargetDataMap.clear();
- }
- }
-
- void setTargetData(IAndroidTarget target, AndroidTargetData data) {
- synchronized (LOCK) {
- mTargetDataMap.put(target, data);
- }
- }
-
- /**
- * Returns the URL to the local documentation.
- * Can return null if no documentation is found in the current SDK.
- *
- * @param osDocsPath Path to the documentation folder in the current SDK.
- * The folder may not actually exist.
- * @return A file:// URL on the local documentation folder if it exists or null.
- */
- private String getDocumentationBaseUrl(String osDocsPath) {
- File f = new File(osDocsPath);
-
- if (f.isDirectory()) {
- try {
- // Note: to create a file:// URL, one would typically use something like
- // f.toURI().toURL().toString(). However this generates a broken path on
- // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
- // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
- // do the correct thing manually.
-
- String path = f.getAbsolutePath();
- if (File.separatorChar != '/') {
- path = path.replace(File.separatorChar, '/');
- }
-
- // For some reason the URL class doesn't add the mandatory "//" after
- // the "file:" protocol name, so it has to be hacked into the path.
- URL url = new URL("file", null, "//" + path); //$NON-NLS-1$ //$NON-NLS-2$
- String result = url.toString();
- return result;
- } catch (MalformedURLException e) {
- // ignore malformed URLs
- }
- }
-
- return null;
- }
-
- /**
- * Delegate listener for project changes.
- */
- private IProjectListener mProjectListener = new IProjectListener() {
- @Override
- public void projectClosed(IProject project) {
- onProjectRemoved(project, false /*deleted*/);
- }
-
- @Override
- public void projectDeleted(IProject project) {
- onProjectRemoved(project, true /*deleted*/);
- }
-
- private void onProjectRemoved(IProject removedProject, boolean deleted) {
- if (DEBUG) {
- System.out.println(">>> CLOSED: " + removedProject.getName());
- }
-
- // get the target project
- synchronized (LOCK) {
- // Don't use getProject() as it could create the ProjectState if it's not
- // there yet and this is not what we want. We want the current object.
- // Therefore, direct access to the map.
- ProjectState removedState = sProjectStateMap.get(removedProject);
- if (removedState != null) {
- // 1. clear the layout lib cache associated with this project
- IAndroidTarget target = removedState.getTarget();
- if (target != null) {
- // get the bridge for the target, and clear the cache for this project.
- AndroidTargetData data = mTargetDataMap.get(target);
- if (data != null) {
- LayoutLibrary layoutLib = data.getLayoutLibrary();
- if (layoutLib != null && layoutLib.getStatus() == LoadStatus.LOADED) {
- layoutLib.clearCaches(removedProject);
- }
- }
- }
-
- // 2. if the project is a library, make sure to update the
- // LibraryState for any project referencing it.
- // Also, record the updated projects that are libraries, to update
- // projects that depend on them.
- for (ProjectState projectState : sProjectStateMap.values()) {
- LibraryState libState = projectState.getLibrary(removedProject);
- if (libState != null) {
- // Close the library right away.
- // This remove links between the LibraryState and the projectState.
- // This is because in case of a rename of a project, projectClosed and
- // projectOpened will be called before any other job is run, so we
- // need to make sure projectOpened is closed with the main project
- // state up to date.
- libState.close();
-
- // record that this project changed, and in case it's a library
- // that its parents need to be updated as well.
- markProject(projectState, projectState.isLibrary());
- }
- }
-
- // now remove the project for the project map.
- sProjectStateMap.remove(removedProject);
- }
- }
-
- if (DEBUG) {
- System.out.println("<<<");
- }
- }
-
- @Override
- public void projectOpened(IProject project) {
- onProjectOpened(project);
- }
-
- @Override
- public void projectOpenedWithWorkspace(IProject project) {
- // no need to force recompilation when projects are opened with the workspace.
- onProjectOpened(project);
- }
-
- @Override
- public void allProjectsOpenedWithWorkspace() {
- // Correct currently open editors
- fixOpenLegacyEditors();
- }
-
- private void onProjectOpened(final IProject openedProject) {
-
- ProjectState openedState = getProjectState(openedProject);
- if (openedState != null) {
- if (DEBUG) {
- System.out.println(">>> OPENED: " + openedProject.getName());
- }
-
- synchronized (LOCK) {
- final boolean isLibrary = openedState.isLibrary();
- final boolean hasLibraries = openedState.hasLibraries();
-
- if (isLibrary || hasLibraries) {
- boolean foundLibraries = false;
- // loop on all the existing project and update them based on this new
- // project
- for (ProjectState projectState : sProjectStateMap.values()) {
- if (projectState != openedState) {
- // If the project has libraries, check if this project
- // is a reference.
- if (hasLibraries) {
- // ProjectState#needs() both checks if this is a missing library
- // and updates LibraryState to contains the new values.
- // This must always be called.
- LibraryState libState = openedState.needs(projectState);
-
- if (libState != null) {
- // found a library! Add the main project to the list of
- // modified project
- foundLibraries = true;
- }
- }
-
- // if the project is a library check if the other project depend
- // on it.
- if (isLibrary) {
- // ProjectState#needs() both checks if this is a missing library
- // and updates LibraryState to contains the new values.
- // This must always be called.
- LibraryState libState = projectState.needs(openedState);
-
- if (libState != null) {
- // There's a dependency! Add the project to the list of
- // modified project, but also to a list of projects
- // that saw one of its dependencies resolved.
- markProject(projectState, projectState.isLibrary());
- }
- }
- }
- }
-
- // if the project has a libraries and we found at least one, we add
- // the project to the list of modified project.
- // Since we already went through the parent, no need to update them.
- if (foundLibraries) {
- markProject(openedState, false /*updateParents*/);
- }
- }
- }
-
- // Correct file editor associations.
- fixEditorAssociations(openedProject);
-
- // Fix classpath entries in a job since the workspace might be locked now.
- Job fixCpeJob = new Job("Adjusting Android Project Classpath") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- ProjectHelper.fixProjectClasspathEntries(
- JavaCore.create(openedProject));
- } catch (JavaModelException e) {
- AdtPlugin.log(e, "error fixing classpath entries");
- // Don't return e2.getStatus(); the job control will then produce
- // a popup with this error, which isn't very interesting for the
- // user.
- }
-
- return Status.OK_STATUS;
- }
- };
-
- // build jobs are run after other interactive jobs
- fixCpeJob.setPriority(Job.BUILD);
- fixCpeJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
- fixCpeJob.schedule();
-
-
- if (DEBUG) {
- System.out.println("<<<");
- }
- }
- }
-
- @Override
- public void projectRenamed(IProject project, IPath from) {
- // we don't actually care about this anymore.
- }
- };
-
- /**
- * Delegate listener for file changes.
- */
- private IFileListener mFileListener = new IFileListener() {
- @Override
- public void fileChanged(final @NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas,
- int kind, @Nullable String extension, int flags, boolean isAndroidPRoject) {
- if (!isAndroidPRoject) {
- return;
- }
-
- if (SdkConstants.FN_PROJECT_PROPERTIES.equals(file.getName()) &&
- file.getParent() == file.getProject()) {
- try {
- // reload the content of the project.properties file and update
- // the target.
- IProject iProject = file.getProject();
-
- ProjectState state = Sdk.getProjectState(iProject);
-
- // get the current target and build tools
- IAndroidTarget oldTarget = state.getTarget();
- boolean oldRsSupportMode = state.getRenderScriptSupportMode();
-
- // get the current library flag
- boolean wasLibrary = state.isLibrary();
-
- LibraryDifference diff = state.reloadProperties();
-
- // load the (possibly new) target.
- IAndroidTarget newTarget = loadTargetAndBuildTools(state);
-
- // reload the libraries if needed
- if (diff.hasDiff()) {
- if (diff.added) {
- synchronized (LOCK) {
- for (ProjectState projectState : sProjectStateMap.values()) {
- if (projectState != state) {
- // need to call needs to do the libraryState link,
- // but no need to look at the result, as we'll compare
- // the result of getFullLibraryProjects()
- // this is easier to due to indirect dependencies.
- state.needs(projectState);
- }
- }
- }
- }
-
- markProject(state, wasLibrary || state.isLibrary());
- }
-
- // apply the new target if needed.
- if (newTarget != oldTarget ||
- oldRsSupportMode != state.getRenderScriptSupportMode()) {
- IJavaProject javaProject = BaseProjectHelper.getJavaProject(
- file.getProject());
- if (javaProject != null) {
- ProjectHelper.updateProject(javaProject);
- }
-
- // update the editors to reload with the new target
- AdtPlugin.getDefault().updateTargetListeners(iProject);
- }
- } catch (CoreException e) {
- // This can't happen as it's only for closed project (or non existing)
- // but in that case we can't get a fileChanged on this file.
- }
- } else if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
- // check if it's an add/remove on a jar files inside libs
- if (EXT_JAR.equals(extension) &&
- file.getProjectRelativePath().segmentCount() == 2 &&
- file.getParent().getName().equals(SdkConstants.FD_NATIVE_LIBS)) {
- // need to update the project and whatever depend on it.
-
- processJarFileChange(file);
- }
- }
- }
-
- private void processJarFileChange(final IFile file) {
- try {
- IProject iProject = file.getProject();
-
- if (iProject.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
- return;
- }
-
- List<IJavaProject> projectList = new ArrayList<IJavaProject>();
- IJavaProject javaProject = BaseProjectHelper.getJavaProject(iProject);
- if (javaProject != null) {
- projectList.add(javaProject);
- }
-
- ProjectState state = Sdk.getProjectState(iProject);
-
- if (state != null) {
- Collection<ProjectState> parents = state.getFullParentProjects();
- for (ProjectState s : parents) {
- javaProject = BaseProjectHelper.getJavaProject(s.getProject());
- if (javaProject != null) {
- projectList.add(javaProject);
- }
- }
-
- ProjectHelper.updateProjects(
- projectList.toArray(new IJavaProject[projectList.size()]));
- }
- } catch (CoreException e) {
- // This can't happen as it's only for closed project (or non existing)
- // but in that case we can't get a fileChanged on this file.
- }
- }
- };
-
- /** List of modified projects. This is filled in
- * {@link IProjectListener#projectOpened(IProject)},
- * {@link IProjectListener#projectOpenedWithWorkspace(IProject)},
- * {@link IProjectListener#projectClosed(IProject)}, and
- * {@link IProjectListener#projectDeleted(IProject)} and processed in
- * {@link IResourceEventListener#resourceChangeEventEnd()}.
- */
- private final List<ProjectState> mModifiedProjects = new ArrayList<ProjectState>();
- private final List<ProjectState> mModifiedChildProjects = new ArrayList<ProjectState>();
-
- private void markProject(ProjectState projectState, boolean updateParents) {
- if (mModifiedProjects.contains(projectState) == false) {
- if (DEBUG) {
- System.out.println("\tMARKED: " + projectState.getProject().getName());
- }
- mModifiedProjects.add(projectState);
- }
-
- // if the project is resolved also add it to this list.
- if (updateParents) {
- if (mModifiedChildProjects.contains(projectState) == false) {
- if (DEBUG) {
- System.out.println("\tMARKED(child): " + projectState.getProject().getName());
- }
- mModifiedChildProjects.add(projectState);
- }
- }
- }
-
- /**
- * Delegate listener for resource changes. This is called before and after any calls to the
- * project and file listeners (for a given resource change event).
- */
- private IResourceEventListener mResourceEventListener = new IResourceEventListener() {
- @Override
- public void resourceChangeEventStart() {
- mModifiedProjects.clear();
- mModifiedChildProjects.clear();
- }
-
- @Override
- public void resourceChangeEventEnd() {
- if (mModifiedProjects.size() == 0) {
- return;
- }
-
- // first make sure all the parents are updated
- updateParentProjects();
-
- // for all modified projects, update their library list
- // and gather their IProject
- final List<IJavaProject> projectList = new ArrayList<IJavaProject>();
- for (ProjectState state : mModifiedProjects) {
- state.updateFullLibraryList();
- projectList.add(JavaCore.create(state.getProject()));
- }
-
- Job job = new Job("Android Library Update") { //$NON-NLS-1$
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- LibraryClasspathContainerInitializer.updateProjects(
- projectList.toArray(new IJavaProject[projectList.size()]));
-
- for (IJavaProject javaProject : projectList) {
- try {
- javaProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD,
- monitor);
- } catch (CoreException e) {
- // pass
- }
- }
- return Status.OK_STATUS;
- }
- };
- job.setPriority(Job.BUILD);
- job.setRule(ResourcesPlugin.getWorkspace().getRoot());
- job.schedule();
- }
- };
-
- /**
- * Updates all existing projects with a given list of new/updated libraries.
- * This loops through all opened projects and check if they depend on any of the given
- * library project, and if they do, they are linked together.
- */
- private void updateParentProjects() {
- if (mModifiedChildProjects.size() == 0) {
- return;
- }
-
- ArrayList<ProjectState> childProjects = new ArrayList<ProjectState>(mModifiedChildProjects);
- mModifiedChildProjects.clear();
- synchronized (LOCK) {
- // for each project for which we must update its parent, we loop on the parent
- // projects and adds them to the list of modified projects. If they are themselves
- // libraries, we add them too.
- for (ProjectState state : childProjects) {
- if (DEBUG) {
- System.out.println(">>> Updating parents of " + state.getProject().getName());
- }
- List<ProjectState> parents = state.getParentProjects();
- for (ProjectState parent : parents) {
- markProject(parent, parent.isLibrary());
- }
- if (DEBUG) {
- System.out.println("<<<");
- }
- }
- }
-
- // done, but there may be parents that are also libraries. Need to update their parents.
- updateParentProjects();
- }
-
- /**
- * Fix editor associations for the given project, if not already done.
- * <p/>
- * Eclipse has a per-file setting for which editor should be used for each file
- * (see {@link IDE#setDefaultEditor(IFile, String)}).
- * We're using this flag to pick between the various XML editors (layout, drawable, etc)
- * since they all have the same file name extension.
- * <p/>
- * Unfortunately, the file setting can be "wrong" for two reasons:
- * <ol>
- * <li> The editor type was added <b>after</b> a file had been seen by the IDE.
- * For example, we added new editors for animations and for drawables around
- * ADT 12, but any file seen by ADT in earlier versions will continue to use
- * the vanilla Eclipse XML editor instead.
- * <li> A bug in ADT 14 and ADT 15 (see issue 21124) meant that files created in new
- * folders would end up with wrong editor associations. Even though that bug
- * is fixed in ADT 16, the fix only affects new files, it cannot retroactively
- * fix editor associations that were set incorrectly by ADT 14 or 15.
- * </ol>
- * <p/>
- * This method attempts to fix the editor bindings retroactively by scanning all the
- * resource XML files and resetting the editor associations.
- * Since this is a potentially slow operation, this is only done "once"; we use a
- * persistent project property to avoid looking repeatedly. In the future if we add
- * additional editors, we can rev the scanned version value.
- */
- private void fixEditorAssociations(final IProject project) {
- QualifiedName KEY = new QualifiedName(AdtPlugin.PLUGIN_ID, "editorbinding"); //$NON-NLS-1$
-
- try {
- String value = project.getPersistentProperty(KEY);
- int currentVersion = 0;
- if (value != null) {
- try {
- currentVersion = Integer.parseInt(value);
- } catch (Exception ingore) {
- }
- }
-
- // The target version we're comparing to. This must be incremented each time
- // we change the processing here so that a new version of the plugin would
- // try to fix existing user projects.
- final int targetVersion = 2;
-
- if (currentVersion >= targetVersion) {
- return;
- }
-
- // Set to specific version such that we can rev the version in the future
- // to trigger further scanning
- project.setPersistentProperty(KEY, Integer.toString(targetVersion));
-
- // Now update the actual editor associations.
- Job job = new Job("Update Android editor bindings") { //$NON-NLS-1$
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- for (IResource folderResource : project.getFolder(FD_RES).members()) {
- if (folderResource instanceof IFolder) {
- IFolder folder = (IFolder) folderResource;
-
- for (IResource resource : folder.members()) {
- if (resource instanceof IFile &&
- resource.getName().endsWith(DOT_XML)) {
- fixXmlFile((IFile) resource);
- }
- }
- }
- }
-
- // TODO change AndroidManifest.xml ID too
-
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
-
- return Status.OK_STATUS;
- }
-
- /**
- * Attempt to fix the editor ID for the given /res XML file.
- */
- private void fixXmlFile(final IFile file) {
- // Fix the default editor ID for this resource.
- // This has no effect on currently open editors.
- IEditorDescriptor desc = IDE.getDefaultEditor(file);
-
- if (desc == null || !CommonXmlEditor.ID.equals(desc.getId())) {
- IDE.setDefaultEditor(file, CommonXmlEditor.ID);
- }
- }
- };
- job.setPriority(Job.BUILD);
- job.schedule();
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
- }
-
- /**
- * Tries to fix all currently open Android legacy editors.
- * <p/>
- * If an editor is found to match one of the legacy ids, we'll try to close it.
- * If that succeeds, we try to reopen it using the new common editor ID.
- * <p/>
- * This method must be run from the UI thread.
- */
- private void fixOpenLegacyEditors() {
-
- AdtPlugin adt = AdtPlugin.getDefault();
- if (adt == null) {
- return;
- }
-
- final IPreferenceStore store = adt.getPreferenceStore();
- int currentValue = store.getInt(AdtPrefs.PREFS_FIX_LEGACY_EDITORS);
- // The target version we're comparing to. This must be incremented each time
- // we change the processing here so that a new version of the plugin would
- // try to fix existing editors.
- final int targetValue = 1;
-
- if (currentValue >= targetValue) {
- return;
- }
-
- // To be able to close and open editors we need to make sure this is done
- // in the UI thread, which this isn't invoked from.
- PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
- @Override
- public void run() {
- HashSet<String> legacyIds =
- new HashSet<String>(Arrays.asList(CommonXmlEditor.LEGACY_EDITOR_IDS));
-
- for (IWorkbenchWindow win : PlatformUI.getWorkbench().getWorkbenchWindows()) {
- for (IWorkbenchPage page : win.getPages()) {
- for (IEditorReference ref : page.getEditorReferences()) {
- try {
- IEditorInput input = ref.getEditorInput();
- if (input instanceof IFileEditorInput) {
- IFile file = ((IFileEditorInput)input).getFile();
- IEditorPart part = ref.getEditor(true /*restore*/);
- if (part != null) {
- IWorkbenchPartSite site = part.getSite();
- if (site != null) {
- String id = site.getId();
- if (legacyIds.contains(id)) {
- // This editor matches one of legacy editor IDs.
- fixEditor(page, part, input, file, id);
- }
- }
- }
- }
- } catch (Exception e) {
- // ignore
- }
- }
- }
- }
-
- // Remember that we managed to do fix all editors
- store.setValue(AdtPrefs.PREFS_FIX_LEGACY_EDITORS, targetValue);
- }
-
- private void fixEditor(
- IWorkbenchPage page,
- IEditorPart part,
- IEditorInput input,
- IFile file,
- String id) {
- IDE.setDefaultEditor(file, CommonXmlEditor.ID);
-
- boolean ok = page.closeEditor(part, true /*save*/);
-
- AdtPlugin.log(IStatus.INFO,
- "Closed legacy editor ID %s for %s: %s", //$NON-NLS-1$
- id,
- file.getFullPath(),
- ok ? "Success" : "Failed");//$NON-NLS-1$ //$NON-NLS-2$
-
- if (ok) {
- // Try to reopen it with the new ID
- try {
- page.openEditor(input, CommonXmlEditor.ID);
- } catch (PartInitException e) {
- AdtPlugin.log(e,
- "Failed to reopen %s", //$NON-NLS-1$
- file.getFullPath());
- }
- }
- }
- });
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/WidgetClassLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/WidgetClassLoader.java
deleted file mode 100644
index 682d6e538..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/WidgetClassLoader.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2008 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 org.eclipse.core.runtime.IProgressMonitor;
-
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-import javax.management.InvalidAttributeValueException;
-
-/**
- * Parser for the text file containing the list of widgets, layouts and layout params.
- * <p/>
- * The file is a straight text file containing one class per line.<br>
- * Each line is in the following format<br>
- * <code>[code][class name] [super class name] [super class name]...</code>
- * where code is a single letter (W for widget, L for layout, P for layout params), and class names
- * are the fully qualified name of the classes.
- */
-public final class WidgetClassLoader implements IAndroidClassLoader {
-
- /**
- * Basic class containing the class descriptions found in the text file.
- */
- private final static class ClassDescriptor implements IClassDescriptor {
-
- private String mFqcn;
- private String mSimpleName;
- private ClassDescriptor mSuperClass;
- private ClassDescriptor mEnclosingClass;
- private final ArrayList<IClassDescriptor> mDeclaredClasses =
- new ArrayList<IClassDescriptor>();
- private boolean mIsInstantiable = false;
-
- ClassDescriptor(String fqcn) {
- mFqcn = fqcn;
- mSimpleName = getSimpleName(fqcn);
- }
-
- @Override
- public String getFullClassName() {
- return mFqcn;
- }
-
- @Override
- public String getSimpleName() {
- return mSimpleName;
- }
-
- @Override
- public IClassDescriptor[] getDeclaredClasses() {
- return mDeclaredClasses.toArray(new IClassDescriptor[mDeclaredClasses.size()]);
- }
-
- private void addDeclaredClass(ClassDescriptor declaredClass) {
- mDeclaredClasses.add(declaredClass);
- }
-
- @Override
- public IClassDescriptor getEnclosingClass() {
- return mEnclosingClass;
- }
-
- void setEnclosingClass(ClassDescriptor enclosingClass) {
- // set the enclosing class.
- mEnclosingClass = enclosingClass;
-
- // add this to the list of declared class in the enclosing class.
- mEnclosingClass.addDeclaredClass(this);
-
- // finally change the name of declared class to make sure it uses the
- // convention: package.enclosing$declared instead of package.enclosing.declared
- mFqcn = enclosingClass.mFqcn + "$" + mFqcn.substring(enclosingClass.mFqcn.length() + 1);
- }
-
- @Override
- public IClassDescriptor getSuperclass() {
- return mSuperClass;
- }
-
- void setSuperClass(ClassDescriptor superClass) {
- mSuperClass = superClass;
- }
-
- @Override
- public boolean equals(Object clazz) {
- if (clazz instanceof ClassDescriptor) {
- return mFqcn.equals(((ClassDescriptor)clazz).mFqcn);
- }
- return super.equals(clazz);
- }
-
- @Override
- public int hashCode() {
- return mFqcn.hashCode();
- }
-
- @Override
- public boolean isInstantiable() {
- return mIsInstantiable;
- }
-
- void setInstantiable(boolean state) {
- mIsInstantiable = state;
- }
-
- private String getSimpleName(String fqcn) {
- String[] segments = fqcn.split("\\.");
- return segments[segments.length-1];
- }
- }
-
- private BufferedReader mReader;
-
- /** Output map of FQCN => descriptor on all classes */
- private final Map<String, ClassDescriptor> mMap = new TreeMap<String, ClassDescriptor>();
- /** Output map of FQCN => descriptor on View classes */
- private final Map<String, ClassDescriptor> mWidgetMap = new TreeMap<String, ClassDescriptor>();
- /** Output map of FQCN => descriptor on ViewGroup classes */
- private final Map<String, ClassDescriptor> mLayoutMap = new TreeMap<String, ClassDescriptor>();
- /** Output map of FQCN => descriptor on LayoutParams classes */
- private final Map<String, ClassDescriptor> mLayoutParamsMap =
- new HashMap<String, ClassDescriptor>();
- /** File path of the source text file */
- private String mOsFilePath;
-
- /**
- * Creates a loader with a given file path.
- * @param osFilePath the OS path of the file to load.
- * @throws FileNotFoundException if the file is not found.
- */
- WidgetClassLoader(String osFilePath) throws FileNotFoundException {
- mOsFilePath = osFilePath;
- mReader = new BufferedReader(new FileReader(osFilePath));
- }
-
- @Override
- public String getSource() {
- return mOsFilePath;
- }
-
- /**
- * Parses the text file and return true if the file was successfully parsed.
- * @param monitor
- */
- boolean parseWidgetList(IProgressMonitor monitor) {
- try {
- String line;
- while ((line = mReader.readLine()) != null) {
- if (line.length() > 0) {
- char prefix = line.charAt(0);
- String[] classes = null;
- ClassDescriptor clazz = null;
- switch (prefix) {
- case 'W':
- classes = line.substring(1).split(" ");
- clazz = processClass(classes, 0, null /* map */);
- if (clazz != null) {
- clazz.setInstantiable(true);
- mWidgetMap.put(classes[0], clazz);
- }
- break;
- case 'L':
- classes = line.substring(1).split(" ");
- clazz = processClass(classes, 0, null /* map */);
- if (clazz != null) {
- clazz.setInstantiable(true);
- mLayoutMap.put(classes[0], clazz);
- }
- break;
- case 'P':
- classes = line.substring(1).split(" ");
- clazz = processClass(classes, 0, mLayoutParamsMap);
- if (clazz != null) {
- clazz.setInstantiable(true);
- }
- break;
- case '#':
- // comment, do nothing
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
- }
-
- // reconciliate the layout and their layout params
- postProcess();
-
- return true;
- } catch (IOException e) {
- } finally {
- try {
- mReader.close();
- } catch (IOException e) {
- }
- }
-
- return false;
- }
-
- /**
- * Parses a View class and adds a ViewClassInfo for it in mWidgetMap.
- * It calls itself recursively to handle super classes which are also Views.
- * @param classes the inheritance list of the class to process.
- * @param index the index of the class to process in the <code>classes</code> array.
- * @param map an optional map in which to put every {@link ClassDescriptor} created.
- */
- private ClassDescriptor processClass(String[] classes, int index,
- Map<String, ClassDescriptor> map) {
- if (index >= classes.length) {
- return null;
- }
-
- String fqcn = classes[index];
-
- if ("java.lang.Object".equals(fqcn)) { //$NON-NLS-1$
- return null;
- }
-
- // check if the ViewInfoClass has not yet been created.
- if (mMap.containsKey(fqcn)) {
- return mMap.get(fqcn);
- }
-
- // create the custom class.
- ClassDescriptor clazz = new ClassDescriptor(fqcn);
- mMap.put(fqcn, clazz);
- if (map != null) {
- map.put(fqcn, clazz);
- }
-
- // get the super class
- ClassDescriptor superClass = processClass(classes, index+1, map);
- if (superClass != null) {
- clazz.setSuperClass(superClass);
- }
-
- return clazz;
- }
-
- /**
- * Goes through the layout params and look for the enclosed class. If the layout params
- * has no known enclosed type it is dropped.
- */
- private void postProcess() {
- Collection<ClassDescriptor> params = mLayoutParamsMap.values();
-
- for (ClassDescriptor param : params) {
- String fqcn = param.getFullClassName();
-
- // get the enclosed name.
- String enclosed = getEnclosedName(fqcn);
-
- // look for a match in the layouts. We don't use the layout map as it only contains the
- // end classes, but in this case we also need to process the layout params for the base
- // layout classes.
- ClassDescriptor enclosingType = mMap.get(enclosed);
- if (enclosingType != null) {
- param.setEnclosingClass(enclosingType);
-
- // remove the class from the map, and put it back with the fixed name
- mMap.remove(fqcn);
- mMap.put(param.getFullClassName(), param);
- }
- }
- }
-
- private String getEnclosedName(String fqcn) {
- int index = fqcn.lastIndexOf('.');
- return fqcn.substring(0, index);
- }
-
- /**
- * Finds and loads all classes that derive from a given set of super classes.
- *
- * @param rootPackage Root 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
- */
- @Override
- public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(String rootPackage,
- String[] superClasses) throws IOException, InvalidAttributeValueException,
- ClassFormatError {
- HashMap<String, ArrayList<IClassDescriptor>> map =
- new HashMap<String, ArrayList<IClassDescriptor>>();
-
- ArrayList<IClassDescriptor> list = new ArrayList<IClassDescriptor>();
- list.addAll(mWidgetMap.values());
- map.put(SdkConstants.CLASS_VIEW, list);
-
- list = new ArrayList<IClassDescriptor>();
- list.addAll(mLayoutMap.values());
- map.put(SdkConstants.CLASS_VIEWGROUP, list);
-
- list = new ArrayList<IClassDescriptor>();
- list.addAll(mLayoutParamsMap.values());
- map.put(SdkConstants.CLASS_VIEWGROUP_LAYOUTPARAMS, list);
-
- return map;
- }
-
- /**
- * 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 {
- return mMap.get(className);
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-devices.xsd b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-devices.xsd
deleted file mode 100755
index a4ea6c42e..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-devices.xsd
+++ /dev/null
@@ -1,345 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Copyright (C) 2009 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.
--->
-<xsd:schema
- targetNamespace="http://schemas.android.com/sdk/android/layout-devices/1"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:c="http://schemas.android.com/sdk/android/layout-devices/1"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- version="1">
-
- <!-- The root element layout-devices defines a sequence of 0..n device elements. -->
-
- <xsd:element name="layout-devices" type="c:layoutDevicesType" />
-
- <xsd:complexType name="layoutDevicesType">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- The "layout-devices" element is the root element of this schema.
-
- It must contain zero or more "device" elements that each define the configurations
- available for a given device.
-
- These definitions are used in the Graphical Layout Editor in the
- Android Development Tools (ADT) plugin for Eclipse.
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:sequence>
- <!-- layout-devices defines a sequence of 0..n device elements. -->
- <xsd:element name="device" minOccurs="0" maxOccurs="unbounded">
-
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- A device element must contain at most one "default" element
- followed by one or more "config" elements.
-
- The "default" element defines all the default parameters
- inherited by the following "config" elements.
- Each "config" element can override the default values, if any.
-
- A "device" element also has a required "name" attribute that
- represents the user-interface name of this device.
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:complexType>
- <!-- device defines a choice of 0..1 default element
- and 1..n config elements. -->
-
- <xsd:sequence>
- <xsd:element name="default" type="c:parametersType"
- minOccurs="0" maxOccurs="1" />
- <xsd:element name="config" type="c:configType"
- minOccurs="1" maxOccurs="unbounded" />
- </xsd:sequence>
-
- <xsd:attribute name="name" type="xsd:normalizedString" use="required" />
- </xsd:complexType>
-
- </xsd:element>
- </xsd:sequence>
- </xsd:complexType>
-
- <!-- The type of a device>default element.
- This is overridden by configType below for the device>config element.
- -->
- <xsd:complexType name="parametersType">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- The parametersType define all the parameters that can happen either in a
- "default" element or in a named "config" element.
- Each parameter element can appear once at most.
-
- Parameters here are the same as those used to specify alternate Android
- resources, as documented by
- http://d.android.com/guide/topics/resources/resources-i18n.html#AlternateResources
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:all>
- <!-- parametersType says that 0..1 of each of these elements must be declared. -->
-
- <xsd:element name="country-code" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the configuration is for a particular Mobile Country Code.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:float">
- <xsd:minInclusive value="100" />
- <xsd:maxInclusive value="999" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="network-code" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the configuration is for a particular Mobile Network Code.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:float">
- <xsd:minExclusive value="0" />
- <xsd:maxExclusive value="1000" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="screen-size" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies that the configuration is for a particular class of screen.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="small" />
- <xsd:enumeration value="normal" />
- <xsd:enumeration value="large" />
- <xsd:enumeration value="xlarge" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="screen-ratio" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies that the configuration is for a taller/wider than traditional
- screen. This is based purely on the aspect ration of the screen: QVGA,
- HVGA, and VGA are notlong; WQVGA, WVGA, FWVGA are long. Note that long
- may mean either wide or tall, depending on the current orientation.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="long" />
- <xsd:enumeration value="notlong" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="screen-orientation" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies that the configuration is for a screen that is tall (port) or
- wide (land).
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="port" />
- <xsd:enumeration value="land" />
- <xsd:enumeration value="square" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="pixel-density" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the screen density the configuration is defined for. The medium
- density of traditional HVGA screens (mdpi) is defined to be approximately
- 160dpi; low density (ldpi) is 120, and high density (hdpi) is 240. There
- is thus a 4:3 scaling factor between each density, so a 9x9 bitmap in ldpi
- would be 12x12 is mdpi and 16x16 in hdpi.
- The special nodpi density that can be used in resource qualifiers is not
- a valid keyword here.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="ldpi" />
- <xsd:enumeration value="mdpi" />
- <xsd:enumeration value="tvdpi" />
- <xsd:enumeration value="hdpi" />
- <xsd:enumeration value="xhdpi" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="touch-type" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the touch type the configuration is defined for.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="notouch" />
- <xsd:enumeration value="stylus" />
- <xsd:enumeration value="finger" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="keyboard-state" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- If your configuration uses a soft keyboard, use the keyssoft value.
- If it doesn't and has a real keyboard, use keysexposed or keyshidden.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="keysexposed" />
- <xsd:enumeration value="keyshidden" />
- <xsd:enumeration value="keyssoft" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="text-input-method" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the primary text input method the configuration is designed for.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="nokeys" />
- <xsd:enumeration value="qwerty" />
- <xsd:enumeration value="12key" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="nav-state" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies whether the primary non-touchscreen navigation control is
- exposed or hidden.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="navexposed" />
- <xsd:enumeration value="navhidden" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="nav-method" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the primary non-touchscreen navigation method the configuration
- is designed for.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="dpad" />
- <xsd:enumeration value="trackball" />
- <xsd:enumeration value="wheel" />
- <xsd:enumeration value="nonav" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="screen-dimension" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the device screen resolution, in pixels.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:sequence minOccurs="2" maxOccurs="2">
-
- <xsd:element name="size">
- <xsd:simpleType>
- <xsd:restriction base="xsd:positiveInteger" />
- </xsd:simpleType>
- </xsd:element>
-
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="xdpi" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the actual density in X of the device screen.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:float">
- <xsd:minExclusive value="0" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- <xsd:element name="ydpi" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Specifies the actual density in Y of the device screen.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:float">
- <xsd:minExclusive value="0" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:element>
-
- </xsd:all>
- </xsd:complexType>
-
- <!-- The type definition of a device>config element.
- This type is basically all the element defined by parametersType and an extra
- required "name" attribute for the user-interface configuration name.
- -->
- <xsd:complexType name="configType">
- <xsd:annotation>
- <xsd:documentation>
- The configType defines the content of a "config" element in a "device" element.
-
- A "config" element can have all the parameters elements defined by
- "parameterType". It also has a required "name" attribute that indicates the
- user-interface name for this configuration.
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:complexContent>
- <xsd:extension base="c:parametersType">
- <xsd:attribute name="name" type="xsd:normalizedString" use="required" />
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
-</xsd:schema>