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  *******************************************************************************/
14 package org.eclipse.equinox.p2.tests.embeddedequinox;
15 
16 import java.io.IOException;
17 import java.lang.reflect.Method;
18 import java.net.URL;
19 import java.net.URLClassLoader;
20 import java.util.Enumeration;
21 import java.util.Map;
22 import org.osgi.framework.BundleContext;
23 
24 /*
25  * This class assumes the bundle's classloader only has access to org.osgi.framework
26  * from the hosting framework.  Any more access could result in ClassVerifier errors.
27  */
28 public class EmbeddedEquinox {
29 	private final Map<String, String> frameworkProperties;
30 	private final String[] frameworkArgs;
31 	private Class<?> eclipseStarterClazz;
32 	private BundleContext context;
33 	private URL[] frameworkClassPath;
34 
EmbeddedEquinox(Map<String, String> frameworkProperties, String[] frameworkArgs, URL[] frameworkClassPath)35 	public EmbeddedEquinox(Map<String, String> frameworkProperties, String[] frameworkArgs, URL[] frameworkClassPath) {
36 		this.frameworkProperties = frameworkProperties;
37 		this.frameworkArgs = frameworkArgs;
38 		this.frameworkClassPath = frameworkClassPath;
39 	}
40 
startFramework()41 	public BundleContext startFramework() {
42 		System.setProperty("osgi.framework.useSystemProperties", "false");
43 		try {
44 			@SuppressWarnings("resource")
45 			// For some reason when you close the framework loader, tests fail!
46 			URLClassLoader frameworkLoader = new FrameworkClassLoader(frameworkClassPath, this.getClass().getClassLoader());
47 			eclipseStarterClazz = frameworkLoader.loadClass("org.eclipse.core.runtime.adaptor.EclipseStarter");
48 
49 			Method setInitialProperties = eclipseStarterClazz.getMethod("setInitialProperties", Map.class); //$NON-NLS-1$
50 			setInitialProperties.invoke(null, frameworkProperties);
51 
52 			Method runMethod = eclipseStarterClazz.getMethod("startup", String[].class, Runnable.class); //$NON-NLS-1$
53 			context = (BundleContext) runMethod.invoke(null, frameworkArgs, null);
54 		} catch (Throwable t) {
55 			if (t instanceof RuntimeException)
56 				throw (RuntimeException) t;
57 			throw new RuntimeException(t);
58 		}
59 		return context;
60 	}
61 
shutdown()62 	public void shutdown() {
63 		try {
64 			Method shutdownMethod = eclipseStarterClazz.getMethod("shutdown"); //$NON-NLS-1$
65 			shutdownMethod.invoke((Object[]) null);
66 
67 		} catch (Throwable t) {
68 			if (t instanceof RuntimeException)
69 				throw (RuntimeException) t;
70 			throw new RuntimeException(t);
71 		}
72 	}
73 
74 	public class FrameworkClassLoader extends URLClassLoader {
75 		ClassLoader embeddedBundleLoader;
76 
FrameworkClassLoader(URL[] urls, ClassLoader parent)77 		public FrameworkClassLoader(URL[] urls, ClassLoader parent) {
78 			super(urls, null);
79 			this.embeddedBundleLoader = parent;
80 		}
81 
82 		@Override
findClass(String name)83 		protected Class<?> findClass(String name) throws ClassNotFoundException {
84 			if (name.startsWith("org.osgi.framework.") || name.startsWith("org.osgi.resource."))
85 				// TODO this should call findClass; but then have to use reflection!!
86 				return embeddedBundleLoader.loadClass(name);
87 			return super.findClass(name);
88 		}
89 
90 		@Override
findResource(String name)91 		public URL findResource(String name) {
92 			if (name.startsWith("org/osgi/framework/") || name.startsWith("org/osgi/resource/"))
93 				// TODO this should call findResource; but then have to use reflection!!
94 				return embeddedBundleLoader.getResource(name);
95 			return super.findResource(name);
96 		}
97 
98 		@Override
findResources(String name)99 		public Enumeration<URL> findResources(String name) throws IOException {
100 			if (name.startsWith("org/osgi/framework/") || name.startsWith("org/osgi/resource/"))
101 				// TODO this should call findResources; but then have to use reflection!!
102 				return embeddedBundleLoader.getResources(name);
103 			return super.findResources(name);
104 		}
105 
106 	}
107 }
108