/******************************************************************************* * Copyright (c) 2008, 2009 Code 9 and others. All rights reserved. This * program and the accompanying materials are made available under the terms of * the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Code 9 - initial API and implementation * IBM - ongoing development ******************************************************************************/ package org.eclipse.equinox.p2.publisher.actions; import java.io.File; import java.util.*; import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.core.helpers.FileUtils.IPathComputer; import org.eclipse.equinox.p2.metadata.*; import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription; import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription; import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; import org.eclipse.equinox.p2.publisher.*; import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; public class RootFilesAction extends AbstractPublisherAction { private String idBase; private Version version; private String flavor; private boolean createParent = true; /** * Returns the id of the top level IU published by this action for the given id and flavor. * @param id the id of the application being published * @param flavor the flavor being published * @return the if for ius published by this action */ public static String computeIUId(String id, String flavor) { return flavor + id + ".rootfiles"; //$NON-NLS-1$ } public RootFilesAction(IPublisherInfo info, String idBase, Version version, String flavor) { this.idBase = idBase == null ? "org.eclipse" : idBase; //$NON-NLS-1$ this.version = version; this.flavor = flavor; } public void setCreateParent(boolean createParent) { this.createParent = createParent; } public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) { setPublisherInfo(publisherInfo); IPublisherResult innerResult = new PublisherResult(); // we have N platforms, generate a CU for each // TODO try and find common properties across platforms String[] configSpecs = publisherInfo.getConfigurations(); for (int i = 0; i < configSpecs.length; i++) { if (monitor.isCanceled()) return Status.CANCEL_STATUS; generateRootFileIUs(configSpecs[i], innerResult); } // merge the IUs into the final result as non-roots and create a parent IU that captures them all results.merge(innerResult, IPublisherResult.MERGE_ALL_NON_ROOT); if (createParent) publishTopLevelRootFilesIU(innerResult.getIUs(null, IPublisherResult.ROOT), results); if (monitor.isCanceled()) return Status.CANCEL_STATUS; return Status.OK_STATUS; } private void publishTopLevelRootFilesIU(Collection<? extends IVersionedId> children, IPublisherResult result) { InstallableUnitDescription descriptor = createParentIU(children, computeIUId(idBase, flavor), version); descriptor.setSingleton(true); IInstallableUnit rootIU = MetadataFactory.createInstallableUnit(descriptor); if (rootIU == null) return; result.addIU(rootIU, IPublisherResult.ROOT); } /** * Generates IUs and CUs for the files that make up the root files for a given * ws/os/arch combination. */ private void generateRootFileIUs(String configSpec, IPublisherResult result) { // Create the IU for the executable InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription(); iu.setSingleton(true); String idPrefix = idBase + ".rootfiles"; //$NON-NLS-1$ String iuId = idPrefix + '.' + createIdString(configSpec); iu.setId(iuId); iu.setVersion(version); IMatchExpression<IInstallableUnit> filter = createFilterSpec(configSpec); iu.setFilter(filter); IArtifactKey key = PublisherHelper.createBinaryArtifactKey(iuId, version); iu.setArtifacts(new IArtifactKey[] {key}); iu.setTouchpointType(PublisherHelper.TOUCHPOINT_NATIVE); IProvidedCapability launcherCapability = MetadataFactory.createProvidedCapability(flavor + idBase, idPrefix, version); iu.setCapabilities(new IProvidedCapability[] {PublisherHelper.createSelfCapability(iuId, version), launcherCapability}); result.addIU(MetadataFactory.createInstallableUnit(iu), IPublisherResult.ROOT); // Create the CU that installs/configures the executable InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription(); String configUnitId = flavor + iuId; cu.setId(configUnitId); cu.setVersion(version); cu.setFilter(filter); cu.setHost(new IRequirement[] {MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, iuId, new VersionRange(version, true, version, true), null, false, false)}); cu.setProperty(InstallableUnitDescription.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString()); //TODO bug 218890, would like the fragment to provide the launcher capability as well, but can't right now. cu.setCapabilities(new IProvidedCapability[] {PublisherHelper.createSelfCapability(configUnitId, version)}); cu.setTouchpointType(PublisherHelper.TOUCHPOINT_NATIVE); Map<String, String> touchpointData = new HashMap<String, String>(); String configurationData = "unzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$ touchpointData.put("install", configurationData); //$NON-NLS-1$ String unConfigurationData = "cleanupzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$ touchpointData.put("uninstall", unConfigurationData); //$NON-NLS-1$ processTouchpointAdvice(cu, touchpointData, info, configSpec); IInstallableUnit unit = MetadataFactory.createInstallableUnit(cu); result.addIU(unit, IPublisherResult.ROOT); if ((info.getArtifactOptions() & (IPublisherInfo.A_INDEX | IPublisherInfo.A_PUBLISH)) > 0) { // Create the artifact descriptor. we have several files so no path on disk IArtifactDescriptor descriptor = PublisherHelper.createArtifactDescriptor(info, key, null); IRootFilesAdvice advice = getAdvice(configSpec); publishArtifact(descriptor, advice.getIncludedFiles(), advice.getExcludedFiles(), info, createPrefixComputer(advice.getRoot())); } } private IPathComputer createPrefixComputer(File root) { if (root == null) return createParentPrefixComputer(1); return createRootPrefixComputer(root); } /** * Compiles the <class>IRootFilesAdvice</class> from the <code>info</code> into one <class>IRootFilesAdvice</class> * and returns the result. * @param configSpec * @return a compilation of <class>IRootfilesAdvice</class> from the <code>info</code>. */ private IRootFilesAdvice getAdvice(String configSpec) { Collection<IRootFilesAdvice> advice = info.getAdvice(configSpec, true, null, null, IRootFilesAdvice.class); ArrayList<File> inclusions = new ArrayList<File>(); ArrayList<File> exclusions = new ArrayList<File>(); File root = null; for (IRootFilesAdvice entry : advice) { // TODO for now we simply get root from the first advice that has one if (root == null) root = entry.getRoot(); File[] list = entry.getIncludedFiles(); if (list != null) inclusions.addAll(Arrays.asList(list)); list = entry.getExcludedFiles(); if (list != null) exclusions.addAll(Arrays.asList(list)); } File[] includeList = inclusions.toArray(new File[inclusions.size()]); File[] excludeList = exclusions.toArray(new File[exclusions.size()]); return new RootFilesAdvice(root, includeList, excludeList, configSpec); } }