OSDN Git Service

Look for classes in java projects when loading custom views.
authorXavier Ducrohet <xav@android.com>
Mon, 17 Jan 2011 02:20:28 +0000 (18:20 -0800)
committerXavier Ducrohet <xav@android.com>
Mon, 17 Jan 2011 02:54:46 +0000 (18:54 -0800)
Even if Java projects can't really contain custom views,
they can contain classes on which the custom views depend.
The ProjectClassLoader now handles these projects.

Changed the way the LayoutReloadMonitor deals with projects
to handle referenced projects.

Also fixed some API returning arrays to make them return lists.

http://code.google.com/p/android/issues/detail?id=13010

Change-Id: I7f9da9d5289a5f2735c2cf3638bedc1efbd0c71a

12 files changed:
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/MultiApkExportAction.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java

index da57a4f..10ec15f 100644 (file)
@@ -254,7 +254,7 @@ public class MultiApkExportAction implements IObjectActionDelegate {
             throws CoreException {
         try {
             // get the libraries for this project
-            IProject[] libProjects = projectState.getFullLibraryProjects();
+            List<IProject> libProjects = projectState.getFullLibraryProjects();
 
             IProject project = projectState.getProject();
             IJavaProject javaProject = JavaCore.create(project);
@@ -294,8 +294,8 @@ public class MultiApkExportAction implements IObjectActionDelegate {
             String outputFile = binFolder.getFile(outputName).getLocation().toOSString();
 
             // get the list of referenced projects.
-            IProject[] javaRefs = ProjectHelper.getReferencedProjects(project);
-            IJavaProject[] referencedJavaProjects = BuildHelper.getJavaProjects(javaRefs);
+            List<IProject> javaRefs = ProjectHelper.getReferencedProjects(project);
+            List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaRefs);
 
             helper.finalPackage(
                     new File(projectBinFolderPath, pkgName).getAbsolutePath(),
index e582a91..b43571a 100644 (file)
@@ -137,7 +137,7 @@ public class BuildHelper {
      * @throws AaptExecException
      * @throws AaptResultException
      */
-    public void packageResources(IFile manifestFile, IProject[] libProjects, String resFilter,
+    public void packageResources(IFile manifestFile, List<IProject> libProjects, String resFilter,
             int versionCode, String outputFolder, String outputFilename)
             throws AaptExecException, AaptResultException {
         // need to figure out some path before we can execute aapt;
@@ -208,8 +208,8 @@ public class BuildHelper {
      * @throws DuplicateFileException
      */
     public void finalDebugPackage(String intermediateApk, String dex, String output,
-            final IJavaProject javaProject, IProject[] libProjects,
-            IJavaProject[] referencedJavaProjects, ResourceMarker resMarker)
+            final IJavaProject javaProject, List<IProject> libProjects,
+            List<IJavaProject> referencedJavaProjects, ResourceMarker resMarker)
             throws ApkCreationException, KeytoolException, AndroidLocationException,
             NativeLibInJarException, DuplicateFileException, CoreException {
 
@@ -262,8 +262,8 @@ public class BuildHelper {
      * @throws DuplicateFileException
      */
     public void finalPackage(String intermediateApk, String dex, String output,
-            final IJavaProject javaProject, IProject[] libProjects,
-            IJavaProject[] referencedJavaProjects, String abiFilter, PrivateKey key,
+            final IJavaProject javaProject, List<IProject> libProjects,
+            List<IJavaProject> referencedJavaProjects, String abiFilter, PrivateKey key,
             X509Certificate certificate, ResourceMarker resMarker)
             throws NativeLibInJarException, ApkCreationException, DuplicateFileException,
             CoreException {
@@ -358,16 +358,16 @@ public class BuildHelper {
         IFolder outputFolder = BaseProjectHelper.getOutputFolder(mProject);
 
         // get the list of referenced projects output to add
-        IProject[] javaProjects = ProjectHelper.getReferencedProjects(mProject);
-        IJavaProject[] referencedJavaProjects = BuildHelper.getJavaProjects(javaProjects);
-        String[] projectOutputs = getProjectOutputs(referencedJavaProjects);
+        List<IProject> javaProjects = ProjectHelper.getReferencedProjects(mProject);
+        List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaProjects);
 
-        String[] outputs = new String[1 + projectOutputs.length];
+        // get the project output, and since it's a new list object, just add the outputFolder
+        // of the project directly to it.
+        List<String> projectOutputs = getProjectOutputs(referencedJavaProjects);
 
-        outputs[0] = outputFolder.getLocation().toOSString();
-        System.arraycopy(projectOutputs, 0, outputs, 1, projectOutputs.length);
+        projectOutputs.add(0, outputFolder.getLocation().toOSString());
 
-        return outputs;
+        return projectOutputs.toArray(new String[projectOutputs.size()]);
     }
 
     /**
@@ -721,7 +721,7 @@ public class BuildHelper {
      * @throws CoreException
      */
     private void writeStandardResources(ApkBuilder apkBuilder, IJavaProject javaProject,
-            IJavaProject[] referencedJavaProjects)
+            List<IJavaProject> referencedJavaProjects)
             throws DuplicateFileException, ApkCreationException, SealedApkException,
             CoreException  {
         IWorkspace ws = ResourcesPlugin.getWorkspace();
@@ -834,10 +834,11 @@ public class BuildHelper {
      * they are Android projects.
      *
      * @param referencedJavaProjects the java projects.
-     * @return an array, always. Can be empty.
+     * @return a new list object containing the output folder paths.
      * @throws CoreException
      */
-    private String[] getProjectOutputs(IJavaProject[] referencedJavaProjects) throws CoreException {
+    private List<String> getProjectOutputs(List<IJavaProject> referencedJavaProjects)
+            throws CoreException {
         ArrayList<String> list = new ArrayList<String>();
 
         IWorkspace ws = ResourcesPlugin.getWorkspace();
@@ -865,7 +866,7 @@ public class BuildHelper {
             }
         }
 
-        return list.toArray(new String[list.size()]);
+        return list;
     }
 
     /**
@@ -891,12 +892,12 @@ public class BuildHelper {
     }
 
     /**
-     * Returns an array of {@link IJavaProject} matching the provided {@link IProject} objects.
+     * Returns a list of {@link IJavaProject} matching the provided {@link IProject} objects.
      * @param projects the IProject objects.
-     * @return an array, always. Can be empty.
+     * @return a new list object containing the IJavaProject object for the given IProject objects.
      * @throws CoreException
      */
-    public static IJavaProject[] getJavaProjects(IProject[] projects) throws CoreException {
+    public static List<IJavaProject> getJavaProjects(List<IProject> projects) throws CoreException {
         ArrayList<IJavaProject> list = new ArrayList<IJavaProject>();
 
         for (IProject p : projects) {
@@ -906,7 +907,7 @@ public class BuildHelper {
             }
         }
 
-        return list.toArray(new IJavaProject[list.size()]);
+        return list;
     }
 
     /**
index 4fe237f..ac48739 100644 (file)
@@ -58,6 +58,7 @@ import org.eclipse.jdt.core.JavaModelException;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 public class PostCompilerBuilder extends BaseBuilder {
@@ -206,9 +207,8 @@ public class PostCompilerBuilder extends BaseBuilder {
         // get a project object
         IProject project = getProject();
 
-        // list of referenced projects.
-        IProject[] libProjects = null;
-        IProject[] javaProjects = null;
+        // list of referenced projects. This is a mix of java projects and library projects
+        // and is computed below.
         IProject[] allRefProjects = null;
 
         try {
@@ -220,7 +220,7 @@ public class PostCompilerBuilder extends BaseBuilder {
             }
 
             // get the libraries
-            libProjects = projectState.getFullLibraryProjects();
+            List<IProject> libProjects = projectState.getFullLibraryProjects();
 
             IJavaProject javaProject = JavaCore.create(project);
 
@@ -228,20 +228,16 @@ public class PostCompilerBuilder extends BaseBuilder {
             abortOnBadSetup(javaProject);
 
             // get the list of referenced projects.
-            javaProjects = ProjectHelper.getReferencedProjects(project);
-            IJavaProject[] referencedJavaProjects = BuildHelper.getJavaProjects(
+            List<IProject> javaProjects = ProjectHelper.getReferencedProjects(project);
+            List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(
                     javaProjects);
 
             // mix the java project and the library projects
-            final int libCount = libProjects.length;
-            final int javaCount = javaProjects != null ? javaProjects.length : 0;
-            allRefProjects = new IProject[libCount + javaCount];
-            if (libCount > 0) {
-                System.arraycopy(libProjects, 0, allRefProjects, 0, libCount);
-            }
-            if (javaCount > 0) {
-                System.arraycopy(javaProjects, 0, allRefProjects, libCount, javaCount);
-            }
+            final int size = libProjects.size() + javaProjects.size();
+            ArrayList<IProject> refList = new ArrayList<IProject>(size);
+            refList.addAll(libProjects);
+            refList.addAll(javaProjects);
+            allRefProjects = refList.toArray(new IProject[size]);
 
             // get the output folder, this method returns the path with a trailing
             // separator
@@ -283,7 +279,7 @@ public class PostCompilerBuilder extends BaseBuilder {
                 // if the main resources didn't change, then we check for the library
                 // ones (will trigger resource repackaging too)
                 if ((mPackageResources == false || mBuildFinalPackage == false) &&
-                        libProjects.length > 0) {
+                        libProjects.size() > 0) {
                     for (IProject libProject : libProjects) {
                         delta = getDelta(libProject);
                         if (delta != null) {
@@ -302,9 +298,10 @@ public class PostCompilerBuilder extends BaseBuilder {
 
                 // also go through the delta for all the referenced projects, until we are forced to
                 // compile anyway
-                for (int i = 0 ; i < referencedJavaProjects.length &&
+                final int referencedCount = referencedJavaProjects.size();
+                for (int i = 0 ; i < referencedCount &&
                         (mBuildFinalPackage == false || mConvertToDex == false); i++) {
-                    IJavaProject referencedJavaProject = referencedJavaProjects[i];
+                    IJavaProject referencedJavaProject = referencedJavaProjects.get(i);
                     delta = getDelta(referencedJavaProject.getProject());
                     if (delta != null) {
                         ReferencedProjectDeltaVisitor refProjectDv =
index acec9b1..dc3bf9e 100644 (file)
@@ -56,6 +56,7 @@ import org.eclipse.jdt.core.JavaCore;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -218,8 +219,9 @@ public class PreCompilerBuilder extends BaseBuilder {
         // get a project object
         IProject project = getProject();
 
-        // list of referenced projects.
-        IProject[] libProjects = null;
+        // For the PreCompiler, only the library projects are considered Referenced projects,
+        // as only those projects have an impact on what is generated by this builder.
+        List<IProject> libProjects = null;
 
         try {
             mDerivedProgressMonitor.reset();
@@ -292,7 +294,7 @@ public class PreCompilerBuilder extends BaseBuilder {
 
                     // if the main resources didn't change, then we check for the library
                     // ones (will trigger resource recompilation too)
-                    if (mMustCompileResources == false && libProjects.length > 0) {
+                    if (mMustCompileResources == false && libProjects.size() > 0) {
                         for (IProject libProject : libProjects) {
                             delta = getDelta(libProject);
                             if (delta != null) {
@@ -516,7 +518,7 @@ public class PreCompilerBuilder extends BaseBuilder {
             mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
         }
 
-        return libProjects;
+        return libProjects.toArray(new IProject[libProjects.size()]);
     }
 
     @Override
@@ -585,7 +587,7 @@ public class PreCompilerBuilder extends BaseBuilder {
      * @throws CoreException
      */
     private void handleResources(IProject project, String javaPackage, IAndroidTarget projectTarget,
-            IFile manifest, IProject[] libProjects) throws CoreException {
+            IFile manifest, List<IProject> libProjects) throws CoreException {
         // get the resource folder
         IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES);
 
index ca58dce..48d6cb4 100644 (file)
@@ -33,6 +33,7 @@ import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarkerDelta;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.CoreException;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -166,9 +167,50 @@ public final class LayoutReloadMonitor {
          * This records the changes for each project, but does not notify listeners.
          */
         public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
-            // get the file project
+            // get the file's project
             IProject project = file.getProject();
 
+            boolean hasAndroidNature = false;
+            try {
+                hasAndroidNature = project.hasNature(AndroidConstants.NATURE_DEFAULT);
+            } catch (CoreException e) {
+                // do nothing if the nature cannot be queried.
+                return;
+            }
+
+            if (hasAndroidNature) {
+                // project is an Android project, it's the one being affected
+                // directly by its own file change.
+                // Note that resource change is handled separately, so there's no need to
+                // figure out if the project is a library and to update its main project(s).
+                processFileChanged(file, project);
+            } else {
+                // check the projects depending on it, if they are Android project, update them.
+                IProject[] referencingProjects = project.getReferencingProjects();
+
+                for (IProject p : referencingProjects) {
+                    try {
+                        hasAndroidNature = p.hasNature(AndroidConstants.NATURE_DEFAULT);
+                    } catch (CoreException e) {
+                        // do nothing if the nature cannot be queried.
+                        continue;
+                    }
+
+                    if (hasAndroidNature) {
+                        // the changed project is a dependency on an Android project,
+                        // update the main project.
+                        processFileChanged(file, p);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Processes a file change for a given project which may or may not be the file's project.
+         * @param file the changed file
+         * @param project the project impacted by the file change.
+         */
+        private void processFileChanged(IFile file, IProject project) {
             // if this project has already been marked as modified, we do nothing.
             ChangeFlags changeFlags = mProjectFlags.get(project);
             if (changeFlags != null && changeFlags.isAllTrue()) {
index e1c6584..e7cbaea 100644 (file)
@@ -53,6 +53,13 @@ public final class ProjectCallback implements ILegacyCallback {
     private ProjectClassLoader mLoader = null;
     private LayoutLog mLogger;
 
+    /**
+     * Creates a new {@link ProjectCallback} to be used with the layout lib.
+     *
+     * @param classLoader The class loader that was used to load layoutlib.jar
+     * @param projectRes the {@link ProjectResources} for the project.
+     * @param project the project.
+     */
     public ProjectCallback(ClassLoader classLoader, ProjectResources projectRes, IProject project) {
         mParentClassLoader = classLoader;
         mProjectRes = projectRes;
index 17fc1e2..ddb4321 100644 (file)
@@ -60,6 +60,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
+import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 
@@ -117,7 +118,7 @@ public final class ExportHelper {
 
             // get the list of library projects
             ProjectState projectState = Sdk.getProjectState(project);
-            IProject[] libProjects = projectState.getFullLibraryProjects();
+            List<IProject> libProjects = projectState.getFullLibraryProjects();
 
             // Step 1. Package the resources.
 
@@ -196,8 +197,8 @@ public final class ExportHelper {
             }
 
             IJavaProject javaProject = JavaCore.create(project);
-            IProject[] javaProjects = ProjectHelper.getReferencedProjects(project);
-            IJavaProject[] referencedJavaProjects = BuildHelper.getJavaProjects(
+            List<IProject> javaProjects = ProjectHelper.getReferencedProjects(project);
+            List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(
                     javaProjects);
 
             helper.executeDx(javaProject, dxInput, dexFile.getAbsolutePath());
index 01479bf..91e2380 100644 (file)
@@ -535,7 +535,7 @@ public final class ProjectHelper {
 
         // test the referenced projects if needed.
         if (includeReferencedProjects) {
-            IProject[] projects = getReferencedProjects(project);
+            List<IProject> projects = getReferencedProjects(project);
 
             for (IProject p : projects) {
                 if (hasError(p, false)) {
@@ -651,10 +651,10 @@ public final class ProjectHelper {
     /**
      * Returns the list of referenced project that are opened and Java projects.
      * @param project
-     * @return list of opened referenced java project.
+     * @return a new list object containing the opened referenced java project.
      * @throws CoreException
      */
-    public static IProject[] getReferencedProjects(IProject project) throws CoreException {
+    public static List<IProject> getReferencedProjects(IProject project) throws CoreException {
         IProject[] projects = project.getReferencedProjects();
 
         ArrayList<IProject> list = new ArrayList<IProject>();
@@ -665,7 +665,7 @@ public final class ProjectHelper {
             }
         }
 
-        return list.toArray(new IProject[list.size()]);
+        return list;
     }
 
 
index 5244618..0deb89c 100644 (file)
 package com.android.ide.eclipse.adt.internal.resources.manager;
 
 import com.android.ide.eclipse.adt.AndroidConstants;
+import com.android.ide.eclipse.adt.internal.build.BuildHelper;
+import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaProject;
@@ -35,6 +38,7 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * ClassLoader able to load class from output of an Eclipse project.
@@ -52,30 +56,71 @@ public final class ProjectClassLoader extends ClassLoader {
 
     @Override
     protected Class<?> findClass(String name) throws ClassNotFoundException {
+        // if we are here through a child classloader, throw an exception.
+        if (mInsideJarClassLoader) {
+            throw new ClassNotFoundException(name);
+        }
+
+        // attempt to load the class from the main project
+        Class<?> clazz = loadFromProject(mJavaProject, name);
+
+        if (clazz != null) {
+            return clazz;
+        }
+
+        // attempt to load the class from the jar dependencies
+        clazz = loadClassFromJar(name);
+        if (clazz != null) {
+            return clazz;
+        }
+
+        // attempt to load the class from the referenced projects.
+        try {
+            List<IProject> javaProjects = ProjectHelper.getReferencedProjects(
+                    mJavaProject.getProject());
+            List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaProjects);
+
+            for (IJavaProject javaProject : referencedJavaProjects) {
+                clazz = loadFromProject(javaProject, name);
+
+                if (clazz != null) {
+                    return clazz;
+                }
+            }
+        } catch (CoreException e) {
+            // log exception?
+        }
+
+        throw new ClassNotFoundException(name);
+    }
+
+    /**
+     * Attempts to load a class from a project output folder.
+     * @param project the project to load the class from
+     * @param name the name of the class
+     * @return a class object if found, null otherwise.
+     */
+    private Class<?> loadFromProject(IJavaProject project, String name) {
         try {
             // get the project output folder.
             IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-            IPath outputLocation = mJavaProject.getOutputLocation();
+            IPath outputLocation = project.getOutputLocation();
             IResource outRes = root.findMember(outputLocation);
             if (outRes == null) {
-                throw new ClassNotFoundException(name);
+                return null;
             }
 
             File outFolder = new File(outRes.getLocation().toOSString());
 
             // get the class name segments
             String[] segments = name.split("\\."); //$NON-NLS-1$
-            
+
+            // try to load the class from the bin folder of the project.
             File classFile = getFile(outFolder, segments, 0);
             if (classFile == null) {
-                if (mInsideJarClassLoader == false) {
-                    // if no file matching the class name was found, look in the 3rd party jars
-                    return loadClassFromJar(name);
-                } else {
-                    throw new ClassNotFoundException(name);
-                }
+                return null;
             }
-            
+
             // load the content of the file and create the class.
             FileInputStream fis = new FileInputStream(classFile);
             byte[] data = new byte[(int)classFile.length()];
@@ -86,7 +131,7 @@ public final class ProjectClassLoader extends ClassLoader {
                 data = null;
             }
             fis.close();
-            
+
             if (data != null) {
                 Class<?> clazz = defineClass(null, data, 0, read);
                 if (clazz != null) {
@@ -94,12 +139,12 @@ public final class ProjectClassLoader extends ClassLoader {
                 }
             }
         } catch (Exception e) {
-            throw new ClassNotFoundException(e.getMessage());
+            // log the exception?
         }
 
-        throw new ClassNotFoundException(name);
+        return null;
     }
-    
+
     /**
      * Returns the File matching the a certain path from a root {@link File}.
      * <p/>The methods checks that the file ends in .class even though the last segment
@@ -121,7 +166,7 @@ public final class ProjectClassLoader extends ClassLoader {
 
         // we're at the last segments. we look for a matching <file>.class
         if (index == segments.length - 1) {
-            toMatch = toMatch + ".class"; 
+            toMatch = toMatch + ".class";
 
             if (files != null) {
                 for (File file : files) {
@@ -130,13 +175,13 @@ public final class ProjectClassLoader extends ClassLoader {
                     }
                 }
             }
-            
+
             // no match? abort.
             throw new FileNotFoundException();
         }
-        
+
         String innerClassName = null;
-        
+
         if (files != null) {
             for (File file : files) {
                 if (file.isDirectory()) {
@@ -151,43 +196,47 @@ public final class ProjectClassLoader extends ClassLoader {
                             sb.append(segments[i]);
                         }
                         sb.append(".class");
-                        
+
                         innerClassName = sb.toString();
                     }
-                    
+
                     if (file.getName().equals(innerClassName)) {
                         return file;
                     }
                 }
             }
         }
-        
+
         return null;
     }
-    
+
     /**
      * Loads a class from the 3rd party jar present in the project
-     * @throws ClassNotFoundException
+     *
+     * @return the class loader or null if not found.
      */
-    private Class<?> loadClassFromJar(String name) throws ClassNotFoundException {
+    private Class<?> loadClassFromJar(String name) {
         if (mJarClassLoader == null) {
             // get the OS path to all the external jars
             URL[] jars = getExternalJars();
-            
+
             mJarClassLoader = new URLClassLoader(jars, this /* parent */);
         }
-        
+
         try {
             // because a class loader always look in its parent loader first, we need to know
             // that we are querying the jar classloader. This will let us know to not query
             // it again for classes we don't find, or this would create an infinite loop.
             mInsideJarClassLoader = true;
             return mJarClassLoader.loadClass(name);
+        } catch (ClassNotFoundException e) {
+            // not found? return null.
+            return null;
         } finally {
             mInsideJarClassLoader = false;
         }
     }
-    
+
     /**
      * Returns an array of external jar files used by the project.
      * @return an array of OS-specific absolute file paths
@@ -195,7 +244,7 @@ public final class ProjectClassLoader extends ClassLoader {
     private final URL[] getExternalJars() {
         // get a java project from it
         IJavaProject javaProject = JavaCore.create(mJavaProject.getProject());
-        
+
         IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
 
         ArrayList<URL> oslibraryList = new ArrayList<URL>();
@@ -206,7 +255,7 @@ public final class ProjectClassLoader extends ClassLoader {
                         e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
                     // if this is a classpath variable reference, we resolve it.
                     if (e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
-                        e = JavaCore.getResolvedClasspathEntry(e); 
+                        e = JavaCore.getResolvedClasspathEntry(e);
                     }
 
                     // get the IPath
index 1209eac..1580906 100644 (file)
@@ -418,7 +418,7 @@ public class ProjectResources implements IResourceRepository {
         if (mProject != null) {
             ProjectState state = Sdk.getProjectState(mProject);
             if (state != null) {
-                IProject[] libraries = state.getFullLibraryProjects();
+                List<IProject> libraries = state.getFullLibraryProjects();
 
                 ResourceManager resMgr = ResourceManager.getInstance();
 
@@ -426,8 +426,8 @@ public class ProjectResources implements IResourceRepository {
                 // one will have priority over the 2nd one. So it's better to loop in the inverse
                 // order and fill the map with resources that will be overwritten by higher
                 // priority resources
-                for (int i = libraries.length - 1 ; i >= 0 ; i--) {
-                    IProject library = libraries[i];
+                for (int i = libraries.size() - 1 ; i >= 0 ; i--) {
+                    IProject library = libraries.get(i);
 
                     ProjectResources libRes = resMgr.getProjectResources(library);
                     if (libRes != null) {
index dd09355..0d58201 100644 (file)
@@ -165,7 +165,7 @@ public final class ProjectState {
     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 IProject[] mLibraryProjects = new IProject[0];
+    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.
@@ -330,13 +330,13 @@ public final class ProjectState {
 
     /**
      * Returns all the <strong>resolved</strong> library projects, including indirect dependencies.
-     * The array is ordered to match the library priority order for resource processing with
+     * 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. May be an empty list.
+     * @return the resolved projects as an unmodifiable list. May be an empty.
      */
-    public IProject[] getFullLibraryProjects() {
+    public List<IProject> getFullLibraryProjects() {
         return mLibraryProjects;
     }
 
@@ -608,7 +608,7 @@ public final class ProjectState {
             buildFullLibraryDependencies(mLibraries, list);
         }
 
-        mLibraryProjects = list.toArray(new IProject[list.size()]);
+        mLibraryProjects = Collections.unmodifiableList(list);
     }
 
     /**
index c13cc73..a7e8647 100644 (file)
@@ -781,7 +781,7 @@ public final class Sdk  {
                         LibraryState libState = projectState.getLibrary(project);
                         if (libState != null) {
                             // get the current libraries.
-                            IProject[] oldLibraries = projectState.getFullLibraryProjects();
+                            List<IProject> oldLibraries = projectState.getFullLibraryProjects();
 
                             // the unlink below will work in the job, but we need to close
                             // the library right away.
@@ -924,7 +924,7 @@ public final class Sdk  {
                                     projectState.getProject().getFullPath());
 
                             // get the current libraries
-                            IProject[] oldLibraries = projectState.getFullLibraryProjects();
+                            List<IProject> oldLibraries = projectState.getFullLibraryProjects();
 
                             // update the library for the main project.
                             LibraryState libState = projectState.updateLibrary(
@@ -977,7 +977,7 @@ public final class Sdk  {
                     boolean wasLibrary = state.isLibrary();
 
                     // get the current list of project dependencies
-                    IProject[] oldLibraries = state.getFullLibraryProjects();
+                    List<IProject> oldLibraries = state.getFullLibraryProjects();
 
                     LibraryDifference diff = state.reloadProperties();
 
@@ -1511,9 +1511,9 @@ public final class Sdk  {
      *            {@link ProjectState#getFullLibraryProjects()} before the ProjectState is updated.
      * @return null if there no action to take, or a {@link LinkUpdateBundle} object to run.
      */
-    private LinkUpdateBundle getLinkBundle(ProjectState project, IProject[] oldLibraries) {
+    private LinkUpdateBundle getLinkBundle(ProjectState project, List<IProject> oldLibraries) {
         // get the new full list of projects
-        IProject[] newLibraries = project.getFullLibraryProjects();
+        List<IProject> newLibraries = project.getFullLibraryProjects();
 
         // and build the real difference. A list of new projects and a list of
         // removed project.
@@ -1634,7 +1634,7 @@ public final class Sdk  {
             // we add them to the list so that can be updated as well.
             for (ProjectState projectState : sProjectStateMap.values()) {
                 // record the current library dependencies
-                IProject[] oldLibraries = projectState.getFullLibraryProjects();
+                List<IProject> oldLibraries = projectState.getFullLibraryProjects();
 
                 boolean needLibraryDependenciesUpdated = false;
                 for (ProjectState library : libraries) {