diff options
8 files changed, 364 insertions, 136 deletions
diff --git a/anttasks/src/com/android/ant/DexExecTask.java b/anttasks/src/com/android/ant/DexExecTask.java index 273f689..085e924 100644 --- a/anttasks/src/com/android/ant/DexExecTask.java +++ b/anttasks/src/com/android/ant/DexExecTask.java @@ -210,6 +210,10 @@ public class DexExecTask extends SingleDependencyTask { try { results.addAll(sanitizer.sanitize(paths)); } catch (DifferentLibException e) { + String[] details = e.getDetails(); + for (String s : details) { + System.err.println(s); + } throw new BuildException(e.getMessage(), e); } catch (Sha1Exception e) { throw new BuildException( 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); + } + } + } + } } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/build/JarListSanitizer.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/build/JarListSanitizer.java index bd4d9a4..c6c0c22 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/build/JarListSanitizer.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/build/JarListSanitizer.java @@ -24,9 +24,11 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.util.ArrayList; +import java.util.Collection; import java.util.Formatter; import java.util.HashMap; import java.util.List; @@ -135,9 +137,15 @@ public class JarListSanitizer { */ public static final class DifferentLibException extends Exception { private static final long serialVersionUID = 1L; + private final String[] mDetails; - public DifferentLibException(String message) { + public DifferentLibException(String message, String[] details) { super(message); + mDetails = details; + } + + public String[] getDetails() { + return mDetails; } } @@ -159,6 +167,7 @@ public class JarListSanitizer { } private final File mOut; + private final PrintStream mOutStream; /** * Creates a sanitizer. @@ -166,6 +175,12 @@ public class JarListSanitizer { */ public JarListSanitizer(File out) { mOut = out; + mOutStream = System.out; + } + + public JarListSanitizer(File out, PrintStream outStream) { + mOut = out; + mOutStream = outStream; } /** @@ -175,7 +190,7 @@ public class JarListSanitizer { * @throws DifferentLibException * @throws Sha1Exception */ - public List<File> sanitize(List<File> files) throws DifferentLibException, Sha1Exception { + public List<File> sanitize(Collection<File> files) throws DifferentLibException, Sha1Exception { List<File> results = new ArrayList<File>(); // get the cache list. @@ -269,8 +284,8 @@ public class JarListSanitizer { for (int i = 1; i < count ; i++) { JarEntity entity = list.get(i); if (entity.getLength() != baseLength || entity.getSha1().equals(baseSha1) == false) { - printEntityDetails(filename, list); - throw new DifferentLibException("Jar mismatch! Fix your dependencies"); + throw new DifferentLibException("Jar mismatch! Fix your dependencies", + getEntityDetails(filename, list)); } } @@ -288,8 +303,8 @@ public class JarListSanitizer { List<JarEntity> v13 = nameMap.get("android-support-v13.jar"); if (v13 != null && v4 != null) { - System.out.println("WARNING: Found both android-support-v4 and android-support-v13 in the dependency list."); - System.out.println("Because v13 includes v4, using only v13."); + mOutStream.println("WARNING: Found both android-support-v4 and android-support-v13 in the dependency list."); + mOutStream.println("Because v13 includes v4, using only v13."); results.remove(v4.get(0).getFile()); } } @@ -381,7 +396,7 @@ public class JarListSanitizer { writer.close(); } catch (IOException e) { - System.err.println("WARNING: unable to write jarlist cache file " + + mOutStream.println("WARNING: unable to write jarlist cache file " + cacheFile.getAbsolutePath()); } catch (Sha1Exception e) { // shouldn't happen here since we check that the sha1 is present first, meaning it's @@ -389,18 +404,21 @@ public class JarListSanitizer { } } - private void printEntityDetails(String filename, List<JarEntity> list) throws Sha1Exception { - System.err.println( + private String[] getEntityDetails(String filename, List<JarEntity> list) throws Sha1Exception { + ArrayList<String> result = new ArrayList<String>(); + result.add( String.format("Found %d versions of %s in the dependency list,", list.size(), filename)); - System.err.println("but not all the versions are identical (check is based on SHA-1 only at this time)."); - System.err.println("All versions of the libraries must be the same at this time."); - System.err.println("Versions found are:"); + result.add("but not all the versions are identical (check is based on SHA-1 only at this time)."); + result.add("All versions of the libraries must be the same at this time."); + result.add("Versions found are:"); for (JarEntity entity : list) { - System.err.println("Path: " + entity.getFile().getAbsolutePath()); - System.err.println("\tLength: " + entity.getLength()); - System.err.println("\tSHA-1: " + entity.getSha1()); + result.add("Path: " + entity.getFile().getAbsolutePath()); + result.add("\tLength: " + entity.getLength()); + result.add("\tSHA-1: " + entity.getSha1()); } + + return result.toArray(new String[result.size()]); } /** |