Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 348967
Collapse All | Expand All

(-).settings/.api_filters (+7 lines)
Lines 890-895 Link Here
890
</message_arguments>
890
</message_arguments>
891
</filter>
891
</filter>
892
</resource>
892
</resource>
893
<resource path="osgi/src/org/osgi/framework/hooks/bundle/CollisionHook.java" type="org.osgi.framework.hooks.bundle.CollisionHook">
894
<filter comment="Ignore OSGi API" id="1110441988">
895
<message_arguments>
896
<message_argument value="org.osgi.framework.hooks.bundle.CollisionHook"/>
897
</message_arguments>
898
</filter>
899
</resource>
893
<resource path="osgi/src/org/osgi/framework/hooks/bundle/EventHook.java" type="org.osgi.framework.hooks.bundle.EventHook">
900
<resource path="osgi/src/org/osgi/framework/hooks/bundle/EventHook.java" type="org.osgi.framework.hooks.bundle.EventHook">
894
<filter comment="Ingore OSGi API." id="1110441988">
901
<filter comment="Ingore OSGi API." id="1110441988">
895
<message_arguments>
902
<message_arguments>
(-)core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java (-1 / +3 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.osgi.framework.internal.core;
11
package org.eclipse.osgi.framework.internal.core;
12
12
13
import org.osgi.framework.hooks.bundle.CollisionHook;
14
13
import java.io.*;
15
import java.io.*;
14
import java.net.URL;
16
import java.net.URL;
15
import java.net.URLConnection;
17
import java.net.URLConnection;
Lines 660-666 Link Here
660
		try {
662
		try {
661
			BundleData newBundleData = storage.begin();
663
			BundleData newBundleData = storage.begin();
662
			// Must call framework createBundle to check execution environment.
664
			// Must call framework createBundle to check execution environment.
663
			final AbstractBundle newBundle = framework.createAndVerifyBundle(newBundleData, false);
665
			final AbstractBundle newBundle = framework.createAndVerifyBundle(CollisionHook.UPDATING, this, newBundleData, false);
664
			boolean exporting;
666
			boolean exporting;
665
			int st = getState();
667
			int st = getState();
666
			synchronized (bundles) {
668
			synchronized (bundles) {
(-)core/framework/org/eclipse/osgi/framework/internal/core/BundleRepository.java (-3 / +7 lines)
Lines 68-85 Link Here
68
		return bundlesBySymbolicName.get(symbolicName);
68
		return bundlesBySymbolicName.get(symbolicName);
69
	}
69
	}
70
70
71
	public synchronized AbstractBundle getBundle(String symbolicName, Version version) {
71
	@SuppressWarnings("unchecked")
72
	public synchronized List<AbstractBundle> getBundles(String symbolicName, Version version) {
72
		AbstractBundle[] bundles = getBundles(symbolicName);
73
		AbstractBundle[] bundles = getBundles(symbolicName);
74
		List<AbstractBundle> result = null;
73
		if (bundles != null) {
75
		if (bundles != null) {
74
			if (bundles.length > 0) {
76
			if (bundles.length > 0) {
75
				for (int i = 0; i < bundles.length; i++) {
77
				for (int i = 0; i < bundles.length; i++) {
76
					if (bundles[i].getVersion().equals(version)) {
78
					if (bundles[i].getVersion().equals(version)) {
77
						return bundles[i];
79
						if (result == null)
80
							result = new ArrayList<AbstractBundle>();
81
						result.add(bundles[i]);
78
					}
82
					}
79
				}
83
				}
80
			}
84
			}
81
		}
85
		}
82
		return null;
86
		return result == null ? Collections.EMPTY_LIST : result;
83
	}
87
	}
84
88
85
	public synchronized void add(AbstractBundle bundle) {
89
	public synchronized void add(AbstractBundle bundle) {
(-)core/framework/org/eclipse/osgi/framework/internal/core/Framework.java (-36 / +82 lines)
Lines 33-40 Link Here
33
import org.eclipse.osgi.util.ManifestElement;
33
import org.eclipse.osgi.util.ManifestElement;
34
import org.eclipse.osgi.util.NLS;
34
import org.eclipse.osgi.util.NLS;
35
import org.osgi.framework.*;
35
import org.osgi.framework.*;
36
import org.osgi.framework.hooks.bundle.EventHook;
36
import org.osgi.framework.hooks.bundle.*;
37
import org.osgi.framework.hooks.bundle.FindHook;
38
import org.osgi.util.tracker.ServiceTracker;
37
import org.osgi.util.tracker.ServiceTracker;
39
38
40
/**
39
/**
Lines 77-82 Link Here
77
	protected StartLevelManager startLevelManager;
76
	protected StartLevelManager startLevelManager;
78
	/** The ServiceRegistry */
77
	/** The ServiceRegistry */
79
	private ServiceRegistry serviceRegistry;
78
	private ServiceRegistry serviceRegistry;
79
	private final int BSN_VERSION;
80
	private static final int BSN_VERSION_SINGLE = 1;
81
	private static final int BSN_VERSION_MULTIPLE = 2;
82
	private static final int BSN_VERSION_MANAGED = 3;
80
83
81
	/*
84
	/*
82
	 * The following maps objects keep track of event listeners
85
	 * The following maps objects keep track of event listeners
Lines 99-104 Link Here
99
	protected static final int BATCHEVENT_END = Integer.MIN_VALUE;
102
	protected static final int BATCHEVENT_END = Integer.MIN_VALUE;
100
	static final String eventHookName = EventHook.class.getName();
103
	static final String eventHookName = EventHook.class.getName();
101
	static final String findHookName = FindHook.class.getName();
104
	static final String findHookName = FindHook.class.getName();
105
	static final String collisionHookName = CollisionHook.class.getName();
102
	/** EventManager for event delivery. */
106
	/** EventManager for event delivery. */
103
	protected EventManager eventManager;
107
	protected EventManager eventManager;
104
	/* Reservation object for install synchronization */
108
	/* Reservation object for install synchronization */
Lines 110-116 Link Here
110
	private boolean bootDelegateAll = false;
114
	private boolean bootDelegateAll = false;
111
	public final boolean contextBootDelegation = "true".equals(FrameworkProperties.getProperty("osgi.context.bootdelegation", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
115
	public final boolean contextBootDelegation = "true".equals(FrameworkProperties.getProperty("osgi.context.bootdelegation", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
112
	public final boolean compatibiltyBootDelegation = "true".equals(FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
116
	public final boolean compatibiltyBootDelegation = "true".equals(FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
113
	private final boolean allowDuplicateBSNVersion = Constants.FRAMEWORK_BSNVERSION_MULTIPLE.equals(FrameworkProperties.getProperty(Constants.FRAMEWORK_BSNVERSION));
114
	ClassLoaderDelegateHook[] delegateHooks;
117
	ClassLoaderDelegateHook[] delegateHooks;
115
	private volatile boolean forcedRestart = false;
118
	private volatile boolean forcedRestart = false;
116
	/**
119
	/**
Lines 158-177 Link Here
158
	 *  
161
	 *  
159
	 */
162
	 */
160
	public Framework(FrameworkAdaptor adaptor) {
163
	public Framework(FrameworkAdaptor adaptor) {
161
		initialize(adaptor);
162
	}
163
164
	/**
165
	 * Initialize the framework to an unlaunched state. This method is called
166
	 * by the Framework constructor.
167
	 *  
168
	 */
169
	protected void initialize(FrameworkAdaptor initAdaptor) {
170
		if (Profile.PROFILE && Profile.STARTUP)
164
		if (Profile.PROFILE && Profile.STARTUP)
171
			Profile.logEnter("Framework.initialze()", null); //$NON-NLS-1$
165
			Profile.logEnter("Framework.initialze()", null); //$NON-NLS-1$
166
		String bsnVersion = FrameworkProperties.getProperty(Constants.FRAMEWORK_BSNVERSION);
167
		if (Constants.FRAMEWORK_BSNVERSION_SINGLE.equals(bsnVersion)) {
168
			BSN_VERSION = BSN_VERSION_SINGLE;
169
		} else if (Constants.FRAMEWORK_BSNVERSION_MULTIPLE.equals(bsnVersion)) {
170
			BSN_VERSION = BSN_VERSION_MULTIPLE;
171
		} else {
172
			BSN_VERSION = BSN_VERSION_MANAGED;
173
		}
172
		long start = System.currentTimeMillis();
174
		long start = System.currentTimeMillis();
173
		this.adaptor = initAdaptor;
175
		this.adaptor = adaptor;
174
		delegateHooks = initAdaptor instanceof BaseAdaptor ? ((BaseAdaptor) initAdaptor).getHookRegistry().getClassLoaderDelegateHooks() : null;
176
		delegateHooks = adaptor instanceof BaseAdaptor ? ((BaseAdaptor) adaptor).getHookRegistry().getClassLoaderDelegateHooks() : null;
175
		active = false;
177
		active = false;
176
		installSecurityManager();
178
		installSecurityManager();
177
		if (Debug.DEBUG_SECURITY) {
179
		if (Debug.DEBUG_SECURITY) {
Lines 182-192 Link Here
182
		// initialize ContextFinder
184
		// initialize ContextFinder
183
		initializeContextFinder();
185
		initializeContextFinder();
184
		/* initialize the adaptor */
186
		/* initialize the adaptor */
185
		initAdaptor.initialize(this);
187
		adaptor.initialize(this);
186
		if (Profile.PROFILE && Profile.STARTUP)
188
		if (Profile.PROFILE && Profile.STARTUP)
187
			Profile.logTime("Framework.initialze()", "adapter initialized"); //$NON-NLS-1$//$NON-NLS-2$
189
			Profile.logTime("Framework.initialze()", "adapter initialized"); //$NON-NLS-1$//$NON-NLS-2$
188
		try {
190
		try {
189
			initAdaptor.initializeStorage();
191
			adaptor.initializeStorage();
190
		} catch (IOException e) /* fatal error */{
192
		} catch (IOException e) /* fatal error */{
191
			throw new RuntimeException(e.getMessage(), e);
193
			throw new RuntimeException(e.getMessage(), e);
192
		}
194
		}
Lines 196-207 Link Here
196
		 * This must be done before calling any of the framework getProperty
198
		 * This must be done before calling any of the framework getProperty
197
		 * methods.
199
		 * methods.
198
		 */
200
		 */
199
		initializeProperties(initAdaptor.getProperties());
201
		initializeProperties(adaptor.getProperties());
200
		/* initialize admin objects */
202
		/* initialize admin objects */
201
		packageAdmin = new PackageAdminImpl(this);
203
		packageAdmin = new PackageAdminImpl(this);
202
		try {
204
		try {
203
			// always create security admin even with security off
205
			// always create security admin even with security off
204
			securityAdmin = new SecurityAdmin(null, this, initAdaptor.getPermissionStorage());
206
			securityAdmin = new SecurityAdmin(null, this, adaptor.getPermissionStorage());
205
		} catch (IOException e) /* fatal error */{
207
		} catch (IOException e) /* fatal error */{
206
			e.printStackTrace();
208
			e.printStackTrace();
207
			throw new RuntimeException(e.getMessage(), e);
209
			throw new RuntimeException(e.getMessage(), e);
Lines 226-238 Link Here
226
		if (Profile.PROFILE && Profile.STARTUP)
228
		if (Profile.PROFILE && Profile.STARTUP)
227
			Profile.logTime("Framework.initialze()", "done createSystemBundle"); //$NON-NLS-1$ //$NON-NLS-2$
229
			Profile.logTime("Framework.initialze()", "done createSystemBundle"); //$NON-NLS-1$ //$NON-NLS-2$
228
		/* install URLStreamHandlerFactory */
230
		/* install URLStreamHandlerFactory */
229
		installURLStreamHandlerFactory(systemBundle.context, initAdaptor);
231
		installURLStreamHandlerFactory(systemBundle.context, adaptor);
230
		/* install ContentHandlerFactory for OSGi URLStreamHandler support */
232
		/* install ContentHandlerFactory for OSGi URLStreamHandler support */
231
		installContentHandlerFactory(systemBundle.context, initAdaptor);
233
		installContentHandlerFactory(systemBundle.context, adaptor);
232
		if (Profile.PROFILE && Profile.STARTUP)
234
		if (Profile.PROFILE && Profile.STARTUP)
233
			Profile.logTime("Framework.initialze()", "done new URLStream/Content HandlerFactory"); //$NON-NLS-1$//$NON-NLS-2$
235
			Profile.logTime("Framework.initialze()", "done new URLStream/Content HandlerFactory"); //$NON-NLS-1$//$NON-NLS-2$
234
		/* create bundle objects for all installed bundles. */
236
		/* create bundle objects for all installed bundles. */
235
		BundleData[] bundleDatas = initAdaptor.getInstalledBundles();
237
		BundleData[] bundleDatas = adaptor.getInstalledBundles();
236
		bundles = new BundleRepository(bundleDatas == null ? 10 : bundleDatas.length + 1);
238
		bundles = new BundleRepository(bundleDatas == null ? 10 : bundleDatas.length + 1);
237
		/* add the system bundle to the Bundle Repository */
239
		/* add the system bundle to the Bundle Repository */
238
		bundles.add(systemBundle);
240
		bundles.add(systemBundle);
Lines 702-715 Link Here
702
704
703
	/**
705
	/**
704
	 * Create a new Bundle object.
706
	 * Create a new Bundle object.
705
	 * 
706
	 * @param bundledata the BundleData of the Bundle to create
707
	 * @param bundledata the BundleData of the Bundle to create
707
	 */
708
	 */
708
	AbstractBundle createAndVerifyBundle(BundleData bundledata, boolean setBundle) throws BundleException {
709
	AbstractBundle createAndVerifyBundle(int operationType, Bundle target, BundleData bundledata, boolean setBundle) throws BundleException {
709
		// Check for a bundle already installed with the same symbolic name and version.
710
		// Check for a bundle already installed with the same symbolic name and version.
710
		if (!allowDuplicateBSNVersion && bundledata.getSymbolicName() != null) {
711
		if (BSN_VERSION != BSN_VERSION_MULTIPLE && bundledata.getSymbolicName() != null) {
711
			AbstractBundle installedBundle = getBundleBySymbolicName(bundledata.getSymbolicName(), bundledata.getVersion());
712
			List<AbstractBundle> installedBundles = getBundleBySymbolicName(bundledata.getSymbolicName(), bundledata.getVersion());
712
			if (installedBundle != null && installedBundle.getBundleId() != bundledata.getBundleID()) {
713
			if (operationType == CollisionHook.UPDATING) {
714
				installedBundles.remove(target);
715
			}
716
			if (BSN_VERSION == BSN_VERSION_MANAGED && !installedBundles.isEmpty()) {
717
				notifyCollisionHooks(operationType, target, installedBundles);
718
			}
719
			if (!installedBundles.isEmpty()) {
720
				Bundle installedBundle = installedBundles.iterator().next();
713
				String msg = NLS.bind(Msg.BUNDLE_INSTALL_SAME_UNIQUEID, new Object[] {installedBundle.getSymbolicName(), installedBundle.getVersion().toString(), installedBundle.getLocation()});
721
				String msg = NLS.bind(Msg.BUNDLE_INSTALL_SAME_UNIQUEID, new Object[] {installedBundle.getSymbolicName(), installedBundle.getVersion().toString(), installedBundle.getLocation()});
714
				throw new DuplicateBundleException(msg, installedBundle);
722
				throw new DuplicateBundleException(msg, installedBundle);
715
			}
723
			}
Lines 824-830 Link Here
824
	 *            then the location is used to get the bundle content.
832
	 *            then the location is used to get the bundle content.
825
	 * @return The Bundle of the installed bundle.
833
	 * @return The Bundle of the installed bundle.
826
	 */
834
	 */
827
	AbstractBundle installBundle(final String location, final InputStream in, BundleContext origin) throws BundleException {
835
	AbstractBundle installBundle(final String location, final InputStream in, final BundleContextImpl origin) throws BundleException {
828
		if (Debug.DEBUG_GENERAL) {
836
		if (Debug.DEBUG_GENERAL) {
829
			Debug.println("install from inputstream: " + location + ", " + in); //$NON-NLS-1$ //$NON-NLS-2$
837
			Debug.println("install from inputstream: " + location + ", " + in); //$NON-NLS-1$ //$NON-NLS-2$
830
		}
838
		}
Lines 834-840 Link Here
834
				/* Map the InputStream or location to a URLConnection */
842
				/* Map the InputStream or location to a URLConnection */
835
				URLConnection source = in != null ? new BundleSource(in) : adaptor.mapLocationToURLConnection(location);
843
				URLConnection source = in != null ? new BundleSource(in) : adaptor.mapLocationToURLConnection(location);
836
				/* call the worker to install the bundle */
844
				/* call the worker to install the bundle */
837
				return installWorkerPrivileged(location, source, callerContext);
845
				return installWorkerPrivileged(location, source, callerContext, origin);
838
			}
846
			}
839
		}, origin);
847
		}, origin);
840
	}
848
	}
Lines 918-933 Link Here
918
	 *            The location identifier of the bundle to install.
926
	 *            The location identifier of the bundle to install.
919
	 * @param source
927
	 * @param source
920
	 *            The URLConnection from which the bundle will be read.
928
	 *            The URLConnection from which the bundle will be read.
929
	 * @param callerContext
930
	 *            The caller access control context
931
	 * @param origin 
932
	 *            The origin bundle context that is installing the the bundle
921
	 * @return The {@link AbstractBundle}of the installed bundle.
933
	 * @return The {@link AbstractBundle}of the installed bundle.
922
	 * @exception BundleException
934
	 * @exception BundleException
923
	 *                If the provided stream cannot be read.
935
	 *                If the provided stream cannot be read.
924
	 */
936
	 */
925
	protected AbstractBundle installWorkerPrivileged(String location, URLConnection source, AccessControlContext callerContext) throws BundleException {
937
	protected AbstractBundle installWorkerPrivileged(String location, URLConnection source, AccessControlContext callerContext, BundleContextImpl origin) throws BundleException {
926
		BundleOperation storage = adaptor.installBundle(location, source);
938
		BundleOperation storage = adaptor.installBundle(location, source);
927
		final AbstractBundle bundle;
939
		final AbstractBundle bundle;
928
		try {
940
		try {
929
			BundleData bundledata = storage.begin();
941
			BundleData bundledata = storage.begin();
930
			bundle = createAndVerifyBundle(bundledata, true);
942
			bundle = createAndVerifyBundle(CollisionHook.INSTALLING, origin.getBundle(), bundledata, true);
931
943
932
			BundleWatcher bundleStats = adaptor.getBundleWatcher();
944
			BundleWatcher bundleStats = adaptor.getBundleWatcher();
933
			if (bundleStats != null)
945
			if (bundleStats != null)
Lines 1021-1037 Link Here
1021
	}
1033
	}
1022
1034
1023
	/**
1035
	/**
1024
	 * Retrieve the bundle that has the given symbolic name and version.
1036
	 * Retrieve the bundles that has the given symbolic name and version.
1025
	 * 
1037
	 * 
1026
	 * @param symbolicName
1038
	 * @param symbolicName
1027
	 *            The symbolic name of the bundle to retrieve
1039
	 *            The symbolic name of the bundle to retrieve
1028
	 * @param version The version of the bundle to retrieve
1040
	 * @param version The version of the bundle to retrieve
1029
	 * @return A {@link AbstractBundle}object, or <code>null</code> if the
1041
	 * @return A collection of {@link AbstractBundle} that match the symbolic name and version
1030
	 *         identifier doesn't match any installed bundle.
1031
	 */
1042
	 */
1032
	public AbstractBundle getBundleBySymbolicName(String symbolicName, Version version) {
1043
	public List<AbstractBundle> getBundleBySymbolicName(String symbolicName, Version version) {
1033
		synchronized (bundles) {
1044
		synchronized (bundles) {
1034
			return bundles.getBundle(symbolicName, version);
1045
			return bundles.getBundles(symbolicName, version);
1035
		}
1046
		}
1036
	}
1047
	}
1037
1048
Lines 1112-1117 Link Here
1112
		});
1123
		});
1113
	}
1124
	}
1114
1125
1126
	private void notifyCollisionHooks(final int operationType, final Bundle target, List<AbstractBundle> collisionCandidates) {
1127
		final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(collisionCandidates);
1128
		if (System.getSecurityManager() == null) {
1129
			notifyCollisionHooksPriviledged(operationType, target, shrinkable);
1130
		} else {
1131
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
1132
				public Object run() {
1133
					notifyCollisionHooksPriviledged(operationType, target, shrinkable);
1134
					return null;
1135
				}
1136
			});
1137
		}
1138
	}
1139
1140
	void notifyCollisionHooksPriviledged(final int operationType, final Bundle target, final Collection<Bundle> collisionCandidates) {
1141
		if (Debug.DEBUG_HOOKS) {
1142
			Debug.println("notifyCollisionHooks(" + operationType + ", " + target + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 
1143
		}
1144
		getServiceRegistry().notifyHooksPrivileged(new HookContext() {
1145
			public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
1146
				if (hook instanceof CollisionHook) {
1147
					((CollisionHook) hook).filterCollisions(operationType, target, collisionCandidates);
1148
				}
1149
			}
1150
1151
			public String getHookClassName() {
1152
				return collisionHookName;
1153
			}
1154
1155
			public String getHookMethodName() {
1156
				return "filterCollisions"; //$NON-NLS-1$ 
1157
			}
1158
		});
1159
	}
1160
1115
	/**
1161
	/**
1116
	 * Resume a bundle.
1162
	 * Resume a bundle.
1117
	 * 
1163
	 * 
Lines 1208-1214 Link Here
1208
	 * @param symbolicName
1254
	 * @param symbolicName
1209
	 *            The symbolic name for the bundle
1255
	 *            The symbolic name for the bundle
1210
	 * @return Bundle object for bundle with the specified Unique or null if no
1256
	 * @return Bundle object for bundle with the specified Unique or null if no
1211
	 *         bundle is installed with the specified location.
1257
	 *         bundle is installed with the specified symbolicName.
1212
	 */
1258
	 */
1213
	protected AbstractBundle[] getBundleBySymbolicName(String symbolicName) {
1259
	protected AbstractBundle[] getBundleBySymbolicName(String symbolicName) {
1214
		synchronized (bundles) {
1260
		synchronized (bundles) {
(-)osgi/src/org/osgi/framework/hooks/bundle/CollisionHook.java (+76 lines)
Added Link Here
1
/*
2
 * Copyright (c) OSGi Alliance (2011). All Rights Reserved.
3
 * 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package org.osgi.framework.hooks.bundle;
17
18
import java.util.Collection;
19
import org.osgi.framework.Bundle;
20
import org.osgi.framework.BundleContext;
21
22
/**
23
 * OSGi Framework Bundle Collision Hook Service.
24
 * 
25
 * <p>
26
 * Bundles registering this service will be called during framework bundle 
27
 * install and update operations to determine if an install or update
28
 * operation will result in a bundle symbolic name and version collision.
29
 * 
30
 * @ThreadSafe
31
 * @version $Id: 64a98074fa8331b0cd21989f9c8583b99b2370cf $
32
 */
33
public interface CollisionHook {
34
35
	/**
36
	 * Specifies a bundle install operation is being performed.
37
	 */
38
	public static final int INSTALLING = 0x01;
39
	/**
40
	 * Specifies a bundle update operation is being performed.
41
	 */
42
	public static final int UPDATING = 0x02;
43
44
	/**
45
	 * Filter bundle collisions hook method. This method is called during the
46
	 * install or update operation. The operation type will be 
47
	 * {@link #INSTALLING installing} or 
48
	 * {@link #UPDATING updating}.  Depending on the operation
49
	 * type the target bundle and the collision candidate collection are the following:
50
	 * <ul>
51
	 *   <li> {@link #INSTALLING installing} - The target is the bundle associated with the
52
	 *        {@link BundleContext} used to call one of the 
53
	 *        {@link BundleContext#installBundle(String) install}
54
	 *        methods.  The collision candidate collection contains the existing bundles
55
	 *        installed which have the same symbolic name and version as the bundle being installed.
56
	 *   <li> {@link #UPDATING updating} - The target is the bundle used to call one of the 
57
	 *        {@link Bundle#update() update} methods.  The collision candidate collection
58
	 *        contains the existing bundles installed which have the same symbolic name and version
59
	 *        as the content the target bundle is being updated to.
60
	 * </ul>
61
	 * This method can filter the list of collision candidates by removing
62
	 * potential collisions. Removing a collision candidate will allow the
63
	 * specified operation to succeed as if the collision candidate is not installed.
64
	 * 
65
	 * @param operationType the operation type.  Must be the value of
66
	 * {@link #INSTALLING installing} or {@link #UPDATING updating}.
67
	 * @param target the target bundle used to determine what collision candidates to filter.
68
	 * @param collisionCandidates a collection of collision candidates.
69
	 *            The collection supports all the optional {@code Collection}
70
	 *            operations except {@code add} and {@code addAll}. Attempting
71
	 *            to add to the collection will result in an
72
	 *            {@code UnsupportedOperationException}. The collection is not
73
	 *            synchronized.
74
	 */
75
	void filterCollisions(int operationType, Bundle target, Collection<Bundle> collisionCandidates);
76
}
(-)src/org/eclipse/osgi/tests/bundles/BundleInstallUpdateTests.java (-2 / +52 lines)
Lines 11-23 Link Here
11
package org.eclipse.osgi.tests.bundles;
11
package org.eclipse.osgi.tests.bundles;
12
12
13
import java.io.File;
13
import java.io.File;
14
import java.io.IOException;
15
import java.net.MalformedURLException;
14
import java.net.URL;
16
import java.net.URL;
17
import java.util.Collection;
15
import junit.framework.Test;
18
import junit.framework.Test;
16
import junit.framework.TestSuite;
19
import junit.framework.TestSuite;
17
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
20
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
18
import org.eclipse.osgi.tests.OSGiTestsActivator;
21
import org.eclipse.osgi.tests.OSGiTestsActivator;
19
import org.osgi.framework.Bundle;
22
import org.osgi.framework.*;
20
import org.osgi.framework.BundleException;
23
import org.osgi.framework.hooks.bundle.CollisionHook;
21
24
22
public class BundleInstallUpdateTests extends AbstractBundleTests {
25
public class BundleInstallUpdateTests extends AbstractBundleTests {
23
	public static Test suite() {
26
	public static Test suite() {
Lines 195-198 Link Here
195
			}
198
			}
196
		}
199
		}
197
	}
200
	}
201
202
	public void testCollisionHook() throws BundleException, MalformedURLException, IOException {
203
		Bundle test1 = installer.installBundle("test");
204
		installer.installBundle("test2");
205
		try {
206
			test1.update(new URL(installer.getBundleLocation("test2")).openStream());
207
			fail("Expected to fail to update to another bsn/version that causes collision");
208
		} catch (BundleException e) {
209
			// expected;
210
		}
211
		Bundle junk = null;
212
		try {
213
			junk = OSGiTestsActivator.getContext().installBundle("junk", new URL(installer.getBundleLocation("test2")).openStream());
214
			fail("Expected to fail to install duplication bsn/version that causes collision");
215
		} catch (BundleException e) {
216
			// expected;
217
		} finally {
218
			if (junk != null)
219
				junk.uninstall();
220
			junk = null;
221
		}
222
223
		CollisionHook hook = new CollisionHook() {
224
			public void filterCollisions(int operationType, Bundle target, Collection collisionCandidates) {
225
				collisionCandidates.clear();
226
			}
227
		};
228
		ServiceRegistration reg = OSGiTestsActivator.getContext().registerService(CollisionHook.class, hook, null);
229
		try {
230
			try {
231
				test1.update(new URL(installer.getBundleLocation("test2")).openStream());
232
			} catch (BundleException e) {
233
				fail("Expected to succeed in updating to a duplicate bsn/version", e);
234
			}
235
			try {
236
				junk = OSGiTestsActivator.getContext().installBundle("junk", new URL(installer.getBundleLocation("test2")).openStream());
237
			} catch (BundleException e) {
238
				fail("Expected to succeed to install duplication bsn/version that causes collision", e);
239
			} finally {
240
				if (junk != null)
241
					junk.uninstall();
242
				junk = null;
243
			}
244
		} finally {
245
			reg.unregister();
246
		}
247
	}
198
}
248
}

Return to bug 348967