Bug 371654 - [region] Allow preservation of original bundle location 
diff --git a/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/internal/region/StandardRegionDigraphPeristenceTests.java b/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/internal/region/StandardRegionDigraphPeristenceTests.java
index 4c81f36..6a32c75 100644
--- a/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/internal/region/StandardRegionDigraphPeristenceTests.java
+++ b/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/internal/region/StandardRegionDigraphPeristenceTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011 VMware Inc.
+ * Copyright (c) 2011, 2012 VMware Inc.
  * 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
@@ -128,6 +128,11 @@
 			// expected
 		}
 		try {
+			bootCopy.installBundleAtLocation("dynamic.add.b.1", new ByteArrayInputStream(new byte[0]));
+		} catch (BundleException e) {
+			// expected
+		}
+		try {
 			bootCopy.installBundle("dynamic.add.b.2");
 		} catch (BundleException e) {
 			// expected
diff --git a/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/region/tests/system/RegionSystemTests.java b/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/region/tests/system/RegionSystemTests.java
index 1c13b2b..9d6aae4 100644
--- a/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/region/tests/system/RegionSystemTests.java
+++ b/bundles/org.eclipse.equinox.region.tests/src/org/eclipse/equinox/region/tests/system/RegionSystemTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011 IBM Corporation and others.
+ * Copyright (c) 2011, 2012 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
@@ -12,6 +12,7 @@
 
 import java.io.IOException;
 import java.lang.management.ManagementFactory;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.*;
 import javax.management.*;
@@ -618,4 +619,39 @@
 		assertEquals("Wrong region found for the bundle id", pp2Region, digraph.getRegion(TEST_BUNDLE_ID));
 	}
 
+	public void testInstallAtLocation() throws BundleException, MalformedURLException, IOException {
+		// create disconnected test regions
+		Region r1 = digraph.createRegion(getName() + ".1");
+		Region r2 = digraph.createRegion(getName() + ".2");
+
+		String location = bundleInstaller.getBundleLocation(PP1);
+		Bundle b1 = null;
+		Bundle b2 = null;
+		String l1 = null;
+		String l2 = null;
+		try {
+			URL url = new URL(location);
+			b1 = r1.installBundle(location + ".1", url.openStream());
+			l1 = b1.getLocation();
+			b2 = r2.installBundleAtLocation(location + ".2", url.openStream());
+			l2 = b2.getLocation();
+		} finally {
+			if (b1 != null) {
+				try {
+					b1.uninstall();
+				} catch (BundleException e) {
+					// ignore
+				}
+			}
+			if (b2 != null) {
+				try {
+					b2.uninstall();
+				} catch (BundleException e) {
+					// ignore
+				}
+			}
+		}
+		assertEquals("Wrong location found.", location + ".1#" + r1.getName(), l1);
+		assertEquals("Wrong location found.", location + ".2", l2);
+	}
 }
diff --git a/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/internal/region/BundleIdBasedRegion.java b/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/internal/region/BundleIdBasedRegion.java
index 478e9e8..7a5c2d9 100644
--- a/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/internal/region/BundleIdBasedRegion.java
+++ b/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/internal/region/BundleIdBasedRegion.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011 VMware Inc.
+ * Copyright (c) 2011, 2012 VMware Inc.
  * 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
@@ -86,13 +86,28 @@
 	 * {@inheritDoc}
 	 */
 	@Override
+	public Bundle installBundleAtLocation(String location, InputStream input) throws BundleException {
+		return installBundle0(location, input, false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
 	public Bundle installBundle(String location, InputStream input) throws BundleException {
+		return installBundle0(location, input, true);
+	}
+
+	private Bundle installBundle0(String location, InputStream input, boolean appendRegionName) throws BundleException {
 		if (this.bundleContext == null)
 			throw new BundleException("This region is not connected to an OSGi Framework.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
 		setRegionThreadLocal();
 		try {
 			input = checkFileProtocol(location, input);
-			return this.bundleContext.installBundle(location + REGION_LOCATION_DELIMITER + this.regionName, input);
+			if (appendRegionName) {
+				location = location + REGION_LOCATION_DELIMITER + this.regionName;
+			}
+			return this.bundleContext.installBundle(location, input);
 		} finally {
 			removeRegionThreadLocal();
 		}
diff --git a/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/region/Region.java b/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/region/Region.java
index c9d17d6..8974fe8 100644
--- a/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/region/Region.java
+++ b/bundles/org.eclipse.equinox.region/src/org/eclipse/equinox/region/Region.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2011 VMware Inc.
+ * Copyright (c) 2008, 2012 VMware Inc.
  * 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
@@ -94,6 +94,19 @@
 	Bundle installBundle(String location) throws BundleException;
 
 	/**
+	 * Installs a bundle and associates the bundle with this region. The bundle's location 
+	 * will be used as is.  The caller of this method is responsible for ensuring the 
+	 * location is unique across regions.
+	 * 
+	 * @param location the bundle location string
+	 * @param input a stream of the bundle's contents or <code>null</code>
+	 * @return the installed Bundle
+	 * @throws BundleException if the install fails
+	 * @see BundleContext#installBundle(String, InputStream)
+	 */
+	Bundle installBundleAtLocation(String location, InputStream input) throws BundleException;
+
+	/**
 	 * 
 	 * Gets the bundle ids of the bundles associated with this region.
 	 *