aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2012-03-02 11:59:37 -0800
committerXavier Ducrohet <xav@android.com>2012-03-02 14:19:03 -0800
commit81c5fb5448a6342cb3bb29ea501fccf95573288c (patch)
tree271023addc7b272659be2ee8fad2a32cc972e388 /eclipse/plugins
parent59efe32b418e494e681e9e6c741bfded4710e947 (diff)
downloadsdk-81c5fb5448a6342cb3bb29ea501fccf95573288c.zip
sdk-81c5fb5448a6342cb3bb29ea501fccf95573288c.tar.gz
sdk-81c5fb5448a6342cb3bb29ea501fccf95573288c.tar.bz2
Automatically add dependencies to Eclipse project.
add libs/*.jar from Library Projects, add Java-only projects only that referenced in Library Projects (recursively so that Java projects that reference other Java projects pull those in too). Also add jar files referenced by Java-only projects. Change-Id: Ic2b10107153e0576f5e6ba34d50bd3fef95c3fea
Diffstat (limited to 'eclipse/plugins')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml51
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java73
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseClasspathContainerInitializer.java111
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java192
6 files changed, 327 insertions, 121 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 0cd0354..e5e8229 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -57,6 +57,35 @@
<super type="org.eclipse.core.resources.textmarker" />
<persistent value="true" />
</extension>
+ <extension
+ id="com.android.ide.eclipse.adt.adtProblem"
+ name="Android ADT Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker" />
+ <super type="org.eclipse.core.resources.textmarker" />
+ <persistent value="true" />
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.adt.targetProblem"
+ name="Android Target Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker" />
+ <persistent value="false" />
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.adt.dependencyProblem"
+ name="Android Dependency Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker" />
+ <persistent value="false" />
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.adt.packagingProblem"
+ name="Android Packaging Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker" />
+ <persistent value="true" />
+ </extension>
<extension point="org.eclipse.ui.ide.markerResolution">
<markerResolutionGenerator
markerType="com.android.ide.eclipse.adt.lintProblem"
@@ -385,28 +414,6 @@
<extension point="org.eclipse.core.runtime.preferences">
<initializer class="com.android.ide.eclipse.adt.internal.preferences.AdtPrefs" />
</extension>
- <extension
- id="com.android.ide.eclipse.adt.adtProblem"
- name="Android ADT Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker" />
- <super type="org.eclipse.core.resources.textmarker" />
- <persistent value="true" />
- </extension>
- <extension
- id="com.android.ide.eclipse.adt.targetProblem"
- name="Android Target Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker" />
- <persistent value="false" />
- </extension>
- <extension
- id="com.android.ide.eclipse.adt.packagingProblem"
- name="Android Packaging Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker" />
- <persistent value="true" />
- </extension>
<extension point="org.eclipse.ui.perspectiveExtensions">
<perspectiveExtension targetID="org.eclipse.jdt.ui.JavaPerspective">
<newWizardShortcut id="com.android.ide.eclipse.adt.project.NewProjectWizard" />
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
index 0a1f2bb..0b619fb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
@@ -214,10 +214,16 @@ public class AdtConstants {
public final static String MARKER_ADT = AdtPlugin.PLUGIN_ID + ".adtProblem"; //$NON-NLS-1$
/** Marker for Android Target errors.
- * This is not cleared on each like other markers. Instead, it's cleared
+ * This is not cleared on each build like other markers. Instead, it's cleared
* when an AndroidClasspathContainerInitializer has succeeded in creating an
* AndroidClasspathContainer */
public final static String MARKER_TARGET = AdtPlugin.PLUGIN_ID + ".targetProblem"; //$NON-NLS-1$
+ /** Marker for Android Dependency errors.
+ * This is not cleared on each build like other markers. Instead, it's cleared
+ * when a LibraryClasspathContainerInitializer has succeeded in creating a
+ * LibraryClasspathContainer */
+ public final static String MARKER_DEPENDENCY = AdtPlugin.PLUGIN_ID + ".dependencyProblem"; //$NON-NLS-1$
+
/** aapt marker error when running the compile command, only to be used
* in {@link PreCompilerBuilder} */
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
index ef3a7ac..e915544 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
@@ -799,9 +799,11 @@ public class BuildHelper {
String configFilter, int versionCode) throws AaptExecException, AaptResultException {
IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+ @SuppressWarnings("deprecation") String aapt = target.getPath(IAndroidTarget.AAPT);
+
// Create the command line.
ArrayList<String> commandArray = new ArrayList<String>();
- commandArray.add(target.getPath(IAndroidTarget.AAPT));
+ commandArray.add(aapt);
commandArray.add(aaptCommand);
if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
commandArray.add("-v"); //$NON-NLS-1$
@@ -1066,8 +1068,13 @@ public class BuildHelper {
IPath path = e.getPath();
IResource resource = wsRoot.findMember(path);
- // case of a jar file (which could be relative to the workspace or a full path)
- if (AdtConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
+
+ if (resource != null && resource.getType() == IResource.PROJECT) {
+ // if it's a project we should just ignore it because it's going to be added
+ // later when we add all the referenced projects.
+
+ } else if (AdtConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
+ // case of a jar file (which could be relative to the workspace or a full path)
if (resource != null && resource.exists() &&
resource.getType() == IResource.FILE) {
oslibraryList.add(resource.getLocation().toOSString());
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java
index b2be4a1..c2493e3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java
@@ -26,22 +26,15 @@ import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.SdkConstants;
-import org.eclipse.core.resources.IMarker;
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.FileLocator;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
@@ -66,7 +59,7 @@ import java.util.regex.Pattern;
* Classpath container initializer responsible for binding {@link AndroidClasspathContainer} to
* {@link IProject}s. This removes the hard-coded path to the android.jar.
*/
-public class AndroidClasspathContainerInitializer extends ClasspathContainerInitializer {
+public class AndroidClasspathContainerInitializer extends BaseClasspathContainerInitializer {
public static final String NULL_API_URL = "<null>"; //$NON-NLS-1$
@@ -276,69 +269,7 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
};
}
} finally {
- if (markerMessage != null) {
- // log the error and put the marker on the project if we can.
- if (outputToConsole) {
- AdtPlugin.printErrorToConsole(iProject, markerMessage);
- }
-
- try {
- BaseProjectHelper.markProject(iProject, AdtConstants.MARKER_TARGET,
- markerMessage, IMarker.SEVERITY_ERROR, IMarker.PRIORITY_HIGH);
- } catch (CoreException e) {
- // In some cases, the workspace may be locked for modification when we
- // pass here.
- // We schedule a new job to put the marker after.
- final String fmessage = markerMessage;
- Job markerJob = new Job("Android SDK: Resolving error markers") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- BaseProjectHelper.markProject(iProject,
- AdtConstants.MARKER_TARGET,
- fmessage, IMarker.SEVERITY_ERROR,
- IMarker.PRIORITY_HIGH);
- } catch (CoreException e2) {
- return e2.getStatus();
- }
-
- return Status.OK_STATUS;
- }
- };
-
- // build jobs are run after other interactive jobs
- markerJob.setPriority(Job.BUILD);
- markerJob.schedule();
- }
- } else {
- // no error, remove potential MARKER_TARGETs.
- try {
- if (iProject.exists()) {
- iProject.deleteMarkers(AdtConstants.MARKER_TARGET, true,
- IResource.DEPTH_INFINITE);
- }
- } catch (CoreException ce) {
- // In some cases, the workspace may be locked for modification when we pass
- // here, so we schedule a new job to put the marker after.
- Job markerJob = new Job("Android SDK: Resolving error markers") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- iProject.deleteMarkers(AdtConstants.MARKER_TARGET, true,
- IResource.DEPTH_INFINITE);
- } catch (CoreException e2) {
- return e2.getStatus();
- }
-
- return Status.OK_STATUS;
- }
- };
-
- // build jobs are run after other interactive jobs
- markerJob.setPriority(Job.BUILD);
- markerJob.schedule();
- }
- }
+ processError(iProject, markerMessage, AdtConstants.MARKER_TARGET, outputToConsole);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseClasspathContainerInitializer.java
new file mode 100644
index 0000000..403b17b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseClasspathContainerInitializer.java
@@ -0,0 +1,111 @@
+/*
+ * 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.project;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.ClasspathContainerInitializer;
+
+/**
+ * Base CPC initializer providing support to all our initializer.
+ *
+ */
+abstract class BaseClasspathContainerInitializer extends ClasspathContainerInitializer {
+
+
+ /**
+ * Adds an error to a project, or remove all markers if error message is null
+ * @param project the project to modify
+ * @param errorMessage the errorMessage or null to remove errors.
+ * @param markerType the marker type to be used.
+ * @param outputToConsole whether to output to the console.
+ */
+ protected static void processError(final IProject project, final String errorMessage,
+ final String markerType, boolean outputToConsole) {
+ if (errorMessage != null) {
+ // log the error and put the marker on the project if we can.
+ if (outputToConsole) {
+ AdtPlugin.printErrorToConsole(project, errorMessage);
+ }
+
+ try {
+ BaseProjectHelper.markProject(project, markerType,
+ errorMessage, IMarker.SEVERITY_ERROR, IMarker.PRIORITY_HIGH);
+ } catch (CoreException e) {
+ // In some cases, the workspace may be locked for modification when we
+ // pass here.
+ // We schedule a new job to put the marker after.
+ final String fmessage = errorMessage;
+ Job markerJob = new Job("Android SDK: Resolving error markers") {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ BaseProjectHelper.markProject(project,
+ markerType,
+ fmessage, IMarker.SEVERITY_ERROR,
+ IMarker.PRIORITY_HIGH);
+ } catch (CoreException e2) {
+ return e2.getStatus();
+ }
+
+ return Status.OK_STATUS;
+ }
+ };
+
+ // build jobs are run after other interactive jobs
+ markerJob.setPriority(Job.BUILD);
+ markerJob.schedule();
+ }
+ } else {
+ // no error, remove existing markers.
+ try {
+ if (project.exists()) {
+ project.deleteMarkers(markerType, true,
+ IResource.DEPTH_INFINITE);
+ }
+ } catch (CoreException ce) {
+ // In some cases, the workspace may be locked for modification when we pass
+ // here, so we schedule a new job to put the marker after.
+ Job markerJob = new Job("Android SDK: Resolving error markers") {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ project.deleteMarkers(markerType, true,
+ IResource.DEPTH_INFINITE);
+ } catch (CoreException e2) {
+ return e2.getStatus();
+ }
+
+ return Status.OK_STATUS;
+ }
+ };
+
+ // build jobs are run after other interactive jobs
+ markerJob.setPriority(Job.BUILD);
+ markerJob.schedule();
+ }
+ }
+ }
+}
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 d012bc8..f21eb1f 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
@@ -18,20 +18,24 @@ package com.android.ide.eclipse.adt.internal.project;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AndroidPrintStream;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.SdkConstants;
+import com.android.sdklib.build.JarListSanitizer;
+import com.android.sdklib.build.JarListSanitizer.DifferentLibException;
+import com.android.sdklib.build.JarListSanitizer.Sha1Exception;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
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.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
@@ -40,11 +44,11 @@ import org.eclipse.jdt.core.JavaModelException;
import java.io.File;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
-public class LibraryClasspathContainerInitializer extends ClasspathContainerInitializer {
+public class LibraryClasspathContainerInitializer extends BaseClasspathContainerInitializer {
public LibraryClasspathContainerInitializer() {
}
@@ -160,6 +164,9 @@ public class LibraryClasspathContainerInitializer extends ClasspathContainerInit
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ // 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>();
List<IProject> libProjects = state.getFullLibraryProjects();
@@ -192,24 +199,11 @@ public class LibraryClasspathContainerInitializer extends ClasspathContainerInit
}
// get project dependencies
- try {
- IProject[] refs = libProject.getReferencedProjects();
- refProjects.addAll(Arrays.asList(refs));
- } catch (CoreException e) {
- }
+ processReferencedProjects(libProject, refProjects, jarFiles, true);
}
- for (IProject p : refProjects) {
- // ignore if it's an Android project, or if it's not a Java Project
- try {
- if (p.hasNature(JavaCore.NATURE_ID) &&
- p.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
- entries.add(JavaCore.newProjectEntry(p.getFullPath()));
- }
- } catch (CoreException e) {
- // can't get the nature? ignore the project.
- }
- }
+ // now get the jar files for the referenced project for this project.
+ processReferencedProjects(iProject, refProjects, jarFiles, false);
// annotations support for older version of android
if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) {
@@ -217,14 +211,53 @@ public class LibraryClasspathContainerInitializer extends ClasspathContainerInit
SdkConstants.FD_TOOLS + File.separator + SdkConstants.FD_SUPPORT +
File.separator + SdkConstants.FN_ANNOTATIONS_JAR);
- IClasspathEntry entry = JavaCore.newLibraryEntry(
- new Path(annotationsJar.getAbsolutePath()),
- null, // source attachment path
- null); // default source attachment root path.
+ jarFiles.add(annotationsJar);
+ }
- entries.add(0, entry);
+ // now add a classpath entry for each Java project (this is a set so dups are already
+ // removed)
+ for (IProject p : refProjects) {
+ entries.add(JavaCore.newProjectEntry(p.getFullPath()));
}
+ // and process the jar files list, but first sanitize it to remove dups.
+ JarListSanitizer sanitizer = new JarListSanitizer(
+ iProject.getFolder(SdkConstants.FD_OUTPUT).getLocation().toFile(),
+ new AndroidPrintStream(iProject, null /*prefix*/,
+ AdtPlugin.getOutStream()));
+
+ String errorMessage = null;
+
+ try {
+ List<File> sanitizedList = sanitizer.sanitize(jarFiles);
+
+ for (File jarFile : sanitizedList) {
+ if (jarFile instanceof CPEFile) {
+ CPEFile cpeFile = (CPEFile) jarFile;
+ IClasspathEntry e = cpeFile.getClasspathEntry();
+
+ entries.add(JavaCore.newLibraryEntry(
+ e.getPath(),
+ e.getSourceAttachmentPath(),
+ e.getSourceAttachmentRootPath(),
+ e.getAccessRules(),
+ e.getExtraAttributes(),
+ e.isExported()));
+ } else {
+ entries.add(JavaCore.newLibraryEntry(new Path(jarFile.getAbsolutePath()),
+ null /*sourceAttachmentPath*/, null /*sourceAttachmentRootPath*/));
+ }
+ }
+ } catch (DifferentLibException e) {
+ errorMessage = e.getMessage();
+ AdtPlugin.printErrorToConsole(iProject, (Object[]) e.getDetails());
+ } catch (Sha1Exception e) {
+ errorMessage = e.getMessage();
+ }
+
+ processError(iProject, errorMessage, AdtConstants.MARKER_DEPENDENCY,
+ true /*outputToConsole*/);
+
return new AndroidClasspathContainer(
entries.toArray(new IClasspathEntry[entries.size()]),
new Path(AdtConstants.CONTAINER_LIBRARIES),
@@ -232,4 +265,115 @@ public class LibraryClasspathContainerInitializer extends ClasspathContainerInit
IClasspathContainer.K_APPLICATION);
}
+
+ 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);
+
+ try {
+ IProject[] refs = project.getReferencedProjects();
+ for (IProject p : refs) {
+ // ignore if it's an Android project, or if it's not a Java Project
+ if (p.hasNature(JavaCore.NATURE_ID) &&
+ p.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
+ // add this project to the list
+ projects.add(p);
+
+ // and then process this project too.
+ processReferencedProjects(p, projects, jarFiles, includeAndroidContainer);
+ }
+ }
+ } catch (CoreException e) {
+ // can't get the referenced projects? ignore
+ }
+ }
+
+ private static void getJarDependencies(IProject p, Set<File> jarFiles,
+ boolean includeAndroidContainer) {
+ IJavaProject javaProject = JavaCore.create(p);
+ IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+ // we could use IJavaProject.getResolvedClasspath directly, but we actually
+ // want to see the containers themselves.
+ IClasspathEntry[] classpaths = javaProject.readRawClasspath();
+ if (classpaths != null) {
+ for (IClasspathEntry e : classpaths) {
+ // if this is a classpath variable reference, we resolve it.
+ if (e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
+ e = JavaCore.getResolvedClasspathEntry(e);
+ }
+
+ 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)) {
+ // get the container.
+ try {
+ IClasspathContainer container = JavaCore.getClasspathContainer(
+ e.getPath(), javaProject);
+ // ignore the system and default_system types as they represent
+ // libraries that are part of the runtime.
+ if (container != null &&
+ container.getKind() == IClasspathContainer.K_APPLICATION) {
+ IClasspathEntry[] entries = container.getClasspathEntries();
+ for (IClasspathEntry entry : entries) {
+ handleClasspathEntry(entry, wsRoot, jarFiles);
+ }
+ }
+ } catch (JavaModelException jme) {
+ // can't resolve the container? ignore it.
+ AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s", e.getPath());
+ }
+ }
+ }
+ }
+ }
+
+ private static final class CPEFile extends File {
+ private static final long serialVersionUID = 1L;
+
+ private final IClasspathEntry mClasspathEntry;
+
+ public CPEFile(String pathname, IClasspathEntry classpathEntry) {
+ super(pathname);
+ mClasspathEntry = classpathEntry;
+ }
+
+ public CPEFile(File file, IClasspathEntry classpathEntry) {
+ super(file.getAbsolutePath());
+ mClasspathEntry = classpathEntry;
+ }
+
+ public IClasspathEntry getClasspathEntry() {
+ return mClasspathEntry;
+ }
+ }
+
+ private static void handleClasspathEntry(IClasspathEntry e, IWorkspaceRoot wsRoot,
+ Set<File> jarFiles) {
+ // get the IPath
+ IPath path = e.getPath();
+
+ IResource resource = wsRoot.findMember(path);
+
+ if (AdtConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
+ // case of a jar file (which could be relative to the workspace or a full path)
+ if (resource != null && resource.exists() &&
+ resource.getType() == IResource.FILE) {
+ jarFiles.add(new CPEFile(resource.getLocation().toFile(), e));
+ } else {
+ // if the jar path doesn't match a workspace resource,
+ // then we get an OSString and check if this links to a valid file.
+ String osFullPath = path.toOSString();
+
+ File f = new CPEFile(osFullPath, e);
+ if (f.isFile()) {
+ jarFiles.add(f);
+ }
+ }
+ }
+ }
}