summaryrefslogtreecommitdiff
path: root/src/plugins/installer/src/com/motorola/studio/android/installer/utilities/P2Installer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/installer/src/com/motorola/studio/android/installer/utilities/P2Installer.java')
-rw-r--r--src/plugins/installer/src/com/motorola/studio/android/installer/utilities/P2Installer.java520
1 files changed, 520 insertions, 0 deletions
diff --git a/src/plugins/installer/src/com/motorola/studio/android/installer/utilities/P2Installer.java b/src/plugins/installer/src/com/motorola/studio/android/installer/utilities/P2Installer.java
new file mode 100644
index 0000000..6dbd901
--- /dev/null
+++ b/src/plugins/installer/src/com/motorola/studio/android/installer/utilities/P2Installer.java
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.motorola.studio.android.installer.utilities;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.operations.InstallOperation;
+import org.eclipse.equinox.p2.operations.Update;
+import org.eclipse.equinox.p2.operations.UpdateOperation;
+import org.eclipse.equinox.p2.query.IQuery;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.installer.InstallerException;
+import com.motorola.studio.android.installer.InstallerPlugin;
+import com.motorola.studio.android.installer.i18n.InstallerNLS;
+import com.motorola.studio.android.installer.utilities.IInstallManager.BACKEND;
+import com.motorola.studio.android.installer.utilities.IInstallManager.CATEGORY;
+
+/**
+ * Implements the methods for using the INstall framework with P2
+ */
+class P2Installer
+{
+
+ private final String LANGUAGE_PACK_QUERY =
+ "this.id ~= /com.motorola.studio.android.feature.nl*/";
+
+ private final String NKD_QUERY = "org.eclipse.sequoyah.android.cdt.feature.feature.group";
+
+ private final String SUBVERSION_QUERY = "org.eclipse.team.svn.feature.group";
+
+ private final String EGIT_QUERY = "org.eclipse.egit.feature.group";
+
+ private final String MYLYN_QUERY1 = "org.eclipse.mylyn.context_feature.feature.group";
+
+ private final String MYLYN_QUERY2 = "org.eclipse.mylyn_feature.feature.group";
+
+ private final String CVS_QUERY = "org.eclipse.cvs.feature.group";
+
+ private final HashMap<URI, IMetadataRepository> mainRepositories =
+ new HashMap<URI, IMetadataRepository>();
+
+ //will be used to record an instance of a InstallOperation. If it did not exist, we would have to instantiate
+ //the InstallOperation on validate and download methods
+ private InstallOperation installOp;
+
+ private UpdateOperation up;
+
+ /**
+ *
+ */
+ public void resetP2Installer()
+ {
+ mainRepositories.clear();
+ installOp = null;
+ }
+
+ private boolean isAllRepositoriesLoaded(Collection<URI> links)
+ {
+
+ boolean isAllLoaded = false;
+
+ if (!mainRepositories.isEmpty())
+ {
+ isAllLoaded = true;
+ for (URI uri : links)
+ {
+ if (!mainRepositories.containsKey(uri))
+ {
+ isAllLoaded = false;
+ break;
+ }
+ }
+ }
+ return isAllLoaded;
+ }
+
+ /**
+ * Load the P2 repositories.
+ * Initially the method verifies if the repositories were already instantiated and is
+ * on the metadata and arfacts maps (metadataRepositoriesMap, artifactRepositoriesMap).
+ * If yes, they should not be instantiated again. Otherwise, the repository and its references
+ * will be loaded.
+ *
+ * If the global maps did not exist, every time that methods validateInstallation, listAvailableUpdates
+ * and downloadAndInstall were called, all the repositories would be loaded again.
+ */
+ private IStatus loadRepositories(List<URI> links, IProgressMonitor monitor)
+ {
+ StudioLogger.debug(this, "loading repositories...");
+ IStatus status = Status.OK_STATUS;
+
+ StudioLogger.debug(this, "there are not loaded repositories");
+ SubMonitor submonitor = SubMonitor.convert(monitor);
+
+ int reposSize = 0;
+ if (links != null)
+ {
+ reposSize += links.size();
+ }
+
+ submonitor.beginTask(InstallerNLS.AbstractConfigurationPage_LoadingRepositoriesTask,
+ reposSize * 100);
+
+ boolean isAllRepositoriesLoaded = isAllRepositoriesLoaded(links);
+
+ if (!isAllRepositoriesLoaded)
+ {
+ P2RepositoriesFactory p2RepositoriesFactory = P2RepositoriesFactory.getInstance();
+ for (URI uri : links)
+ {
+ IMetadataRepository metadataRepository = null;
+ //loads metadata repositories from URIs
+ try
+ {
+ metadataRepository =
+ p2RepositoriesFactory.getMetadataRepository(uri, true,
+ submonitor.newChild(100));
+ mainRepositories.put(uri, metadataRepository);
+
+ }
+ catch (Exception e)
+ {
+ status = new Status(IStatus.WARNING, InstallerPlugin.PLUGIN_ID, e.getMessage());
+ StudioLogger.error(this.getClass(),
+ "could not instantiate repository from URI " + uri);
+ }
+
+ }
+ }
+ else
+ {
+ submonitor.done();
+ }
+
+ return status;
+ }
+
+ /**
+ * Loads InstallableItems based on category and links. They are put into the collection listToFill
+ *
+ * @param listToFill
+ * @param links
+ * @param category
+ * @param monitor
+ * @return
+ * @throws InstallerException
+ */
+ public IStatus listAllAvailableInstallItems(Collection<InstallableItem> listToFill,
+ List<URI> uriList, CATEGORY category, IProgressMonitor monitor)
+ throws InstallerException
+ {
+
+ StudioLogger.debug(this, "listing available installable items...");
+ IStatus status =
+ new Status(IStatus.ERROR, InstallerPlugin.PLUGIN_ID, 0,
+ InstallerNLS.P2Installer_Could_Not_Find_Proper_Backend, null);
+
+ //this links list is created because the method loadRepositories remove some items of the list
+ //if the repositorie is already loaded.
+ List<URI> links = new ArrayList<URI>();
+ links.addAll(uriList);
+
+ SubMonitor submonitor = SubMonitor.convert(monitor);
+ submonitor.beginTask(InstallerNLS.P2Installer_Loading_Repositories, 100);
+
+ status = loadRepositories(links, submonitor.newChild(20));
+
+ Collection<IInstallableUnit> units = new HashSet<IInstallableUnit>();
+
+ IQuery<IInstallableUnit> query = null;
+
+ //category is used to create the correct query
+ switch (category)
+ {
+ case LANG_PACKS:
+ {
+ //Filter IUs in order to receive only lang packs
+ query = QueryUtil.createMatchQuery(LANGUAGE_PACK_QUERY); //$NON-NLS-1$
+ break;
+ }
+
+ case NDK:
+ {
+ //Filter IUs in order to receive only NDK related
+ query = QueryUtil.createIUQuery(NKD_QUERY); //$NON-NLS-1$
+ break;
+ }
+
+ case UPDATE_STUDIO:
+ {
+ //No special query needed
+ break;
+ }
+
+ case OTHER_COMPONENTS:
+ {
+ Collection<IQuery<IInstallableUnit>> queries =
+ new ArrayList<IQuery<IInstallableUnit>>();
+ queries.add(QueryUtil.createIUQuery(SUBVERSION_QUERY));
+ queries.add(QueryUtil.createIUQuery(MYLYN_QUERY1));
+ queries.add(QueryUtil.createIUQuery(MYLYN_QUERY2));
+ queries.add(QueryUtil.createIUQuery(CVS_QUERY));
+ queries.add(QueryUtil.createIUQuery(EGIT_QUERY));
+
+ query = QueryUtil.createCompoundQuery(queries, false);
+ break;
+ }
+ default:
+ {
+ // No specific query to use as filter, download them all!
+ break;
+ }
+ }
+
+ int monitorWorkSize = 0;
+ try
+ {
+ monitorWorkSize = 40 / mainRepositories.values().size();
+ }
+ catch (ArithmeticException e)
+ {
+ // Do nothing
+ }
+ for (Iterator<IMetadataRepository> iterator = mainRepositories.values().iterator(); iterator
+ .hasNext();)
+ {
+ IMetadataRepository repository = iterator.next();
+ try
+ {
+
+ Collection<IInstallableUnit> ius =
+ P2Utilities.getInstallableUnits(repository, query,
+ submonitor.newChild(monitorWorkSize));
+ units.addAll(ius);
+
+ status = Status.OK_STATUS;
+ }
+ catch (InstallerException e)
+ {
+ StudioLogger.error(this.getClass(), "could not retrieve installable units");
+ status =
+ new Status(IStatus.ERROR, InstallerPlugin.PLUGIN_ID, 0,
+ "Error retrieving available installable units", null);
+
+ }
+ }
+
+ monitorWorkSize = 0;
+ try
+ {
+ monitorWorkSize = 40 / units.size();
+ }
+ catch (ArithmeticException e)
+ {
+ // Do nothing
+ }
+ for (Iterator<IInstallableUnit> iterator = units.iterator(); iterator.hasNext();)
+ {
+ IInstallableUnit iInstallableUnit = iterator.next();
+
+ if (P2Utilities.isGroup(iInstallableUnit))
+ {
+ // I'm only returning groups since only groups
+ // are listed for the user to select what to install
+ InstallableItem item = iu2InstallableItem(iInstallableUnit, monitor);
+ listToFill.add(item);
+ }
+
+ }
+
+ if (status.getMessage().equals("org.eclipse.core.runtime.OperationCanceledException"))
+ {
+ StudioLogger.debug(this, "operation was canceled");
+ status =
+ new Status(Status.CANCEL, status.getPlugin(), status.getCode(),
+ status.getMessage(), status.getException());
+ }
+
+ submonitor.done();
+
+ return status;
+ }
+
+ //Translates a P2 installable unit to a InstallableItem object
+ private InstallableItem iu2InstallableItem(IInstallableUnit unit, IProgressMonitor monitor)
+ throws InstallerException
+ {
+ InstallableItem item = new P2InstallableItem();
+ item.setData(unit);
+ item.setBundleID(unit.getId());
+ item.setInstalled(P2Utilities.isInstalled(unit, monitor));
+ item.setLicense(P2Utilities.getLicenseText(unit));
+ item.setDisplayName(P2Utilities.getIUExternalizedValue(unit, IInstallableUnit.PROP_NAME));
+ item.setDescription(P2Utilities.getIUExternalizedValue(unit,
+ IInstallableUnit.PROP_DESCRIPTION));
+ item.setProvider(P2Utilities.getIUExternalizedValue(unit, IInstallableUnit.PROP_PROVIDER));
+ item.setRequirementsIds(P2Utilities.getRequirements(unit));
+ return item;
+ }
+
+ /**
+ * Method used to install the installable items. The repositories and installOp should be already loaded,
+ * otherwise they will be.
+ *
+ * @param links
+ * @param itemsToDownloadAndInstall
+ * @param monitor
+ * @return
+ */
+ public IStatus downloadAndInstall(List<URI> links,
+ Collection<InstallableItem> itemsToDownloadAndInstall, IProgressMonitor monitor)
+ {
+ StudioLogger.debug(this, "downloadAndInstall: installing selected installable items");
+ IStatus status =
+ new Status(IStatus.ERROR, InstallerPlugin.PLUGIN_ID, 0,
+ InstallerNLS.P2Installer_Could_Not_Install_Selected_Items, null);
+
+ if ((itemsToDownloadAndInstall != null) && (!itemsToDownloadAndInstall.isEmpty()))
+ {
+
+ final List<IInstallableUnit> installableUnits = new ArrayList<IInstallableUnit>();
+
+ for (InstallableItem item : itemsToDownloadAndInstall)
+ {
+ IInstallableUnit unit = (IInstallableUnit) item.getData();
+ installableUnits.add(unit);
+ }
+
+ try
+ {
+ if (installOp == null)
+ {
+ status = loadRepositories(links, monitor);
+
+ status =
+ P2Utilities.installIu(installableUnits, mainRepositories.values(),
+ monitor);
+ }
+ else
+ {
+ status = P2Utilities.installIu(installableUnits, installOp, monitor);
+ }
+ }
+ catch (InstallerException e)
+ {
+ StudioLogger.error(this.getClass(), "could not install selected installable unit");
+ status = new Status(IStatus.WARNING, InstallerPlugin.PLUGIN_ID, e.getMessage());
+ }
+
+ //clean installOp and maps. After the installation has occurred, they can be cleaned.
+ installOp = null;
+ mainRepositories.clear();
+
+ return status;
+ }
+ return status;
+ }
+
+ /**
+ * Updates studio.
+ * IMPORTANT: the method listAllAvailableUpdates MUST be called first
+ *
+ * @param monitor
+ * @return
+ */
+ public IStatus updateStudio(IProgressMonitor monitor)
+ {
+ StudioLogger.debug(this, "updateStudio: installing selected installable items");
+ IStatus status =
+ new Status(IStatus.ERROR, InstallerPlugin.PLUGIN_ID, 0,
+ InstallerNLS.P2Installer_Could_Not_Install_Selected_Items, null);
+
+ try
+ {
+ status = P2Utilities.updateIu(up, monitor);
+
+ }
+ catch (Exception e)
+ {
+ StudioLogger.error(this.getClass(), "could not install selected installable unit.", e);
+ status = new Status(IStatus.WARNING, InstallerPlugin.PLUGIN_ID, e.getMessage());
+ }
+
+ return status;
+ }
+
+ /**
+ * @param itemsToDownloadAndInstall
+ * @param backEnd
+ * @param monitor
+ * @return
+ */
+ public IStatus validateInstallation(List<URI> links,
+ Collection<InstallableItem> itemsToDownloadAndInstall, BACKEND backEnd,
+ IProgressMonitor monitor)
+ {
+ // installOp will be loaded as global variable because will be used on method downloadAndInstall.
+ // It must not be instantiated twice if it were already validated.
+ installOp = null;
+
+ List<URI> allURIs = new ArrayList<URI>(mainRepositories.keySet());
+ for (Iterator<URI> iterator = allURIs.iterator(); iterator.hasNext();)
+ {
+ URI uri = iterator.next();
+ if (!links.contains(uri))
+ {
+ mainRepositories.remove(uri);
+ }
+
+ }
+
+ Collection<IInstallableUnit> temp = new HashSet<IInstallableUnit>();
+
+ loadRepositories(links, monitor);
+
+ for (Iterator<InstallableItem> iterator = itemsToDownloadAndInstall.iterator(); iterator
+ .hasNext();)
+ {
+ InstallableItem iInstallableItem = iterator.next();
+ temp.add((IInstallableUnit) iInstallableItem.getData());
+
+ }
+ if ((itemsToDownloadAndInstall != null) && (itemsToDownloadAndInstall.size() > 0))
+ {
+ try
+ {
+ installOp =
+ P2Utilities.getInstallOperation(temp, mainRepositories.values(), monitor);
+ }
+ catch (InstallerException e)
+ {
+ StudioLogger.error(this.getClass(), "Could not retrieve install operation");
+
+ return new Status(IStatus.ERROR, InstallerPlugin.PLUGIN_ID, 0, e.getMessage(), null);
+
+ }
+
+ }
+
+ return installOp != null ? installOp.getResolutionResult() : Status.CANCEL_STATUS;
+
+ }
+
+ /**
+ * Lists all available updates given a link.
+ * After this method the method updateStudio can be invoked
+ *
+ * @param listToFill
+ * @param links
+ * @param category
+ * @param backEnd
+ * @param monitor
+ * @return
+ * @throws InstallerException
+ */
+ public IStatus listAllAvailableUpdates(Collection<InstallableItem> listToFill, List<URI> links,
+ CATEGORY category, BACKEND backEnd, IProgressMonitor monitor) throws InstallerException
+ {
+ IStatus result = Status.OK_STATUS;
+
+ try
+ {
+ up = P2Utilities.getUpdateOperation(links, monitor);
+ if (up != null)
+ {
+
+ result = up.getResolutionResult();
+ Update[] updates = up.getSelectedUpdates();
+
+ if (listToFill != null)
+ {
+ for (int i = 0; i < updates.length; i++)
+ {
+ InstallableItem item = iu2InstallableItem(updates[i].replacement, monitor);
+ listToFill.add(item);
+ }
+ }
+ }
+ else
+ {
+ result = Status.CANCEL_STATUS;
+ }
+ }
+ catch (Exception e)
+ {
+ StudioLogger.error(this.getClass(), "Error looking for updates. ", e);
+ result = new Status(IStatus.ERROR, InstallerPlugin.PLUGIN_ID, 0, e.getMessage(), null);
+ }
+
+ return result;
+ }
+
+}