diff options
author | Xavier Ducrohet <xav@android.com> | 2012-03-02 17:51:09 -0800 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2012-03-02 18:09:44 -0800 |
commit | 906fec2a94663ad1aa76aad55fdf2cbb97324d66 (patch) | |
tree | 1eee9c01de6008fb0a3d866008ac83e036c9f0f4 /eclipse | |
parent | 57f1082fa77411a2a171387fb279e32b2a6945a5 (diff) | |
download | sdk-906fec2a94663ad1aa76aad55fdf2cbb97324d66.zip sdk-906fec2a94663ad1aa76aad55fdf2cbb97324d66.tar.gz sdk-906fec2a94663ad1aa76aad55fdf2cbb97324d66.tar.bz2 |
Fix issue with automatic jar dependency.
The previous commit relied on a cached version of the Android container
to add jar in to the list. This properly look for inside the libs folder
for jar file, and restrict looking at project classpathes to only
Java-only projects.
Also hooked into the file change listener of the Sdk class to
update the project container when a file is added to removed
to a libs folder.
Change-Id: Ia7d13b5544a27d0e8baab4873654a74b0a7889e6
Diffstat (limited to 'eclipse')
2 files changed, 107 insertions, 19 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java index f21eb1f..7a19344 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java @@ -121,8 +121,8 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer return null; } + // First check that the project has a library-type container. try { - // First check that the project has a library-type container. IClasspathEntry[] rawClasspath = javaProject.getRawClasspath(); IClasspathEntry[] oldRawClasspath = rawClasspath; @@ -160,6 +160,18 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer // check if the project has a valid target. ProjectState state = Sdk.getProjectState(iProject); + /* + * At this point we're going to gather a list of all that need to go in the + * dependency container. + * - Library project outputs (direct and indirect) + * - Java project output (those can be indirectly referenced through library projects + * or other other Java projects) + * - Jar files: + * + inside this project's libs/ + * + inside the library projects' libs/ + * + inside the referenced Java projects' classpath + */ + List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); @@ -167,7 +179,9 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer // list of java project dependencies and jar files that will be built while // going through the library projects. Set<File> jarFiles = new HashSet<File>(); - HashSet<IProject> refProjects = new HashSet<IProject>(); + Set<IProject> refProjects = new HashSet<IProject>(); + + // process all the libraries List<IProject> libProjects = state.getFullLibraryProjects(); for (IProject libProject : libProjects) { @@ -190,20 +204,26 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer } } + // we can directly add a CPE for this jar as there's no risk of a duplicate. IClasspathEntry entry = JavaCore.newLibraryEntry( jarIFile.getLocation(), sourceFolder, // source attachment path null); // default source attachment root path. entries.add(entry); + + // now, gather the content of this library project's libs folder. + getJarListFromLibsFolder(libProject, jarFiles); } // get project dependencies - processReferencedProjects(libProject, refProjects, jarFiles, true); + processReferencedProjects(libProject, refProjects, jarFiles); } - // now get the jar files for the referenced project for this project. - processReferencedProjects(iProject, refProjects, jarFiles, false); + // now process this projects' referenced projects + processReferencedProjects(iProject, refProjects, jarFiles); + // and its own jar files from libs + getJarListFromLibsFolder(iProject, jarFiles); // annotations support for older version of android if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) { @@ -267,10 +287,7 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer private static void processReferencedProjects(IProject project, - Set<IProject> projects, Set<File> jarFiles, boolean includeAndroidContainer) { - // get the jar dependencies of the project in the list - getJarDependencies(project, jarFiles, includeAndroidContainer); - + Set<IProject> projects, Set<File> jarFiles) { try { IProject[] refs = project.getReferencedProjects(); for (IProject p : refs) { @@ -280,8 +297,11 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer // add this project to the list projects.add(p); - // and then process this project too. - processReferencedProjects(p, projects, jarFiles, includeAndroidContainer); + // get the jar dependencies of the project in the list + getJarListFromClasspath(p, jarFiles); + + // and then process the referenced project by this project too. + processReferencedProjects(p, projects, jarFiles); } } } catch (CoreException e) { @@ -289,9 +309,37 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer } } - private static void getJarDependencies(IProject p, Set<File> jarFiles, - boolean includeAndroidContainer) { - IJavaProject javaProject = JavaCore.create(p); + /** + * Finds all the jar files inside a project's libs folder. + * @param project + * @param jarFiles + */ + private static void getJarListFromLibsFolder(IProject project, Set<File> jarFiles) { + IFolder libsFolder = project.getFolder(SdkConstants.FD_NATIVE_LIBS); + if (libsFolder.exists()) { + try { + IResource[] members = libsFolder.members(); + for (IResource member : members) { + if (member.getType() == IResource.FILE && + AdtConstants.EXT_JAR.equalsIgnoreCase(member.getFileExtension())) { + jarFiles.add(member.getLocation().toFile()); + } + } + } catch (CoreException e) { + // can't get the list? ignore this folder. + } + } + } + + /** + * Finds all the jars a given project depends on by looking at the classpath. + * This must be a non android project, as android project have container that really + * we shouldn't go through. + * @param project the project to query + * @param jarFiles the list of file to fill. + */ + private static void getJarListFromClasspath(IProject project, Set<File> jarFiles) { + IJavaProject javaProject = JavaCore.create(project); IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot(); // we could use IJavaProject.getResolvedClasspath directly, but we actually @@ -306,10 +354,7 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { handleClasspathEntry(e, wsRoot, jarFiles); - } else if (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER && - (includeAndroidContainer || - e.getPath().toString().startsWith( - "com.android.ide.eclipse.adt.") == false)) { + } else if (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { // get the container. try { IClasspathContainer container = JavaCore.getClasspathContainer( 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 index 092ffb5..63f381f 100644 --- 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 @@ -83,6 +83,7 @@ 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; @@ -712,7 +713,8 @@ public final class Sdk { // is called back during registration with project opened in the workspace. monitor.addResourceEventListener(mResourceEventListener); monitor.addProjectListener(mProjectListener); - monitor.addFileListener(mFileListener, IResourceDelta.CHANGED | IResourceDelta.ADDED); + monitor.addFileListener(mFileListener, + IResourceDelta.CHANGED | IResourceDelta.ADDED | IResourceDelta.REMOVED); // pre-compute some paths mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() + @@ -1062,6 +1064,47 @@ public final class Sdk { // 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 (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); + + 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. } } }; |