Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: f1fdd72f37d0e8dc0d82e0c4d7b3ced2d36fd3a1 (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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/*******************************************************************************
 * Copyright (c) 2010, 2017 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.reconciler.dropins;

import java.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.p2.update.Configuration;
import org.eclipse.equinox.internal.p2.update.Site;
import org.eclipse.equinox.p2.core.ProvisionException;

public class AbstractSharedBundleProductTest extends AbstractReconcilerTest {

	public static final String PLATFORM_BASE = "platform:/base/";
	protected static String sharedLocationURL = null;

	public AbstractSharedBundleProductTest(String name) {
		super(name);
	}

	public AbstractSharedBundleProductTest(String name, String location) {
		super(name, location);
	}

	private Map<String, BundleInfo> getBootstrapBundles() {
		Map<String, BundleInfo> result = new HashMap();

		// TODO deal with fragments
		//	list.add("org.eclipse.core.net.win32.x86");
		//	list.add("org.eclipse.equinox.security.win32.x86");
		final String[] bootstrap = new String[] { //
				"org.eclipse.core.contenttype", //
				"org.eclipse.core.expressions", //
				"org.eclipse.core.jobs", //
				"org.eclipse.core.net", //
				"org.eclipse.core.runtime", //
				"org.eclipse.core.runtime.compatibility.registry", //
				"org.eclipse.ecf", //
				"org.eclipse.ecf.filetransfer", //
				"org.eclipse.ecf.identity", //
				"org.eclipse.ecf.provider.filetransfer", //
				"org.eclipse.ecf.provider.filetransfer.ssl", //
				"org.eclipse.ecf.ssl", //
				"org.eclipse.equinox.app", //
				"org.eclipse.equinox.common", //
				"org.eclipse.equinox.ds", //
				"org.eclipse.equinox.frameworkadmin", //
				"org.eclipse.equinox.frameworkadmin.equinox", //
				"org.eclipse.equinox.p2.artifact.repository", //
				"org.eclipse.equinox.p2.core", //
				"org.eclipse.equinox.p2.director", //
				"org.eclipse.equinox.p2.directorywatcher", //
				"org.eclipse.equinox.p2.engine", //
				"org.eclipse.equinox.p2.extensionlocation", //
				"org.eclipse.equinox.p2.garbagecollector", //
				"org.eclipse.equinox.p2.jarprocessor", //
				"org.eclipse.equinox.p2.metadata", //
				"org.eclipse.equinox.p2.metadata.repository", //
				"org.eclipse.equinox.p2.publisher", //
				"org.eclipse.equinox.p2.ql", //
				"org.eclipse.equinox.p2.reconciler.dropins", //
				"org.eclipse.equinox.p2.repository", //
				"org.eclipse.equinox.p2.touchpoint.eclipse", //
				"org.eclipse.equinox.p2.touchpoint.natives", //
				"org.eclipse.equinox.preferences", //
				"org.eclipse.equinox.registry", //
				"org.eclipse.equinox.security", //
				"org.eclipse.equinox.simpleconfigurator", //
				"org.eclipse.equinox.simpleconfigurator.manipulator", //
				"org.eclipse.equinox.util", //
				"org.eclipse.osgi", //
				"org.eclipse.osgi.services", //
				"org.sat4j.core", //
				"org.sat4j.pb"};

		// load the bundles.info and put the results into a map for easier lookup
		BundleInfo[] infos = null;
		try {
			infos = loadBundlesInfo(getBundlesInfo());
		} catch (IOException e) {
			fail("Exception occurred loading bundles.info file from: " + getBundlesInfo().getAbsolutePath(), e);
		}
		Map<String, BundleInfo> map = new HashMap();
		for (int i = 0; infos != null && i < infos.length; i++) {
			map.put(infos[i].getSymbolicName(), infos[i]);
			// always add the launcher bundles. do it here because we don't know what os/ws config we will have
			if (infos[i].getSymbolicName().contains("equinox.launcher"))
				result.put(infos[i].getSymbolicName(), infos[i]);
		}

		// just add the bootstrap bundles into the result before returning
		for (int i = 0; i < bootstrap.length; i++) {
			BundleInfo info = map.get(bootstrap[i]);
			if (info != null)
				result.put(info.getSymbolicName(), info);
		}
		return result;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.p2.tests.reconciler.dropins.AbstractReconcilerTest#initialize()
	 */
	@Override
	public void initialize() throws Exception {

		// extract the platform archive to the output folder
		super.initialize();

		// setup the shared bundle location
		File shared = new File(output, "shared");
		shared.mkdirs();
		assertTrue("0.0", shared.isDirectory());

		// move all features to the shared location
		File features = new File(output, "eclipse/features");
		File sharedFeatureLocation = new File(shared, "features");
		move("1.0", features, sharedFeatureLocation);

		// move all bundles (except launchers) to the shared location
		File bundles = new File(output, "eclipse/plugins");
		File sharedBundleLocation = new File(shared, "plugins");
		FileFilter filter = pathname -> !pathname.getName().contains("equinox.launcher");
		move("2.0", bundles, sharedBundleLocation, filter);

		// update the bundles.info file to contain only the boostrap bundles
		// and also update their locations.
		Map<String, BundleInfo> infos = getBootstrapBundles();
		updateBundlesInfo(infos, sharedBundleLocation);

		// update the platform.xml file to a user-include policy pointing
		// to the bundles in the shared location.
		updateConfiguration(infos, shared);

		// update the config.ini file to make sure the framework JAR
		// is pointing to the right location
		updateConfigIni(infos);

		// reconcile to ensure everything is ok
		reconcile("5.0");
	}

	private void updateConfigIni(Map<String, BundleInfo> infos) {
		File location = new File(output, "eclipse/configuration/config.ini");
		Properties ini = new Properties();
		try (InputStream input = new BufferedInputStream(new FileInputStream(location))) {
			ini.load(input);
		} catch (IOException e) {
			fail("Exception while loading config.ini from: " + location.getAbsolutePath(), e);
		}
		BundleInfo framework = infos.get("org.eclipse.osgi");
		assertNotNull("Unable to find framework in list of bootstrap bundles.", framework);
		ini.put("osgi.framework", framework.getLocation().toString());
		try (OutputStream out = new BufferedOutputStream(new FileOutputStream(location));) {
			ini.store(out, null);
		} catch (IOException e) {
			fail("Exception while saving config.ini to: " + location.getAbsolutePath(), e);
		}
	}

	private void updateConfiguration(Map<String, BundleInfo> infos, File shared) {
		Configuration config = new Configuration();
		config.setTransient(false);
		config.setVersion("3.0");

		// add site containing all the bootstrap bundles
		Site site = new Site();
		try {
			sharedLocationURL = shared.toURI().toURL().toExternalForm();
			site.setUrl(sharedLocationURL);
		} catch (MalformedURLException e) {
			fail("Exception occurred while converting site location to URL: " + shared.getAbsolutePath(), e);
		}
		site.setPolicy(Site.POLICY_USER_INCLUDE);
		site.setUpdateable(false);
		site.setEnabled(true);
		URI sharedURI = shared.toURI();
		for (BundleInfo info : infos.values()) {
			URI relative = URIUtil.makeRelative(info.getLocation(), sharedURI);
			site.addPlugin(relative.toString());
		}
		config.add(site);

		// add a site for platform:/base/
		site = new Site();
		site.setUrl(PLATFORM_BASE);
		site.setPolicy(Site.POLICY_USER_EXCLUDE);
		site.setUpdateable(true);
		site.setEnabled(true);
		config.add(site);

		// save the new config
		saveConfiguration(config);
	}

	public void removeBundlesFromConfiguration(Configuration config, String[] locations) {
		for (String location : locations)
			removeBundleFromConfiguration(config, location);
	}

	protected Site getSharedSite(Configuration config) {
		for (Site site : config.getSites()) {
			if (sharedLocationURL != null && sharedLocationURL.equals(site.getUrl()))
				return site;
		}
		return null;
	}

	public boolean removeBundleFromConfiguration(Configuration config, String location) {
		Site shared = getSharedSite(config);
		assertNotNull("Unable to determine shared site from configuration.", shared);
		boolean removed = shared.removePlugin(location);
		if (removed)
			return true;
		// try again with a relative path
		URI relative = null;
		try {
			relative = URIUtil.makeRelative(new URI(location), new URI(sharedLocationURL));
		} catch (URISyntaxException e) {
			fail("Exception while converting location to URI.", e);
		}
		return shared.removePlugin(relative.toString());
	}

	public void addBundlesToConfigurations(Configuration config, String[] locations) {
		for (String location : locations)
			addBundleToConfiguration(config, location);
	}

	public void addBundleToConfiguration(Configuration config, String location) {
		Site shared = getSharedSite(config);
		assertNotNull("Unable to determine shared site from configuration.", shared);
		URI relative = null;
		try {
			relative = URIUtil.makeRelative(new URI(location), new URI(sharedLocationURL));
		} catch (URISyntaxException e) {
			fail("Exception while converting location to URI.", e);
		}
		shared.addPlugin(relative.toString());
	}

	protected File getPlatformXMLLocation() {
		return new File(output, "eclipse/configuration/org.eclipse.update/platform.xml");
	}

	public void saveConfiguration(Configuration config) {
		File configLocation = getPlatformXMLLocation();
		try {
			config.save(configLocation, null);
		} catch (ProvisionException e) {
			fail("Exception occurred while saving configuration: " + configLocation.getAbsolutePath(), e);
		}
	}

	public Configuration loadConfiguration() {
		File configLocation = getPlatformXMLLocation();
		try {
			return Configuration.load(configLocation, null);
		} catch (ProvisionException e) {
			fail("Exception loading configuration.", e);
		}
		// avoid compile error
		return null;
	}

	private void updateBundlesInfo(Map<String, BundleInfo> infos, File sharedBundleLocation) {
		for (BundleInfo info : infos.values()) {
			if (info.getSymbolicName().contains("equinox.launcher"))
				continue;
			File location = new File(sharedBundleLocation, new Path(info.getLocation().toString()).lastSegment());
			assertTrue("3.1." + location.getAbsolutePath(), location.exists());
			info.setLocation(location.toURI());
		}
		// re-write the bundles.info file with the new information
		try {
			saveBundlesInfo(infos.values().toArray(new BundleInfo[infos.size()]), getBundlesInfo());
		} catch (IOException e) {
			fail("Exception occurred while saving bundles.info to: " + getBundlesInfo().getAbsolutePath(), e);
		}
	}

}

Back to the top