1 /*******************************************************************************
2  * Copyright (c) 2006, 2014 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  *     Raymond Augé <raymond.auge@liferay.com> - Bug 436698
14  *******************************************************************************/
15 package org.eclipse.equinox.http.servlet.tests.bundle;
16 
17 import java.io.IOException;
18 import java.net.URL;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Map;
22 
23 import org.eclipse.osgi.service.urlconversion.URLConverter;
24 import org.osgi.framework.Bundle;
25 import org.osgi.framework.BundleContext;
26 import org.osgi.framework.BundleException;
27 import org.osgi.framework.InvalidSyntaxException;
28 import org.osgi.util.tracker.ServiceTracker;
29 
30 public class BundleInstaller {
31 	private BundleContext context;
32 	private String rootLocation;
33 	private HashMap<String, Bundle> bundles = new HashMap<>();
34 	private ServiceTracker<Object, Object> converter;
35 
BundleInstaller(String bundlesRoot, BundleContext context)36 	public BundleInstaller(String bundlesRoot, BundleContext context) throws InvalidSyntaxException {
37 		this.context = context;
38 		rootLocation = bundlesRoot;
39 		converter = new ServiceTracker<>(context, context.createFilter("(&(objectClass=" + URLConverter.class.getName() + ")(protocol=bundleentry))"), null);
40 		converter.open();
41 	}
42 
installBundle(String name)43 	synchronized public Bundle installBundle(String name) throws BundleException {
44 		return installBundle(name, true);
45 	}
46 
installBundle(String name, boolean track)47 	synchronized public Bundle installBundle(String name, boolean track) throws BundleException {
48 		if (bundles == null && track) {
49 			return null;
50 		}
51 		String location = getBundleLocation(name);
52 		Bundle bundle = context.installBundle(location);
53 		if (track) {
54 			bundles.put(name, bundle);
55 		}
56 		return bundle;
57 	}
58 
getBundleLocation(String name)59 	public String getBundleLocation(String name) throws BundleException {
60 		String bundleFileName = rootLocation + "/" + name;
61 		URL bundleURL = context.getBundle().getEntry(bundleFileName);
62 		if (bundleURL == null) {
63 			bundleURL = context.getBundle().getEntry(bundleFileName + ".jar");
64 		}
65 		if (bundleURL == null) {
66 			throw new BundleException("Could not find bundle to install at: " + name);
67 		}
68 		try {
69 			bundleURL = ((URLConverter) converter.getService()).resolve(bundleURL);
70 		} catch (IOException e) {
71 			throw new BundleException("Converter error", e);
72 		}
73 		String location = bundleURL.toExternalForm();
74 		if ("file".equals(bundleURL.getProtocol())) {
75 			location = "reference:" + location;
76 		}
77 		return location;
78 	}
79 
updateBundle(String fromName, String toName)80 	synchronized public Bundle updateBundle(String fromName, String toName) throws BundleException {
81 		if (bundles == null) {
82 			return null;
83 		}
84 		Bundle fromBundle = bundles.get(fromName);
85 		if (fromBundle == null) {
86 			throw new BundleException("The bundle to update does not exist!! " + fromName);
87 		}
88 		String bundleFileName = rootLocation + "/" + toName;
89 		URL bundleURL = context.getBundle().getEntry(bundleFileName);
90 		if (bundleURL == null) {
91 			bundleURL = context.getBundle().getEntry(bundleFileName + ".jar");
92 		}
93 		try {
94 			bundleURL = ((URLConverter) converter.getService()).resolve(bundleURL);
95 		} catch (IOException e) {
96 			throw new BundleException("Converter error", e);
97 		}
98 		String location = bundleURL.toExternalForm();
99 		if ("file".equals(bundleURL.getProtocol())) {
100 			location = "reference:" + location;
101 		}
102 		try {
103 			fromBundle.update(new URL(location).openStream());
104 		} catch (Exception e) {
105 			throw new BundleException("Errors when updating bundle " + fromBundle, e);
106 		}
107 		bundles.remove(fromName);
108 		bundles.put(toName, fromBundle);
109 		return fromBundle;
110 	}
111 
uninstallBundle(String name)112 	synchronized public Bundle uninstallBundle(String name) throws BundleException {
113 		if (bundles == null) {
114 			return null;
115 		}
116 		Bundle bundle = bundles.remove(name);
117 		if (bundle == null) {
118 			return null;
119 		}
120 		bundle.uninstall();
121 		return bundle;
122 	}
123 
uninstallBundle(Bundle b)124 	synchronized public void uninstallBundle(Bundle b) throws BundleException {
125 		if (bundles == null) {
126 			return;
127 		}
128 		if (bundles.containsValue(b)) {
129 			for (Map.Entry<String, Bundle> entry : bundles.entrySet()) {
130 				if (entry.getValue().equals(b)) {
131 					bundles.remove(entry.getKey());
132 					break;
133 				}
134 			}
135 		}
136 		b.uninstall();
137 	}
138 
uninstallAllBundles()139 	synchronized public Bundle[] uninstallAllBundles() throws BundleException {
140 		if (bundles == null) {
141 			return null;
142 		}
143 		ArrayList<Bundle> result = new ArrayList<>(bundles.size());
144 		for (Object element : bundles.values()) {
145 			Bundle bundle = (Bundle) element;
146 			try {
147 				bundle.uninstall();
148 			} catch (IllegalStateException e) {
149 				// ignore; bundle probably already uninstalled
150 			}
151 			result.add(bundle);
152 		}
153 		bundles.clear();
154 		return result.toArray(new Bundle[result.size()]);
155 	}
156 
getBundle(String name)157 	synchronized public Bundle getBundle(String name) {
158 		if (bundles == null) {
159 			return null;
160 		}
161 		return bundles.get(name);
162 	}
163 
shutdown()164 	synchronized public Bundle[] shutdown() throws BundleException {
165 		if (bundles == null) {
166 			return null;
167 		}
168 		Bundle[] result = uninstallAllBundles();
169 		converter.close();
170 		bundles = null;
171 		return result;
172 	}
173 }
174