summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rapicault (JBoss)2013-04-08 21:57:49 (EDT)
committerPascal Rapicault2013-04-09 16:51:14 (EDT)
commit11c1ab663154efe0e0be72945607a9fe45ffc679 (patch)
tree38545ac956026af780414c4f558885b90388ed74
parentff2e9c3c5f2ee4cbd1ea736b73c59097e1365045 (diff)
downloadrt.equinox.p2-11c1ab663154efe0e0be72945607a9fe45ffc679.zip
rt.equinox.p2-11c1ab663154efe0e0be72945607a9fe45ffc679.tar.gz
rt.equinox.p2-11c1ab663154efe0e0be72945607a9fe45ffc679.tar.bz2
Add support for product and shared install
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java7
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java25
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java38
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java117
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java92
7 files changed, 279 insertions, 5 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
index 12a45a2..fe74176 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
@@ -62,6 +62,13 @@ public final class MetadataFactory {
*/
public static final String PROP_TYPE_CATEGORY = "org.eclipse.equinox.p2.type.category"; //$NON-NLS-1$
+ /**
+ * A property key (value <code>"org.eclipse.equinox.p2.type.product"</code>) for a
+ * boolean property indicating that an installable unit is the root IU of a product.
+ *
+ */
+ public static final String PROP_TYPE_PRODUCT = "org.eclipse.equinox.p2.type.product"; //$NON-NLS-1$
+
public InstallableUnitDescription() {
super();
}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java
index 5b4c54c..44f7c99 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java
@@ -13,8 +13,7 @@ package org.eclipse.equinox.p2.query;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
-import org.eclipse.equinox.internal.p2.metadata.expression.ContextExpression;
-import org.eclipse.equinox.internal.p2.metadata.expression.ExpressionFactory;
+import org.eclipse.equinox.internal.p2.metadata.expression.*;
import org.eclipse.equinox.internal.p2.metadata.expression.Expression.VariableFinder;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.*;
@@ -35,6 +34,8 @@ public class QueryUtil {
public static final String PROP_TYPE_GROUP = "org.eclipse.equinox.p2.type.group"; //$NON-NLS-1$
+ public static final String PROP_TYPE_PRODUCT = "org.eclipse.equinox.p2.type.product"; //$NON-NLS-1$
+
public static final String PROP_TYPE_PATCH = "org.eclipse.equinox.p2.type.patch"; //$NON-NLS-1$
private static final IExpression matchesRequirementsExpression = ExpressionUtil.parse("$0.exists(r | this ~= r)"); //$NON-NLS-1$
@@ -210,6 +211,14 @@ public class QueryUtil {
}
/**
+ * Creates an {@link IInstallableUnit} that will match all products.
+ * @return The created query
+ */
+ public static IQuery<IInstallableUnit> createIUProductQuery() {
+ return createIUPropertyQuery(QueryUtil.PROP_TYPE_PRODUCT, Boolean.TRUE.toString());
+ }
+
+ /**
* Creates a query that searches for {@link IInstallableUnit} instances that have
* a property whose value matches the provided value. If no property name is
* specified, then all {@link IInstallableUnit} instances are accepted.
@@ -498,6 +507,18 @@ public class QueryUtil {
}
/**
+ * Test if the {@link IInstallableUnit} is a product.
+ * @param iu the element being tested.
+ * @return <tt>true</tt> if the parameter is a group.
+ */
+ public static boolean isProduct(IInstallableUnit iu) {
+ String value = iu.getProperty(PROP_TYPE_PRODUCT);
+ if (value != null && (value.equals(Boolean.TRUE.toString())))
+ return true;
+ return false;
+ }
+
+ /**
* Test if the {@link IInstallableUnit} is a patch.
* @param iu the element being tested.
* @return <tt>true</tt> if the parameter is a patch.
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
index 25b7648..fc03057 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
@@ -17,6 +17,7 @@ import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
+import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
@@ -35,6 +36,10 @@ public class RequestFlexer {
private boolean allowInstalledRemoval = false;
private boolean allowDifferentVersion = false;
private boolean allowPartialInstall = false;
+
+ private boolean ensureProductPresence = true;
+ private boolean honorSharedSettings = true;
+
private ProvisioningContext provisioningContext;
Set<IRequirement> requirementsForElementsBeingInstalled = new HashSet<IRequirement>();
@@ -72,6 +77,10 @@ public class RequestFlexer {
provisioningContext = context;
}
+ public void setEnsureProduct(boolean productPresent) {
+ ensureProductPresence = productPresent;
+ }
+
public IProfileChangeRequest getChangeRequest(IProfileChangeRequest request, IProfile prof, IProgressMonitor monitor) {
this.profile = prof;
IProfileChangeRequest loosenedRequest = computeLooseRequest(request);
@@ -84,6 +93,9 @@ public class RequestFlexer {
if (intermediaryPlan.getAdditions().query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).isEmpty() && intermediaryPlan.getRemovals().query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).isEmpty())
//No changes, we can't return anything
return null;
+ if (!productContainmentOK(intermediaryPlan)) {
+ return null;
+ }
IProfileChangeRequest effectiveRequest = computeEffectiveChangeRequest(intermediaryPlan, loosenedRequest, request);
if (effectiveRequest.getAdditions().isEmpty() && effectiveRequest.getRemovals().isEmpty())
return null;
@@ -92,7 +104,7 @@ public class RequestFlexer {
private boolean canShortCircuit(IProfileChangeRequest originalRequest) {
//Case where the user is asking to install only some of the requested IUs but there is only one IU to install.
- if (allowPartialInstall)
+ if (allowPartialInstall && !allowInstalledUpdate && !allowDifferentVersion && !allowInstalledRemoval)
if (originalRequest.getAdditions().size() == 1 && originalRequest.getRemovals().isEmpty())
return true;
@@ -300,7 +312,7 @@ public class RequestFlexer {
//Loosen up the IUs that are already part of the profile
//Given how we are creating our request, this needs to take into account the removal from the original request as well as the change in inclusion
private IProfileChangeRequest loosenUpInstalledSoftware(IProfileChangeRequest request, IProfileChangeRequest originalRequest) {
- IQueryResult<IInstallableUnit> allRoots = profile.query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null);
+ Set<IInstallableUnit> allRoots = getRoots();
for (IInstallableUnit existingIU : allRoots) {
Collection<IInstallableUnit> potentialUpdates = allowInstalledUpdate ? findUpdates(existingIU) : new HashSet<IInstallableUnit>();
@@ -319,6 +331,15 @@ public class RequestFlexer {
return request;
}
+ private Set<IInstallableUnit> getRoots() {
+ Set<IInstallableUnit> allRoots = profile.query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null).toSet();
+ if (!honorSharedSettings)
+ return allRoots;
+ IQueryResult<IInstallableUnit> baseRoots = profile.query(new IUProfilePropertyQuery("org.eclipse.equinox.p2.base", Boolean.TRUE.toString()), null);
+ allRoots.removeAll(baseRoots.toUnmodifiableSet());
+ return allRoots;
+ }
+
//This return whether or not the given IU is installed optionally or not.
//This also take into account the future state
private boolean isOptionallyInstalled(IInstallableUnit existingIU, IProfileChangeRequest request) {
@@ -353,6 +374,19 @@ public class RequestFlexer {
}
}
return futureOptionalIUs;
+ }
+ private boolean productContainmentOK(IProvisioningPlan intermediaryPlan) {
+ if (!ensureProductPresence)
+ return true;
+ if (!hasProduct())
+ return true;
+ //At this point we know we had a product installed and we want to make sure there is one in the resulting solution
+ return !intermediaryPlan.getFutureState().query(QueryUtil.createIUProductQuery(), new NullProgressMonitor()).isEmpty();
}
+
+ private boolean hasProduct() {
+ return !profile.available(new UserVisibleRootQuery(), new NullProgressMonitor()).query(QueryUtil.createIUPropertyQuery(QueryUtil.PROP_TYPE_PRODUCT, Boolean.TRUE.toString()), new NullProgressMonitor()).isEmpty();
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java
index 4c87ddc..5f02f79 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java
@@ -157,7 +157,7 @@ public class RootIUAction extends AbstractPublisherAction {
root.setRequirements(requiredCapabilities.toArray(new IRequirement[requiredCapabilities.size()]));
root.setArtifacts(new IArtifactKey[0]);
- root.setProperty("lineUp", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ root.setProperty(InstallableUnitDescription.PROP_TYPE_PRODUCT, Boolean.TRUE.toString());
root.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(id, VersionRange.emptyRange, IUpdateDescriptor.NORMAL, null));
root.setProperty(InstallableUnitDescription.PROP_TYPE_GROUP, Boolean.TRUE.toString());
root.setCapabilities(new IProvidedCapability[] {createSelfCapability(id, version)});
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
index cf742e7..b3c3175 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
@@ -20,8 +20,11 @@ public class AllAnyVersionTests extends TestCase {
suite.addTestSuite(TestRequestFlexerOneInstalledOneBeingInstalled.class);
suite.addTestSuite(TestRequestFlexerOneInstalledReplacingIt.class);
suite.addTestSuite(TestRequestFlexerOneInstalledTwoBeingInstalled.class);
+ // suite.addTestSuite(TestRequestFlexerProduct.class);
suite.addTestSuite(TestRequestFlexerRequestWithOptionalInstall.class);
suite.addTestSuite(TestRequestFlexerRequestWithRemoval.class);
+ suite.addTestSuite(TestRequestFlexerSharedInstall.class);
return suite;
+
}
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java
new file mode 100644
index 0000000..a1ab360
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc. 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import java.util.Properties;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerProduct extends AbstractProvisioningTest {
+ public IInstallableUnit sdk1;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit platform1;
+
+ public IInstallableUnit sdk2;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit platform2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: svn1 \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit svn1;
+
+ @IUDescription(content = "package: svn2 \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit svn2;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private IProfileChangeRequest originalRequest;
+
+ private ProvisioningContext context;
+
+ private void setupSDK1() {
+ IRequirement[] reqPlatform1 = new IRequirement[1];
+ reqPlatform1[0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "platform", new VersionRange("[1.0.0,1.0.0]"), null, true, false, true);
+ sdk1 = createIU("SDK", Version.create("1.0.0"), null, reqPlatform1, new IProvidedCapability[0], new Properties(), null, null, true);
+ }
+
+ private void setupSDK2() {
+ IRequirement[] reqPlatform1 = new IRequirement[1];
+ reqPlatform1[0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "platform", new VersionRange("[2.0.0,2.0.0]"), null, true, false, true);
+ sdk2 = createIU("SDK", Version.create("2.0.0"), null, reqPlatform1, new IProvidedCapability[0], new Properties(), null, null, true);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ setupSDK1();
+ setupSDK2();
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+
+ originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ public void testProductRemovalIsDetected() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(false);
+ av.setAllowDifferentVersion(false);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(false);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+
+ //There is no solution because with the given criteria, it would remove the product
+ assertNull(realRequest);
+ }
+
+ public void testProductNewProduct() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(false);
+ av.setAllowDifferentVersion(false);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+
+ //In this case we can update the base, so we will find sdk2
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java
new file mode 100644
index 0000000..11a715b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc. 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerSharedInstall extends AbstractProvisioningTest {
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit sdk1;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit platform1;
+
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit sdk2;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit platform2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: svn1 \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit svn1;
+
+ @IUDescription(content = "package: svn2 \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit svn2;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private IProfileChangeRequest originalRequest;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(installAsRootsAndFlaggedAsBase(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+
+ originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ public void testBaseBlocked() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(false);
+ av.setAllowDifferentVersion(false);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+
+ //Even though we allow for the base to change (removal and change), there is no solution because it is a shared install
+ //and thus the roots from the base are immutable
+ assertNull(realRequest);
+ }
+
+}