private List<LoadedManifestInfo> loadLibraries(
      SelectorResolver selectors, MergingReport.Builder mergingReportBuilder)
      throws MergeFailureException {

    ImmutableList.Builder<LoadedManifestInfo> loadedLibraryDocuments = ImmutableList.builder();
    for (Pair<String, File> libraryFile : mLibraryFiles) {
      mLogger.info("Loading library manifest " + libraryFile.getSecond().getPath());
      ManifestInfo manifestInfo =
          new ManifestInfo(
              libraryFile.getFirst(),
              libraryFile.getSecond(),
              XmlDocument.Type.LIBRARY,
              Optional.<String>absent());
      XmlDocument libraryDocument;
      try {
        libraryDocument =
            XmlLoader.load(
                selectors,
                mSystemPropertyResolver,
                manifestInfo.mName,
                manifestInfo.mLocation,
                XmlDocument.Type.LIBRARY,
                Optional.<String>absent() /* mainManifestPackageName */);
      } catch (Exception e) {
        throw new MergeFailureException(e);
      }
      // extract the package name...
      String libraryPackage = libraryDocument.getRootNode().getXml().getAttribute("package");
      // save it in the selector instance.
      if (!Strings.isNullOrEmpty(libraryPackage)) {
        selectors.addSelector(libraryPackage, libraryFile.getFirst());
      }

      // perform placeholder substitution, this is useful when the library is using
      // a placeholder in a key element, we however do not need to record these
      // substitutions so feed it with a fake merging report.
      MergingReport.Builder builder = new MergingReport.Builder(mergingReportBuilder.getLogger());
      builder.getActionRecorder().recordDefaultNodeAction(libraryDocument.getRootNode());
      performPlaceHolderSubstitution(manifestInfo, libraryDocument, builder);
      if (builder.hasErrors()) {
        // we log the errors but continue, in case the error is of no consequence
        // to the application consuming the library.
        builder.build().log(mLogger);
      }

      loadedLibraryDocuments.add(
          new LoadedManifestInfo(
              manifestInfo,
              Optional.fromNullable(libraryDocument.getPackageName()),
              libraryDocument));
    }
    return loadedLibraryDocuments.build();
  }
  private static void forkResourceFile(
      @NotNull Module module,
      @NotNull final ResourceFolderType folderType,
      @NotNull final VirtualFile file,
      @Nullable final XmlFile xmlFile,
      @Nullable String myNewFolder,
      @Nullable Configuration configuration,
      boolean open) {
    final Project project = module.getProject();
    final FolderConfiguration folderConfig;
    if (myNewFolder == null) {
      // Open a file chooser to select the configuration to be created
      VirtualFile parentFolder = file.getParent();
      assert parentFolder != null;
      VirtualFile res = parentFolder.getParent();
      folderConfig = selectFolderConfig(project, res, folderType);
    } else {
      folderConfig = FolderConfiguration.getConfigForFolder(myNewFolder);
    }
    if (folderConfig == null) {
      return;
    }

    final Computable<Pair<String, VirtualFile>> computable =
        new Computable<Pair<String, VirtualFile>>() {
          @Override
          public Pair<String, VirtualFile> compute() {
            String folderName = folderConfig.getFolderName(folderType);
            try {
              VirtualFile parentFolder = file.getParent();
              assert parentFolder != null;
              VirtualFile res = parentFolder.getParent();
              VirtualFile newParentFolder = res.findChild(folderName);
              if (newParentFolder == null) {
                newParentFolder = res.createChildDirectory(this, folderName);
                if (newParentFolder == null) {
                  String message =
                      String.format(
                          "Could not create folder %1$s in %2$s", folderName, res.getPath());
                  return Pair.of(message, null);
                }
              }

              final VirtualFile existing = newParentFolder.findChild(file.getName());
              if (existing != null && existing.exists()) {
                String message =
                    String.format(
                        "File 'res/%1$s/%2$s' already exists!", folderName, file.getName());
                return Pair.of(message, null);
              }

              // Attempt to get the document from the PSI file rather than the file on disk: get
              // edited contents too
              String text;
              if (xmlFile != null) {
                text = xmlFile.getText();
              } else {
                text = StreamUtil.readText(file.getInputStream(), "UTF-8");
              }
              VirtualFile newFile = newParentFolder.createChildData(this, file.getName());
              VfsUtil.saveText(newFile, text);
              return Pair.of(null, newFile);
            } catch (IOException e2) {
              String message =
                  String.format(
                      "Failed to create File 'res/%1$s/%2$s' : %3$s",
                      folderName, file.getName(), e2.getMessage());
              return Pair.of(message, null);
            }
          }
        };

    WriteCommandAction<Pair<String, VirtualFile>> action =
        new WriteCommandAction<Pair<String, VirtualFile>>(project, "Add Resource") {
          @Override
          protected void run(@NotNull Result<Pair<String, VirtualFile>> result) throws Throwable {
            result.setResult(computable.compute());
          }
        };
    Pair<String, VirtualFile> result = action.execute().getResultObject();

    String error = result.getFirst();
    VirtualFile newFile = result.getSecond();
    if (error != null) {
      Messages.showErrorDialog(project, error, "Create Resource");
    } else {
      // First create a compatible configuration based on the current configuration
      if (configuration != null) {
        ConfigurationManager configurationManager = configuration.getConfigurationManager();
        configurationManager.createSimilar(newFile, file);
      }

      if (open) {
        OpenFileDescriptor descriptor = new OpenFileDescriptor(project, newFile, -1);
        FileEditorManager.getInstance(project).openEditor(descriptor, true);
      }
    }
  }
  /**
   * Called by {@link NewXmlFileWizard} to initialize the page with the selection received by the
   * wizard -- typically the current user workbench selection.
   *
   * <p>Things we expect to find out from the selection:
   *
   * <ul>
   *   <li>The project name, valid if it's an android nature.
   *   <li>The current folder, valid if it's a folder under /res
   *   <li>An existing filename, in which case the user will be asked whether to override it.
   * </ul>
   *
   * <p>The selection can also be set to a {@link Pair} of {@link IProject} and a workspace resource
   * path (where the resource path does not have to exist yet, such as res/anim/).
   *
   * @param selection The selection when the wizard was initiated.
   */
  private boolean initializeFromSelection(IStructuredSelection selection) {
    if (selection == null) {
      return false;
    }

    // Find the best match in the element list. In case there are multiple selected elements
    // select the one that provides the most information and assign them a score,
    // e.g. project=1 + folder=2 + file=4.
    IProject targetProject = null;
    String targetWsFolderPath = null;
    String targetFileName = null;
    int targetScore = 0;
    for (Object element : selection.toList()) {
      if (element instanceof IAdaptable) {
        IResource res = (IResource) ((IAdaptable) element).getAdapter(IResource.class);
        IProject project = res != null ? res.getProject() : null;

        // Is this an Android project?
        try {
          if (project == null || !project.hasNature(AdtConstants.NATURE_DEFAULT)) {
            continue;
          }
        } catch (CoreException e) {
          // checking the nature failed, ignore this resource
          continue;
        }

        int score = 1; // we have a valid project at least

        IPath wsFolderPath = null;
        String fileName = null;
        assert res != null; // Eclipse incorrectly thinks res could be null, so tell it no
        if (res.getType() == IResource.FOLDER) {
          wsFolderPath = res.getProjectRelativePath();
        } else if (res.getType() == IResource.FILE) {
          if (SdkUtils.endsWithIgnoreCase(res.getName(), DOT_XML)) {
            fileName = res.getName();
          }
          wsFolderPath = res.getParent().getProjectRelativePath();
        }

        // Disregard this folder selection if it doesn't point to /res/something
        if (wsFolderPath != null
            && wsFolderPath.segmentCount() > 1
            && SdkConstants.FD_RESOURCES.equals(wsFolderPath.segment(0))) {
          score += 2;
        } else {
          wsFolderPath = null;
          fileName = null;
        }

        score += fileName != null ? 4 : 0;

        if (score > targetScore) {
          targetScore = score;
          targetProject = project;
          targetWsFolderPath = wsFolderPath != null ? wsFolderPath.toString() : null;
          targetFileName = fileName;
        }
      } else if (element instanceof Pair<?, ?>) {
        // Pair of Project/String
        @SuppressWarnings("unchecked")
        Pair<IProject, String> pair = (Pair<IProject, String>) element;
        targetScore = 1;
        targetProject = pair.getFirst();
        targetWsFolderPath = pair.getSecond();
        targetFileName = "";
      }
    }

    if (targetProject == null) {
      // Try to figure out the project from the active editor
      IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
      if (window != null) {
        IWorkbenchPage page = window.getActivePage();
        if (page != null) {
          IEditorPart activeEditor = page.getActiveEditor();
          if (activeEditor instanceof AndroidXmlEditor) {
            Object input = ((AndroidXmlEditor) activeEditor).getEditorInput();
            if (input instanceof FileEditorInput) {
              FileEditorInput fileInput = (FileEditorInput) input;
              targetScore = 1;
              IFile file = fileInput.getFile();
              targetProject = file.getProject();
              IPath path = file.getParent().getProjectRelativePath();
              targetWsFolderPath = path != null ? path.toString() : null;
            }
          }
        }
      }
    }

    if (targetProject == null) {
      // If we didn't find a default project based on the selection, check how many
      // open Android projects we can find in the current workspace. If there's only
      // one, we'll just select it by default.
      IJavaProject[] projects = AdtUtils.getOpenAndroidProjects();
      if (projects != null && projects.length == 1) {
        targetScore = 1;
        targetProject = projects[0].getProject();
      }
    }

    // Now set the UI accordingly
    if (targetScore > 0) {
      mValues.project = targetProject;
      mValues.folderPath = targetWsFolderPath;
      mProjectButton.setSelectedProject(targetProject);
      mFileNameTextField.setText(targetFileName != null ? targetFileName : ""); // $NON-NLS-1$

      // If the current selection context corresponds to a specific file type,
      // select it.
      if (targetWsFolderPath != null) {
        int pos = targetWsFolderPath.lastIndexOf(WS_SEP_CHAR);
        if (pos >= 0) {
          targetWsFolderPath = targetWsFolderPath.substring(pos + 1);
        }
        String[] folderSegments = targetWsFolderPath.split(RES_QUALIFIER_SEP);
        if (folderSegments.length > 0) {
          mValues.configuration = FolderConfiguration.getConfig(folderSegments);
          String folderName = folderSegments[0];
          selectTypeFromFolder(folderName);
        }
      }
    }

    return true;
  }