Skip to main content
summaryrefslogtreecommitdiffstats
blob: 4ed55747e0007891d0dcd3b0f81c31ae574da4ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*******************************************************************************
 * Copyright (c) 2008, 2011 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.eclipse;

import java.io.File;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.publisher.eclipse.ExecutablesDescriptor;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.publisher.*;
import org.eclipse.equinox.p2.publisher.actions.VersionAdvice;
import org.eclipse.equinox.p2.query.QueryUtil;

/**
 * Create IUs and CUs that represent the entire launcher for an application.  This includes
 * the executable, the launcher fragments as well as the CUs required to install and configure
 * these elements.
 */
public class ApplicationLauncherAction extends AbstractPublisherAction {

	private final String flavor;
	private final String[] configSpecs;
	private final File location;
	private final String executableName;
	private final Version version;
	private final String id;

	/**
	 * 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 + ".application"; //$NON-NLS-1$
	}

	public ApplicationLauncherAction(String id, Version version, String flavor, String executableName, File location, String[] configSpecs) {
		this.flavor = flavor;
		this.configSpecs = configSpecs;
		this.id = id;
		this.version = version;
		this.executableName = executableName;
		this.location = location;
	}

	@Override
	public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
		// Create the basic actions and run them putting the IUs in a temporary result
		Collection<IPublisherAction> actions = createActions(publisherInfo);
		createAdvice(publisherInfo, results);
		IPublisherResult innerResult = new PublisherResult();
		MultiStatus finalStatus = new MultiStatus(ApplicationLauncherAction.class.getName(), 0, "publishing result", null); //$NON-NLS-1$
		for (IPublisherAction action : actions) {
			if (monitor.isCanceled())
				return Status.CANCEL_STATUS;
			finalStatus.merge(action.perform(publisherInfo, innerResult, monitor));
		}
		if (!finalStatus.isOK())
			return finalStatus;
		// 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);
		publishApplicationLauncherIU(innerResult.getIUs(null, IPublisherResult.ROOT), results);
		return Status.OK_STATUS;
	}

	/**
	 * Create advice needed by the actions related to and following this action
	 */
	private void createAdvice(IPublisherInfo publisherInfo, IPublisherResult results) {
		createLauncherAdvice(publisherInfo, results);
	}

	/**
	 * Create and register advice that will tell people what versions of the launcher bundle and 
	 * fragments are in use in this particular result.
	 */
	private void createLauncherAdvice(IPublisherInfo publisherInfo, IPublisherResult results) {
		Collection<IInstallableUnit> ius = getIUs(results.getIUs(null, null), EquinoxLauncherCUAction.ORG_ECLIPSE_EQUINOX_LAUNCHER);
		if (publisherInfo.getContextMetadataRepository() != null)
			ius.addAll(getIUs(publisherInfo.getContextMetadataRepository().query(QueryUtil.ALL_UNITS, null).toUnmodifiableSet(), EquinoxLauncherCUAction.ORG_ECLIPSE_EQUINOX_LAUNCHER));
		VersionAdvice advice = new VersionAdvice();
		boolean found = false;
		for (IInstallableUnit iu : ius) {
			// skip over source bundles and fragments
			// TODO should we use the source property here rather than magic name matching?
			if (iu.getId().endsWith(".source") || QueryUtil.isFragment(iu)) //$NON-NLS-1$
				continue;
			advice.setVersion(IInstallableUnit.NAMESPACE_IU_ID, iu.getId(), iu.getVersion());
			found = true;
		}
		if (found)
			publisherInfo.addAdvice(advice);
	}

	private Collection<IInstallableUnit> getIUs(Collection<IInstallableUnit> ius, String prefix) {
		Set<IInstallableUnit> result = new HashSet<>();
		for (IInstallableUnit tmp : ius) {
			if (tmp.getId().startsWith(prefix))
				result.add(tmp);
		}
		return result;
	}

	private void publishApplicationLauncherIU(Collection<? extends IVersionedId> children, IPublisherResult result) {
		InstallableUnitDescription descriptor = createParentIU(children, computeIUId(id, flavor), version);
		descriptor.setSingleton(true);
		IInstallableUnit rootIU = MetadataFactory.createInstallableUnit(descriptor);
		if (rootIU == null)
			return;
		result.addIU(rootIU, IPublisherResult.ROOT);
	}

	private Collection<IPublisherAction> createActions(IPublisherInfo publisherInfo) {
		Collection<IPublisherAction> actions = new ArrayList<>();
		actions.add(new EquinoxLauncherCUAction(flavor, configSpecs));
		actions.addAll(createExecutablesActions(configSpecs));
		return actions;
	}

	protected Collection<IPublisherAction> createExecutablesActions(String[] configs) {
		Collection<IPublisherAction> actions = new ArrayList<>(configs.length);
		for (int i = 0; i < configs.length; i++) {
			ExecutablesDescriptor executables = computeExecutables(configs[i]);
			IPublisherAction action = new EquinoxExecutableAction(executables, configs[i], id, version, flavor);
			actions.add(action);
		}
		return actions;
	}

	protected ExecutablesDescriptor computeExecutables(String configSpec) {
		// See if we know about an executables feature then use it as the source
		ExecutablesDescriptor result = ExecutablesDescriptor.createExecutablesFromFeature(location, configSpec);
		if (result != null)
			return result;
		// otherwise, assume that we are running against an Eclipse install and do the default thing
		String os = AbstractPublisherAction.parseConfigSpec(configSpec)[1];
		return ExecutablesDescriptor.createDescriptor(os, executableName, location);
	}
}

Back to the top