1 /*******************************************************************************
2  * Copyright (c) 2007, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Red Hat, Inc. - fragment support
14  *******************************************************************************/
15 package org.eclipse.equinox.p2.tests.simpleconfigurator;
16 
17 import java.io.*;
18 import java.net.MalformedURLException;
19 import java.net.URL;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.jar.JarFile;
23 import java.util.jar.Manifest;
24 import org.eclipse.core.runtime.FileLocator;
25 import org.eclipse.core.runtime.Platform;
26 import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
27 import org.eclipse.equinox.p2.tests.TestActivator;
28 import org.eclipse.equinox.p2.tests.embeddedequinox.EmbeddedEquinox;
29 import org.osgi.framework.*;
30 
31 public abstract class AbstractSimpleConfiguratorTest extends AbstractProvisioningTest {
32 	static String BUNDLE_JAR_DIRECTORY = "simpleConfiguratorTest/bundlesTxt2";
33 	private EmbeddedEquinox equinox = null;
34 
35 	@Override
setUp()36 	protected void setUp() throws Exception {
37 		super.setUp();
38 	}
39 
40 	@Override
tearDown()41 	protected void tearDown() throws Exception {
42 		super.tearDown();
43 		if (equinox != null)
44 			equinox.shutdown();
45 	}
46 
47 	//Assert that all files are in the bundles
assertJarsInstalled(File[] jars, Bundle[] bundles)48 	protected void assertJarsInstalled(File[] jars, Bundle[] bundles) {
49 		for (File jar : jars) {
50 			boolean found = false;
51 			String jarName = getManifestEntry(jar, Constants.BUNDLE_SYMBOLICNAME);
52 			for (Bundle bundle : bundles) {
53 				String bundleName = bundle.getSymbolicName();
54 				if (bundleName.equalsIgnoreCase(jarName))
55 					found = true;
56 			}
57 			if (!found)
58 				fail("Bundle should be present:  " + jarName);
59 		}
60 	}
61 
getLocation(String bundleId)62 	private File getLocation(String bundleId) {
63 		try {
64 			URL u = FileLocator.resolve(Platform.getBundle(bundleId).getEntry(""));
65 			String urlString = u.toExternalForm();
66 			if (urlString.startsWith("file:")) {
67 				return new File(urlString.substring(5));
68 			}
69 			if (urlString.startsWith("jar:")) {
70 				return new File(urlString.substring(9, urlString.length() - 2));
71 			}
72 			return null;
73 		} catch (IOException e) {
74 			return null;
75 		}
76 	}
77 
78 	@SuppressWarnings("deprecation")
startFramework(File bundleInfo, File[] additionalBundle)79 	protected BundleContext startFramework(File bundleInfo, File[] additionalBundle) {
80 		try {
81 			File simpleConfiguratorBundle = getLocation("org.eclipse.equinox.simpleconfigurator");
82 			File osgiBundleLoc = getLocation("org.eclipse.osgi");
83 
84 			// for test purposes create an install.area and configuration.area located in the local bundle data area.
85 			File installarea = TestActivator.context.getDataFile(getName() + "/" + System.currentTimeMillis() + "/eclipse");
86 			File configarea = new File(installarea, "configuration");
87 			URL osgiBundle = osgiBundleLoc.toURI().toURL();
88 			//if we have framework in workspace need to add the bin directory
89 			URL osgiBundleDevPath = null;
90 			if (!osgiBundle.getPath().endsWith(".jar")) {
91 				osgiBundleDevPath = new URL(osgiBundle, "bin/");
92 			}
93 
94 			Map<String, String> frameworkProperties = new HashMap<>();
95 			// note that any properties you do not want to be inherited from the hosting Equinox will need
96 			// to be nulled out.  Otherwise you will pick them up from the hosting env.
97 			frameworkProperties.put("osgi.framework", null);
98 			frameworkProperties.put("osgi.install.area", installarea.toURL().toExternalForm());
99 			frameworkProperties.put("osgi.configuration.area", configarea.toURL().toExternalForm());
100 			StringBuilder osgiBundles = new StringBuilder();
101 			for (int i = 0; additionalBundle != null && i < additionalBundle.length; i++) {
102 				osgiBundles.append("reference:").append(additionalBundle[i].toURL().toExternalForm()).append(",");
103 			}
104 			osgiBundles.append("reference:").append(simpleConfiguratorBundle.toURL().toExternalForm()).append("@1:start");
105 			frameworkProperties.put("osgi.bundles", osgiBundles.toString());
106 
107 			frameworkProperties.put("org.eclipse.equinox.simpleconfigurator.configUrl", bundleInfo.toURL().toExternalForm());
108 			frameworkProperties.put("osgi.dev", "bin/");
109 
110 			URL[] osgiPath = osgiBundleDevPath == null ? new URL[] {osgiBundle} : new URL[] {osgiBundle, osgiBundleDevPath};
111 			equinox = new EmbeddedEquinox(frameworkProperties, new String[] {}, osgiPath);
112 			return equinox.startFramework();
113 		} catch (MalformedURLException e) {
114 			return null;
115 		}
116 	}
117 
118 	//Create a bundles.info with all the jars listed plus OSGi and SimpleConfigurator
createBundlesTxt(File[] jars)119 	protected File createBundlesTxt(File[] jars) throws IOException {
120 		File bundlesTxt = File.createTempFile("bundles", ".txt");
121 		bundlesTxt.deleteOnExit();
122 
123 		try (BufferedWriter bundlesTxtOut = new BufferedWriter(new FileWriter(bundlesTxt))) {
124 
125 			for (File bundleJar : jars) {
126 				bundlesTxtOut.write(getBundlesTxtEntry(bundleJar) + "\n");
127 			}
128 			bundlesTxtOut.write(getBundlesTxtEntry(getLocation("org.eclipse.equinox.simpleconfigurator")) + "\n");
129 			bundlesTxtOut.write(getBundlesTxtEntry(getLocation("org.eclipse.osgi")) + "\n");
130 
131 		}
132 
133 		return bundlesTxt;
134 	}
135 
getBundlesTxtEntry(File bundleJar)136 	private String getBundlesTxtEntry(File bundleJar) {
137 		String name = getManifestEntry(bundleJar, Constants.BUNDLE_SYMBOLICNAME);
138 		String version = getManifestEntry(bundleJar, Constants.BUNDLE_VERSION);
139 		// <name>,<version>,file:<file>,<startlevel>,true
140 		return name + "," + version + "," + bundleJar.toURI() + "," + getStartLevel(name) + ",true";
141 	}
142 
getManifestEntry(File bundleFile, String entry)143 	private String getManifestEntry(File bundleFile, String entry) {
144 		try {
145 			String value = null;
146 			if (bundleFile.isDirectory()) {
147 				File m = new File(bundleFile, "META-INF/MANIFEST.MF");
148 				try (InputStream os = new FileInputStream(m)) {
149 					Manifest mf;
150 					mf = new Manifest(os);
151 					value = mf.getMainAttributes().getValue(entry);
152 				}
153 			} else {
154 				try (JarFile bundleJar = new JarFile(bundleFile)) {
155 					value = bundleJar.getManifest().getMainAttributes().getValue(entry);
156 				}
157 			}
158 			if (value.contains(";")) {
159 				String[] valueElements = value.split(";");
160 				return valueElements[0];
161 			}
162 			return value;
163 		} catch (IOException e) {
164 			return null;
165 		}
166 	}
167 
getStartLevel(String bundleName)168 	private int getStartLevel(String bundleName) {
169 		int startLevel = 4;
170 		// some special case start levels
171 		if (bundleName.matches("org.eclipse.osgi")) {
172 			startLevel = -1;
173 		} else if (bundleName.matches("org.eclipse.equinox.common")) {
174 			startLevel = 2;
175 		} else if (bundleName.matches("org.eclipse.equinox.simpleconfigurator")) {
176 			startLevel = 1;
177 		}
178 		return startLevel;
179 	}
180 
getBundleJars(File directory)181 	protected File[] getBundleJars(File directory) {
182 		FilenameFilter bundleFilter = (directoryName, filename) -> !filename.startsWith(".") && !filename.equals("CVS");
183 		return directory.listFiles(bundleFilter);
184 	}
185 }
186