Beispiel #1
0
  @Before
  public void setUp() throws Exception {
    startMonitoringJob();

    System.out.println("AdtProject: setup");
    System.out.println("Starting Test: " + testName.getMethodName());
    // Prevent preview icon computation during plugin test to make test
    // faster

    if (AndmoreAndroidPlugin.getDefault() == null) {
      fail("This test must be run as an Eclipse plugin test, not a plain JUnit test!");
    }

    AdtPrefs.getPrefs().setPaletteModes("ICON_TEXT"); // $NON-NLS-1$

    getProject();

    Sdk current = Sdk.getCurrent();
    assertNotNull(current);
    LoadStatus sdkStatus = AndmoreAndroidPlugin.getDefault().getSdkLoadStatus();
    assertSame(LoadStatus.LOADED, sdkStatus);
    IAndroidTarget target = current.getTarget(getProject());
    IJavaProject javaProject = BaseProjectHelper.getJavaProject(getProject());
    assertNotNull(javaProject);
    int iterations = 0;
    while (true) {
      if (iterations == 100) {
        fail("Couldn't load target; ran out of time");
      }
      LoadStatus status = current.checkAndLoadTargetData(target, javaProject);
      if (status == LoadStatus.FAILED) {
        fail("Couldn't load target " + target);
      }
      if (status != LoadStatus.LOADING) {
        break;
      }
      Thread.sleep(250);
      iterations++;
    }
    //		AndroidTargetData targetData = current.getTargetData(target);
    //		assertNotNull(targetData);
    //		LayoutDescriptors layoutDescriptors = targetData.getLayoutDescriptors();
    //		assertNotNull(layoutDescriptors);
    //		List<ViewElementDescriptor> viewDescriptors = layoutDescriptors.getViewDescriptors();
    //		assertNotNull(viewDescriptors);
    //		assertTrue(viewDescriptors.size() > 0);
    //		List<ViewElementDescriptor> layoutParamDescriptors =
    // layoutDescriptors.getLayoutDescriptors();
    //		assertNotNull(layoutParamDescriptors);
    //		assertTrue(layoutParamDescriptors.size() > 0);
  }
 /**
  * Returns an optional ImageDescriptor for the element.
  *
  * <p>By default this tries to return an image based on the XML name of the element. If this
  * fails, it tries to return the default Android logo as defined in the plugin. If all fails, it
  * returns null.
  *
  * @return An ImageDescriptor for this element or null.
  */
 public ImageDescriptor getImageDescriptor() {
   IconFactory factory = IconFactory.getInstance();
   int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
   int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
   ImageDescriptor id = factory.getImageDescriptor(mXmlName, color, shape);
   return id != null ? id : AndmoreAndroidPlugin.getAndroidLogoDesc();
 }
 private static boolean showConvertMessageBox(String fileName) {
   return MessageDialog.openQuestion(
       AndmoreAndroidPlugin.getDisplay().getActiveShell(),
       "Warning",
       String.format(
           "The file \"%s\" doesn't seem to be a 9-patch file. \n" + "Do you want to convert?",
           fileName));
 }
  private static IClasspathContainer allocateContainer(
      IJavaProject javaProject, List<IClasspathEntry> entries, IPath id, String description) {

    if (AndmoreAndroidPlugin.getDefault()
        == null) { // This is totally weird, but I've seen it happen!
      return null;
    }

    // First check that the project has a library-type container.
    try {
      IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
      final IClasspathEntry[] oldRawClasspath = rawClasspath;

      boolean foundContainer = false;
      for (IClasspathEntry entry : rawClasspath) {
        // get the entry and kind
        final int kind = entry.getEntryKind();

        if (kind == IClasspathEntry.CPE_CONTAINER) {
          String path = entry.getPath().toString();
          String idString = id.toString();
          if (idString.equals(path)) {
            foundContainer = true;
            break;
          }
        }
      }

      // if there isn't any, add it.
      if (foundContainer == false) {
        // add the android container to the array
        rawClasspath =
            ProjectHelper.addEntryToClasspath(
                rawClasspath, JavaCore.newContainerEntry(id, true /*isExported*/));
      }

      // set the new list of entries to the project
      if (rawClasspath != oldRawClasspath) {
        javaProject.setRawClasspath(rawClasspath, new NullProgressMonitor());
      }
    } catch (JavaModelException e) {
      // This really shouldn't happen, but if it does, simply return null (the calling
      // method will fails as well)
      return null;
    }

    return new AndroidClasspathContainer(
        entries.toArray(new IClasspathEntry[entries.size()]),
        id,
        description,
        IClasspathContainer.K_APPLICATION);
  }
  /**
   * Processes a {@link IClasspathEntry} and add it to one of the list if applicable.
   *
   * @param entry the entry to process
   * @param javaProject the {@link IJavaProject} from which this entry came.
   * @param wsRoot the {@link IWorkspaceRoot}
   * @param projects the project list to add to
   * @param jarFiles the jar list to add to
   * @param includeJarFiles whether to include jar files or just projects. This is useful when
   *     calling on an Android project (value should be <code>false</code>)
   */
  private static void processCPE(
      IClasspathEntry entry,
      IJavaProject javaProject,
      IWorkspaceRoot wsRoot,
      Set<IProject> projects,
      Set<File> jarFiles,
      boolean includeJarFiles) {

    // if this is a classpath variable reference, we resolve it.
    if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
      entry = JavaCore.getResolvedClasspathEntry(entry);
    }

    if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
      IProject refProject = wsRoot.getProject(entry.getPath().lastSegment());
      try {
        // ignore if it's an Android project, or if it's not a Java Project
        if (refProject.hasNature(JavaCore.NATURE_ID)
            && refProject.hasNature(AndmoreAndroidConstants.NATURE_DEFAULT) == false) {
          // add this project to the list
          projects.add(refProject);

          // also get the dependency from this project.
          getDependencyListFromClasspath(refProject, projects, jarFiles, true /*includeJarFiles*/);
        }
      } catch (CoreException exception) {
        // can't query the project nature? ignore
      }
    } else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
      if (includeJarFiles) {
        handleClasspathLibrary(entry, wsRoot, jarFiles);
      }
    } else if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
      // get the container and its content
      try {
        IClasspathContainer container =
            JavaCore.getClasspathContainer(entry.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 cpe : entries) {
            processCPE(cpe, javaProject, wsRoot, projects, jarFiles, includeJarFiles);
          }
        }
      } catch (JavaModelException jme) {
        // can't resolve the container? ignore it.
        AndmoreAndroidPlugin.log(jme, "Failed to resolve ClasspathContainer: %s", entry.getPath());
      }
    }
  }
  private IPath showSaveAsDialog() {
    SaveAsDialog dialog = new SaveAsDialog(AndmoreAndroidPlugin.getDisplay().getActiveShell());

    IFile dest =
        mProject.getFile(
            NinePatchedImage.getNinePatchedFileName(
                mFileEditorInput.getFile().getProjectRelativePath().toOSString()));
    dialog.setOriginalFile(dest);

    dialog.create();

    if (dialog.open() == Window.CANCEL) {
      return null;
    }

    return dialog.getResult();
  }
Beispiel #7
0
  protected IFile getTestDataFile(
      IProject project, String sourceName, String destPath, boolean overwrite) throws Exception {
    String[] split = destPath.split("/"); // $NON-NLS-1$
    IContainer parent;
    String name;
    if (split.length == 1) {
      parent = project;
      name = destPath;
    } else {
      IFolder folder = project.getFolder(split[0]);
      NullProgressMonitor monitor = new NullProgressMonitor();
      if (!folder.exists()) {
        folder.create(true /* force */, true /* local */, monitor);
      }
      for (int i = 1, n = split.length; i < n - 1; i++) {
        IFolder subFolder = folder.getFolder(split[i]);
        if (!subFolder.exists()) {
          subFolder.create(true /* force */, true /* local */, monitor);
        }
        folder = subFolder;
      }
      name = split[split.length - 1];
      parent = folder;
    }
    IFile file = parent.getFile(new Path(name));
    if (overwrite && file.exists()) {
      String currentContents = AndmoreAndroidPlugin.readFile(file);
      String newContents = readTestFile(sourceName, true);
      if (currentContents == null || !currentContents.equals(newContents)) {
        file.delete(true, new NullProgressMonitor());
      } else {
        return file;
      }
    }
    if (!file.exists()) {
      String xml = readTestFile(sourceName, true);
      InputStream bstream = new ByteArrayInputStream(xml.getBytes("UTF-8")); // $NON-NLS-1$
      NullProgressMonitor monitor = new NullProgressMonitor();
      file.create(bstream, false /* force */, monitor);
    }

    return file;
  }
  /**
   * Returns the {@link RenderPreviewList} for the given project
   *
   * @param project the project the list is associated with
   * @return a {@link RenderPreviewList} for the given project, never null
   */
  @NonNull
  public static RenderPreviewList get(@NonNull IProject project) {
    RenderPreviewList list = null;
    try {
      list = (RenderPreviewList) project.getSessionProperty(PREVIEW_LIST);
    } catch (CoreException e) {
      // Not a problem; we will just create a new one
    }

    if (list == null) {
      list = new RenderPreviewList(project);
      try {
        project.setSessionProperty(PREVIEW_LIST, list);
      } catch (CoreException e) {
        AndmoreAndroidPlugin.log(e, null);
      }
    }

    return list;
  }
  @Override
  public void launch(ISelection selection, String mode) {
    if (!(selection instanceof IStructuredSelection)) {
      return;
    }

    Object s = ((IStructuredSelection) selection).getFirstElement();
    if (!(s instanceof IAdaptable)) {
      return;
    }

    IResource r = (IResource) ((IAdaptable) s).getAdapter(IResource.class);
    if (r == null) {
      return;
    }

    IProject project = r.getProject();
    if (project == null) {
      return;
    }

    // verify that this is a non library Android project
    ProjectState state = Sdk.getProjectState(project);
    if (state == null || state.isLibrary()) {
      return;
    }

    // verify that this project has C/C++ nature
    if (!CoreModel.hasCCNature(project) && !CoreModel.hasCNature(project)) {
      AndmoreAndroidPlugin.printErrorToConsole(
          project,
          String.format(
              "Selected project (%s) does not have C/C++ nature. "
                  + "To add native support, right click on the project, "
                  + "Android Tools -> Add Native Support",
              project.getName()));
      return;
    }

    debugProject(project, mode);
  }
  /**
   * Returns an optional icon for the element, typically to be used in XML form trees.
   *
   * <p>This icon is customized to the given descriptor, that is different elements will have
   * different icons.
   *
   * <p>By default this tries to return an icon based on the XML name of the element. If this fails,
   * it tries to return the default Android logo as defined in the plugin. If all fails, it returns
   * null.
   *
   * @return An icon for this element. This is never null.
   */
  public Image getCustomizedIcon() {
    IconFactory factory = IconFactory.getInstance();
    int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
    int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
    String name = mXmlName;

    int pos = name.lastIndexOf('.');
    if (pos != -1) {
      // If the user uses a fully qualified name, such as
      // "android.gesture.GestureOverlayView" in their XML, we need to
      // look up only by basename
      name = name.substring(pos + 1);
    }
    Image icon = factory.getIcon(name, color, shape);
    if (icon == null) {
      icon = getGenericIcon();
    }
    if (icon == null) {
      icon = AndmoreAndroidPlugin.getAndroidLogo();
    }
    return icon;
  }
  private void debugProject(IProject project, String mode) {
    // obtain existing native debug config for project
    ILaunchConfiguration config =
        AndroidLaunchController.getLaunchConfig(project, NdkGdbLaunchDelegate.LAUNCH_TYPE_ID);
    if (config == null) {
      return;
    }

    // Set the ndk gdb specific launch attributes in the config (if
    // necessary)
    if (!hasNdkAttributes(config)) {
      try {
        config = setNdkDefaults(config, project);
      } catch (CoreException e) {
        AndmoreAndroidPlugin.printErrorToConsole(
            project, "Unable to create launch configuration for project.");
        return;
      }
    }

    // launch
    DebugUITools.launch(config, mode);
  }
Beispiel #12
0
  protected int getCaretOffset(IFile file, String caretLocation) {
    assertTrue(caretLocation, caretLocation.contains("^"));

    String fileContent = AndmoreAndroidPlugin.readFile(file);
    return getCaretOffset(fileContent, caretLocation);
  }
Beispiel #13
0
  private void checkResourceFix(String name, String caretLocation, String expectedNewPath)
      throws Exception {
    IProject project = getProject();
    IFile file = getTestDataFile(project, name, FD_RES + "/" + FD_RES_LAYOUT + "/" + name);

    // Determine the offset
    final int offset = getCaretOffset(file, caretLocation);

    String osRoot = project.getLocation().toOSString();
    List<String> errors = new ArrayList<String>();
    String fileRelativePath = file.getProjectRelativePath().toPortableString();
    String filePath = osRoot + File.separator + fileRelativePath;
    // Run AaptParser such that markers are added...
    // When debugging these tests, the project gets a chance to build itself
    // so
    // the real aapt errors are there. But when the test is run directly,
    // aapt has
    // not yet run. I tried waiting for the build (using the code in
    // SampleProjectTest)
    // but this had various adverse effects (exception popups from the
    // Eclipse debugger
    // etc) so instead this test just hardcodes the aapt errors that should
    // be
    // observed on quickfix1.xml.
    assertEquals("Unit test is hardcoded to errors for quickfix1.xml", "quickfix1.xml", name);
    errors.add(
        filePath
            + ":7: error: Error: No resource found that matches the given name"
            + " (at 'text' with value '@string/firststring').");
    errors.add(
        filePath
            + ":7: error: Error: No resource found that matches the given name"
            + " (at 'layout_width' with value '@dimen/testdimen').");
    errors.add(
        filePath
            + ":13: error: Error: No resource found that matches the given name"
            + " (at 'layout' with value '@layout/testlayout').");
    AaptParser.parseOutput(errors, project);

    AaptQuickFix aaptQuickFix = new AaptQuickFix();

    // Open file
    IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
    assertNotNull(page);
    IEditorPart editor = IDE.openEditor(page, file);
    assertTrue(editor instanceof AndroidXmlEditor);
    AndroidXmlEditor layoutEditor = (AndroidXmlEditor) editor;
    final ISourceViewer viewer = layoutEditor.getStructuredSourceViewer();

    // Test marker resolution.
    IMarker[] markers =
        file.findMarkers(AndmoreAndroidConstants.MARKER_AAPT_COMPILE, true, IResource.DEPTH_ZERO);
    for (IMarker marker : markers) {
      int start = marker.getAttribute(IMarker.CHAR_START, 0);
      int end = marker.getAttribute(IMarker.CHAR_END, 0);
      if (offset >= start && offset <= end) {
        // Found the target marker. Now check the marker resolution of
        // it.
        assertTrue(aaptQuickFix.hasResolutions(marker));
        IMarkerResolution[] resolutions = aaptQuickFix.getResolutions(marker);
        assertNotNull(resolutions);
        assertEquals(1, resolutions.length);
        IMarkerResolution resolution = resolutions[0];
        assertNotNull(resolution);
        assertTrue(resolution.getLabel().contains("Create resource"));

        // Not running marker yet -- if we create the files here they
        // already
        // exist when the quick assist code runs. (The quick fix and the
        // quick assist
        // mostly share code for the implementation anyway.)
        // resolution.run(marker);
        break;
      }
    }

    // Next test quick assist.

    IQuickAssistInvocationContext invocationContext =
        new IQuickAssistInvocationContext() {
          @Override
          public int getLength() {
            return 0;
          }

          @Override
          public int getOffset() {
            return offset;
          }

          @Override
          public ISourceViewer getSourceViewer() {
            return viewer;
          }
        };
    ICompletionProposal[] proposals = aaptQuickFix.computeQuickAssistProposals(invocationContext);
    assertNotNull(proposals);
    assertTrue(proposals.length == 1);
    ICompletionProposal proposal = proposals[0];

    assertNotNull(proposal.getAdditionalProposalInfo());
    assertNotNull(proposal.getImage());
    assertTrue(proposal.getDisplayString().contains("Create resource"));

    IDocument document = new Document();
    String fileContent = AndmoreAndroidPlugin.readFile(file);
    document.set(fileContent);

    // Apply quick fix
    proposal.apply(document);

    IPath path = new Path(expectedNewPath);
    IFile newFile = project.getFile(path);
    assertNotNull(path.toPortableString(), newFile);

    // Ensure that the newly created file was opened
    IEditorPart currentFile = AdtUtils.getActiveEditor();
    assertEquals(
        newFile.getProjectRelativePath(),
        ((FileEditorInput) currentFile.getEditorInput()).getFile().getProjectRelativePath());

    // Look up caret offset
    assertTrue(
        currentFile != null ? currentFile.getClass().getName() : "null",
        currentFile instanceof AndroidXmlEditor);
    AndroidXmlEditor newEditor = (AndroidXmlEditor) currentFile;
    ISourceViewer newViewer = newEditor.getStructuredSourceViewer();
    Point selectedRange = newViewer.getSelectedRange();

    String newFileContents = AndmoreAndroidPlugin.readFile(newFile);

    // Insert selection markers -- [ ] for the selection range, ^ for the
    // caret
    String newFileWithCaret = addSelection(newFileContents, selectedRange);
    newFileWithCaret = removeSessionData(newFileWithCaret);

    assertEqualsGolden(name, newFileWithCaret);
  }
Beispiel #14
0
  private void checkNamespaceFix(String name, String caretLocation) throws Exception {
    IProject project = getProject();
    IFile file = getTestDataFile(project, name, FD_RES + "/" + FD_RES_COLOR + "/" + name);

    // Determine the offset
    final int offset = getCaretOffset(file, caretLocation);

    String osRoot = project.getLocation().toOSString();
    List<String> errors = new ArrayList<String>();
    String fileRelativePath = file.getProjectRelativePath().toPortableString();
    String filePath = osRoot + File.separator + fileRelativePath;
    assertEquals("Unit test is hardcoded to errors for quickfix2.xml", "quickfix2.xml", name);
    errors.add(filePath + ":5: error: Error parsing XML: unbound prefix");
    AaptParser.parseOutput(errors, project);

    AaptQuickFix aaptQuickFix = new AaptQuickFix();

    // Open file
    IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
    assertNotNull(page);
    IEditorPart editor = IDE.openEditor(page, file);
    assertTrue(editor instanceof AndroidXmlEditor);
    AndroidXmlEditor layoutEditor = (AndroidXmlEditor) editor;
    final ISourceViewer viewer = layoutEditor.getStructuredSourceViewer();

    // Test marker resolution.
    IMarker[] markers =
        file.findMarkers(AndmoreAndroidConstants.MARKER_AAPT_COMPILE, true, IResource.DEPTH_ZERO);
    assertEquals(1, markers.length);
    IMarker marker = markers[0];
    // Found the target marker. Now check the marker resolution of it.
    assertTrue(aaptQuickFix.hasResolutions(marker));
    IMarkerResolution[] resolutions = aaptQuickFix.getResolutions(marker);
    assertNotNull(resolutions);
    assertEquals(1, resolutions.length);
    IMarkerResolution resolution = resolutions[0];
    assertNotNull(resolution);
    assertTrue(resolution.getLabel().contains("Insert namespace"));

    // Next test quick assist.

    IQuickAssistInvocationContext invocationContext =
        new IQuickAssistInvocationContext() {
          @Override
          public int getLength() {
            return 0;
          }

          @Override
          public int getOffset() {
            return offset;
          }

          @Override
          public ISourceViewer getSourceViewer() {
            return viewer;
          }
        };
    ICompletionProposal[] proposals = aaptQuickFix.computeQuickAssistProposals(invocationContext);
    assertNotNull(proposals);
    assertTrue(proposals.length == 1);
    ICompletionProposal proposal = proposals[0];

    assertNotNull(proposal.getAdditionalProposalInfo());
    assertNotNull(proposal.getImage());
    assertTrue(proposal.getDisplayString().contains("Insert namespace"));

    // Open the file to ensure we can get an XML model with
    // getExistingModelForEdit:
    AndmoreAndroidPlugin.openFile(file, null);
    IEditorPart newEditor = AdtUtils.getActiveEditor();
    assertTrue(newEditor instanceof AndroidXmlEditor);

    AndroidXmlEditor xmlEditor = (AndroidXmlEditor) newEditor;
    IDocument document = xmlEditor.getStructuredSourceViewer().getDocument();

    // Apply quick fix
    String before = document.get();
    proposal.apply(document);
    String after = document.get();
    String diff = getDiff(before, after);
    assertEqualsGolden(name, diff);
  }
Beispiel #15
0
  @Override
  public void doSave(final IProgressMonitor monitor) {
    boolean hasNinePatchExtension = mFileName.endsWith(DOT_9PNG);
    boolean doConvert = false;

    if (!hasNinePatchExtension) {
      String patchedName = NinePatchedImage.getNinePatchedFileName(mFileName);
      doConvert =
          MessageDialog.openQuestion(
              AndmoreAndroidPlugin.getDisplay().getActiveShell(),
              "Warning",
              String.format(
                  "The file \"%s\" doesn't seem to be a 9-patch file. \n"
                      + "Do you want to convert and save as \"%s\" ?",
                  mFileName, patchedName));

      if (doConvert) {
        IFile destFile =
            mProject.getFile(
                NinePatchedImage.getNinePatchedFileName(
                    mFileEditorInput.getFile().getProjectRelativePath().toOSString()));
        if (!destFile.exists()) {
          mFileEditorInput = new FileEditorInput(destFile);
          mFileName = mFileEditorInput.getName();
        } else {
          IPath relativePath = null;
          if ((relativePath = showSaveAsDialog()) != null) {
            mFileEditorInput =
                new FileEditorInput(ResourcesPlugin.getWorkspace().getRoot().getFile(relativePath));
            mFileName = mFileEditorInput.getName();
          } else {
            doConvert = false;
          }
        }
      }
    }

    if (hasNinePatchExtension || doConvert) {
      ImageLoader loader = new ImageLoader();
      loader.data = new ImageData[] {mNinePatchedImage.getRawImageData()};

      IFile file = mFileEditorInput.getFile();

      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      loader.save(outputStream, SWT.IMAGE_PNG);
      byte[] byteArray = outputStream.toByteArray();

      try {
        if (file.exists()) {
          file.setContents(new ByteArrayInputStream(byteArray), true, false, monitor);
        } else {
          file.create(new ByteArrayInputStream(byteArray), true, monitor);
        }

        mNinePatchedImage.clearDirtyFlag();

        AndmoreAndroidPlugin.getDisplay()
            .asyncExec(
                new Runnable() {
                  @Override
                  public void run() {
                    setPartName(mFileName);
                    firePropertyChange(PROP_DIRTY);
                  }
                });
      } catch (CoreException e) {
        AndmoreAndroidPlugin.log(e, null);
      }
    }
  }
  private static IClasspathContainer allocateDependencyContainer(IJavaProject javaProject) {
    final IProject iProject = javaProject.getProject();
    final List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
    final Set<File> jarFiles = new HashSet<File>();
    final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

    AndmoreAndroidPlugin plugin = AndmoreAndroidPlugin.getDefault();
    if (plugin == null) { // This is totally weird, but I've seen it happen!
      return null;
    }

    synchronized (Sdk.getLock()) {
      boolean sdkIsLoaded = plugin.getSdkLoadStatus() == LoadStatus.LOADED;

      // check if the project has a valid target.
      final ProjectState state = Sdk.getProjectState(iProject);
      if (state == null) {
        // getProjectState should already have logged an error. Just bail out.
        return null;
      }

      // annotations support for older version of android
      if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) {
        File annotationsJar =
            new File(
                Sdk.getCurrent().getSdkOsLocation(),
                SdkConstants.FD_TOOLS
                    + File.separator
                    + SdkConstants.FD_SUPPORT
                    + File.separator
                    + SdkConstants.FN_ANNOTATIONS_JAR);

        jarFiles.add(annotationsJar);
      }

      if (state.getRenderScriptSupportMode()) {
        if (!sdkIsLoaded) {
          return null;
        }
        BuildToolInfo buildToolInfo = state.getBuildToolInfo();
        if (buildToolInfo == null) {
          buildToolInfo = Sdk.getCurrent().getLatestBuildTool();

          if (buildToolInfo == null) {
            return null;
          }
        }

        File renderScriptSupportJar =
            RenderScriptProcessor.getSupportJar(buildToolInfo.getLocation().getAbsolutePath());

        jarFiles.add(renderScriptSupportJar);
      }

      // process all the libraries

      List<IProject> libProjects = state.getFullLibraryProjects();
      for (IProject libProject : libProjects) {
        // get the project output
        IFolder outputFolder = BaseProjectHelper.getAndroidOutputFolder(libProject);

        if (outputFolder != null) { // can happen when closing/deleting a library)
          IFile jarIFile =
              outputFolder.getFile(libProject.getName().toLowerCase() + SdkConstants.DOT_JAR);

          // get the source folder for the library project
          List<IPath> srcs = BaseProjectHelper.getSourceClasspaths(libProject);
          // find the first non-derived source folder.
          IPath sourceFolder = null;
          for (IPath src : srcs) {
            IFolder srcFolder = workspaceRoot.getFolder(src);
            if (srcFolder.isDerived() == false) {
              sourceFolder = src;
              break;
            }
          }

          // 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.
                  true /*isExported*/);

          entries.add(entry);
        }
      }

      entries.addAll(convertJarsToClasspathEntries(iProject, jarFiles));

      return allocateContainer(
          javaProject, entries, new Path(CONTAINER_DEPENDENCIES), "Android Dependencies");
    }
  }
  private static List<IClasspathEntry> convertJarsToClasspathEntries(
      final IProject iProject, Set<File> jarFiles) {
    List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(jarFiles.size());

    // 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*/, AndmoreAndroidPlugin.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(),
                  true /*isExported*/));
        } else {
          String jarPath = jarFile.getAbsolutePath();

          IPath sourceAttachmentPath = null;
          IClasspathAttribute javaDocAttribute = null;

          File jarProperties = new File(jarPath + DOT_PROPERTIES);
          if (jarProperties.isFile()) {
            Properties p = new Properties();
            InputStream is = null;
            try {
              p.load(is = new FileInputStream(jarProperties));

              String value = p.getProperty(ATTR_SRC);
              if (value != null) {
                File srcPath = getFile(jarFile, value);

                if (srcPath.exists()) {
                  sourceAttachmentPath = new Path(srcPath.getAbsolutePath());
                }
              }

              value = p.getProperty(ATTR_DOC);
              if (value != null) {
                File docPath = getFile(jarFile, value);
                if (docPath.exists()) {
                  try {
                    javaDocAttribute =
                        JavaCore.newClasspathAttribute(
                            IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME,
                            docPath.toURI().toURL().toString());
                  } catch (MalformedURLException e) {
                    AndmoreAndroidPlugin.log(
                        e,
                        "Failed to process 'doc' attribute for %s",
                        jarProperties.getAbsolutePath());
                  }
                }
              }

            } catch (FileNotFoundException e) {
              // shouldn't happen since we check upfront
            } catch (IOException e) {
              AndmoreAndroidPlugin.log(e, "Failed to read %s", jarProperties.getAbsolutePath());
            } finally {
              if (is != null) {
                try {
                  is.close();
                } catch (IOException e) {
                  // ignore
                }
              }
            }
          }

          if (javaDocAttribute != null) {
            entries.add(
                JavaCore.newLibraryEntry(
                    new Path(jarPath),
                    sourceAttachmentPath,
                    null /*sourceAttachmentRootPath*/,
                    new IAccessRule[0],
                    new IClasspathAttribute[] {javaDocAttribute},
                    true /*isExported*/));
          } else {
            entries.add(
                JavaCore.newLibraryEntry(
                    new Path(jarPath),
                    sourceAttachmentPath,
                    null /*sourceAttachmentRootPath*/,
                    true /*isExported*/));
          }
        }
      }
    } catch (DifferentLibException e) {
      errorMessage = e.getMessage();
      AndmoreAndroidPlugin.printErrorToConsole(iProject, (Object[]) e.getDetails());
    } catch (Sha1Exception e) {
      errorMessage = e.getMessage();
    }

    processError(
        iProject,
        errorMessage,
        AndmoreAndroidConstants.MARKER_DEPENDENCY,
        true /*outputToConsole*/);

    return entries;
  }