Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--build-kernel/build.xml1
-rw-r--r--build-kernel/config/org.eclipse.virgo.kernel.userregion.properties37
-rw-r--r--build-kernel/kernel-ivy.xml5
-rw-r--r--build-kernel/lib/org.eclipse.virgo.kernel.launch.properties10
-rw-r--r--build-kernel/repository/ext/org.eclipse.virgo.kernel.kernelshadow.plan21
-rw-r--r--org.eclipse.virgo.kernel.agent.dm/.classpath1
-rw-r--r--org.eclipse.virgo.kernel.agent.dm/src/main/java/org/eclipse/virgo/kernel/agent/dm/internal/DeployerFailureListener.java32
-rw-r--r--org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java2
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/AbstractDeployerIntegrationTest.java20
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/NestedPlanIntegrationTests.java4
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/no.heap.dump.test.config.properties7
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/spring256.test.config.properties7
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/test.config.properties7
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties33
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java2
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/RegionAwarePackageAdminAccessor.java26
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/StandardInstallArtifactRefreshHandler.java6
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/InstallEnvironment.java5
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/internal/StandardInstallEnvironment.java9
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/deployer-context.xml13
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/internal-osgi-context.xml30
-rw-r--r--org.eclipse.virgo.kernel.deployer/src/test/java/org/eclipse/virgo/kernel/deployer/core/internal/ManifestUpgraderTests.java5
-rw-r--r--org.eclipse.virgo.kernel.model/src/main/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializer.java20
-rw-r--r--org.eclipse.virgo.kernel.model/src/test/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializerTests.java21
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/quasi/QuasiFramework.java8
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/BundleIdBasedRegion.java258
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/IndeterminateRegionException.java38
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java145
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java132
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java148
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java374
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java40
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionSpanningException.java51
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java96
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHook.java68
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java115
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java223
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookFactory.java45
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java69
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java119
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java229
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/resources/META-INF/spring/osgi-framework-context.xml10
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerTests.java69
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHookTests.java85
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java256
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java501
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java90
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java306
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegionTests.java305
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java190
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java70
-rw-r--r--org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/Activator.java2
-rw-r--r--org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/internal/OsgiKernelShellCommand.java2
-rw-r--r--org.eclipse.virgo.kernel.shell/.classpath1
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/CommandExecutor.java2
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/LinePrinter.java2
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SessionCommandExecutor.java2
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SingleSessionCommandExecutor.java2
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardQuasiLiveFramework.java7
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateService.java45
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/module-context.xml3
-rw-r--r--org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/osgi-context.xml4
-rw-r--r--org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateServiceTests.java60
-rw-r--r--org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/stubs/StubQuasiFramework.java4
-rw-r--r--org.eclipse.virgo.kernel.shutdown/src/main/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfiguration.java2
-rw-r--r--org.eclipse.virgo.kernel.shutdown/src/test/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfigurationTests.java2
-rw-r--r--org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/QuasiFrameworkIntegrationTests.java6
-rw-r--r--org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/RegionTests.java1
-rw-r--r--org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgicommand/helper/test/ClassLoadingHelperIntegrationTests.java17
-rw-r--r--org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/test/AbstractKernelIntegrationTest.java17
-rw-r--r--org.eclipse.virgo.kernel.test/src/test/resources/META-INF/test.config.properties6
-rw-r--r--org.eclipse.virgo.kernel.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties24
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/Activator.java13
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/equinox/UsesAnalyser.java2
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java50
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFramework.java194
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFrameworkFactory.java19
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardResolutionFailureDetective.java3
-rw-r--r--org.eclipse.virgo.kernel.userregion/src/test/java/org/eclipse/virgo/kernel/userregion/internal/equinox/AbstractOsgiFrameworkLaunchingTests.java52
-rw-r--r--org.eclipse.virgo.kernel.userregion/template.mf1
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/.classpath24
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/.project35
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/.settings/org.eclipse.wst.common.project.facet.core.xml4
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/.springBeans13
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/build.xml8
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/ivy.xml34
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/main/java/.gitignore0
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java311
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/PackageImportWildcardExpander.java (renamed from org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/PackageImportWildcardExpander.java)16
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionFactoryParserLogger.java (renamed from org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerParserLogger.java)8
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java128
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/test/java/.gitignore0
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/PackageImportWildcardExpanderTests.java (renamed from org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/PackageImportWildcardExpanderTests.java)3
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java115
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/template.mf19
100 files changed, 4970 insertions, 664 deletions
diff --git a/.gitignore b/.gitignore
index 2f4a727d..671b0cd9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ integration-repo
ivy-cache
derby.log
.ant-targets-build.xml
+com.cenqua.clover.core.prefs \ No newline at end of file
diff --git a/build-kernel/build.xml b/build-kernel/build.xml
index d0ed369b..784fcaa2 100644
--- a/build-kernel/build.xml
+++ b/build-kernel/build.xml
@@ -9,6 +9,7 @@
<pathelement location="../org.eclipse.virgo.kernel.services"/>
<pathelement location="../org.eclipse.virgo.kernel.osgi"/>
<pathelement location="../org.eclipse.virgo.kernel.deployer"/>
+ <pathelement location="../org.eclipse.virgo.kernel.userregionfactory"/>
<pathelement location="../org.eclipse.virgo.kernel.userregion"/>
<pathelement location="../org.eclipse.virgo.kernel.agent.dm"/>
<pathelement location="../org.eclipse.virgo.kernel.kerneldmfragment"/>
diff --git a/build-kernel/config/org.eclipse.virgo.kernel.userregion.properties b/build-kernel/config/org.eclipse.virgo.kernel.userregion.properties
index 9e817595..ec89d2fd 100644
--- a/build-kernel/config/org.eclipse.virgo.kernel.userregion.properties
+++ b/build-kernel/config/org.eclipse.virgo.kernel.userregion.properties
@@ -9,6 +9,7 @@ packageImports =\
org.eclipse.virgo.kernel.deployer.core.event;version="0",\
org.eclipse.virgo.kernel.install.*;version="0",\
org.eclipse.virgo.kernel.osgi.*;version="0",\
+ org.eclipse.virgo.kernel.model;version="0",\
org.eclipse.virgo.kernel.model.management;version="0",\
org.eclipse.virgo.kernel.module;version="0",\
org.eclipse.virgo.kernel.serviceability;version="0",\
@@ -24,6 +25,13 @@ packageImports =\
org.apache.commons.logging;version="[1.0.0,2.0.0)",\
org.apache.commons.logging.impl;version="[1.0.0,2.0.0)",\
org.aspectj.*;version="[1.6.5.RELEASE,2.0.0)",\
+ org.osgi.*;version="0",\
+ org.ietf.jgss;version="0",\
+ org.omg.*;version="0",\
+ org.w3c.*;version="0",\
+ org.xml.*;version="0",\
+ org.eclipse.osgi.*;version="0",\
+ javax.*;version="0",\
org.osgi.service.cm;version="0",\
org.osgi.service.log;version="0",\
org.osgi.service.event;version="0",\
@@ -31,6 +39,9 @@ packageImports =\
org.slf4j.spi;version="[1.6.1,2)"
serviceImports =\
+ org.eclipse.virgo.kernel.osgi.region.Region,\
+ org.eclipse.virgo.kernel.osgi.region.RegionDigraph,\
+ org.osgi.framework.hooks.resolver.ResolverHookFactory,\
org.eclipse.virgo.kernel.deployer.core.ApplicationDeployer,\
org.eclipse.virgo.kernel.deployer.core.DeployUriNormaliser,\
org.eclipse.virgo.kernel.install.artifact.ScopeServiceRepository,\
@@ -45,9 +56,13 @@ serviceImports =\
org.eclipse.virgo.kernel.core.Shutdown,\
org.osgi.service.cm.ConfigurationAdmin,\
org.osgi.service.event.EventAdmin,\
+ org.eclipse.virgo.medic.eventlog.EventLogger,\
org.eclipse.virgo.medic.dump.DumpGenerator,\
org.eclipse.virgo.kernel.shim.scope.ScopeFactory,\
- org.eclipse.virgo.kernel.shim.serviceability.TracingService
+ org.eclipse.virgo.kernel.shim.serviceability.TracingService,\
+ org.eclipse.virgo.kernel.model.RuntimeArtifactRepository,\
+ org.eclipse.osgi.service.resolver.PlatformAdmin,\
+ org.osgi.service.packageadmin.PackageAdmin
serviceExports =\
org.eclipse.virgo.kernel.install.artifact.InstallArtifactLifecycleListener,\
@@ -59,24 +74,12 @@ serviceExports =\
org.eclipse.virgo.kernel.osgi.framework.OsgiFramework,\
org.eclipse.virgo.kernel.osgi.framework.ImportExpander,\
org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil,\
+ org.eclipse.virgo.kernel.osgi.region.Region,\
org.osgi.service.event.EventHandler,\
org.osgi.service.cm.ConfigurationListener,\
org.osgi.service.cm.ManagedService,\
- org.osgi.service.cm.ManagedServiceFactory
-
-inheritedFrameworkProperties =\
- eclipse.bundle.setTCCL,\
- eclipse.enableStateSaver,\
- org.eclipse.virgo.suppress.heap.dumps,\
- osgi.java.profile,\
- osgi.parentClassloader,\
- osgi.context.bootdelegation,\
- osgi.compatibility.bootdelegation,\
- osgi.java.profile.bootdelegation,\
- osgi.hook.configurators.include
-
-# osgi console support
-# osgi.console=2401
+ org.osgi.service.cm.ManagedServiceFactory,\
+ org.osgi.framework.BundleContext
# the next line must not be broken with back-slashes
-initialArtifacts = repository:plan/org.eclipse.virgo.kernel.userregion.springdm
+initialArtifacts = repository:plan/org.eclipse.virgo.kernel.kernelshadow,repository:plan/org.eclipse.virgo.kernel.userregion.springdm
diff --git a/build-kernel/kernel-ivy.xml b/build-kernel/kernel-ivy.xml
index c324ce1f..4353289b 100644
--- a/build-kernel/kernel-ivy.xml
+++ b/build-kernel/kernel-ivy.xml
@@ -14,6 +14,7 @@
<!-- lib/kernel -->
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel" rev="latest.integration" conf="lib-kernel->runtime"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgicommand" rev="latest.integration" conf="lib-kernel->runtime"/>
+ <dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.userregionfactory" rev="latest.integration" conf="lib-kernel->runtime"/>
<dependency org="org.slf4j" name="com.springsource.slf4j.org.apache.commons.logging" rev="${org.slf4j}" conf="lib-kernel->runtime"/>
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="${org.aspectj}" conf="lib-kernel->runtime"/>
<dependency org="org.eclipse.osgi" name="org.eclipse.osgi.services" rev="${org.eclipse.osgi.services}" conf="lib-kernel->runtime"/>
@@ -26,6 +27,10 @@
<dependency org="org.springframework.osgi" name="org.springframework.osgi.extender" rev="${org.springframework.osgi}" conf="repository-ext->runtime"/>
<dependency org="org.springframework.osgi" name="org.springframework.osgi.io" rev="${org.springframework.osgi}" conf="repository-ext->runtime"/>
+ <!-- Following two lines are part of the workaround to bug 333071 -->
+ <dependency org="org.apache.commons" name="com.springsource.org.apache.commons.codec" rev="1.3.0" conf="repository-ext->runtime"/>
+ <dependency org="org.apache.commons" name="com.springsource.org.apache.commons.httpclient" rev="3.1.0" conf="repository-ext->runtime"/>
+
<exclude org="org.eclipse.osgi" module="org.eclipse.osgi"/>
<exclude org="org.eclipse.virgo.util" conf="repository-ext"/>
<exclude org="org.eclipse.virgo.osgi" module="org.eclipse.virgo.osgi.extensions.equinox"/>
diff --git a/build-kernel/lib/org.eclipse.virgo.kernel.launch.properties b/build-kernel/lib/org.eclipse.virgo.kernel.launch.properties
index 593bd060..a72788ab 100644
--- a/build-kernel/lib/org.eclipse.virgo.kernel.launch.properties
+++ b/build-kernel/lib/org.eclipse.virgo.kernel.launch.properties
@@ -31,18 +31,22 @@ launcher.bundles =\
file:lib/kernel/com.springsource.org.aopalliance-1.0.0.jar,\
file:lib/kernel/org.eclipse.virgo.kernel.artifact-@KERNEL.VERSION@.jar@start,\
file:lib/kernel/org.eclipse.virgo.kernel.services-@KERNEL.VERSION@.jar@start,\
- file:lib/kernel/org.eclipse.virgo.kernel.osgi-@KERNEL.VERSION@.jar@start,\
file:lib/kernel/org.eclipse.virgo.kernel.deployer-@KERNEL.VERSION@.jar@start,\
file:lib/kernel/org.eclipse.virgo.kernel.model-@KERNEL.VERSION@.jar@start,\
file:lib/kernel/org.eclipse.virgo.kernel.kerneldmfragment-@KERNEL.VERSION@.jar,\
- file:lib/kernel/org.eclipse.virgo.kernel.shell-@KERNEL.VERSION@.jar@start
-
+ file:lib/kernel/org.eclipse.virgo.kernel.shell-@KERNEL.VERSION@.jar@start,\
+ file:lib/kernel/org.eclipse.virgo.kernel.osgi-@KERNEL.VERSION@.jar@start,\
+ file:lib/kernel/org.eclipse.virgo.kernel.userregionfactory-@KERNEL.VERSION@.jar@start
#Equinox Configuration
osgi.parentClassloader=fwk
osgi.context.bootdelegation=false
osgi.compatibility.bootdelegation=false
osgi.clean=true
+org.osgi.framework.bsnversion=multiple
+
+# osgi console support
+# osgi.console=2401
osgi.java.profile=file:lib/java6-server.profile
osgi.java.profile.bootdelegation=override
diff --git a/build-kernel/repository/ext/org.eclipse.virgo.kernel.kernelshadow.plan b/build-kernel/repository/ext/org.eclipse.virgo.kernel.kernelshadow.plan
new file mode 100644
index 00000000..ac806be3
--- /dev/null
+++ b/build-kernel/repository/ext/org.eclipse.virgo.kernel.kernelshadow.plan
@@ -0,0 +1,21 @@
+<plan name="org.eclipse.virgo.kernel.kernelshadow" version="2.2.0" scoped="false" atomic="false"
+ xmlns="http://www.eclipse.org/virgo/schema/plan"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.eclipse.org/virgo/schema/plan
+ http://www.eclipse.org/virgo/schema/plan/eclipse-virgo-plan.xsd">
+
+ <!-- This plan is part of a workaround for bug 333071 to ensure that the following bundles
+ are deployed to the user region even though they are also present in the kernel
+ region. The bug means these bundles would not be faulted-in as their absence from
+ the user region goes undetected. -->
+ <artifact type="bundle" name="org.springframework.aop" version="[3.0.0.RELEASE, 3.0.1)"/>
+ <artifact type="bundle" name="org.springframework.asm" version="[3.0.0.RELEASE, 3.0.1)"/>
+ <artifact type="bundle" name="org.springframework.expression" version="[3.0.0.RELEASE, 3.0.1)"/>
+ <artifact type="bundle" name="org.springframework.beans" version="[3.0.0.RELEASE, 3.0.1)"/>
+ <artifact type="bundle" name="org.springframework.core" version="[3.0.0.RELEASE, 3.0.1)"/>
+ <artifact type="bundle" name="org.springframework.context" version="[3.0.0.RELEASE, 3.0.1)"/>
+ <artifact type="bundle" name="com.springsource.org.aopalliance" version="[1, 1]"/>
+ <artifact type="bundle" name="com.springsource.org.apache.commons.codec" version="[1.3.0, 1.3.0]"/>
+ <artifact type="bundle" name="com.springsource.org.apache.commons.httpclient" version="[3.1.0, 3.1.0]"/>
+</plan>
diff --git a/org.eclipse.virgo.kernel.agent.dm/.classpath b/org.eclipse.virgo.kernel.agent.dm/.classpath
index 5f209d69..779ed358 100644
--- a/org.eclipse.virgo.kernel.agent.dm/.classpath
+++ b/org.eclipse.virgo.kernel.agent.dm/.classpath
@@ -40,6 +40,7 @@
<classpathentry kind="src" path="/org.eclipse.virgo.kernel.core"/>
<classpathentry kind="var" path="KERNEL_IVY_CACHE/org.springframework/org.springframework.core/3.0.0.RELEASE/org.springframework.core-3.0.0.RELEASE.jar" sourcepath="/KERNEL_IVY_CACHE/org.springframework/org.springframework.core/3.0.0.RELEASE/org.springframework.core-sources-3.0.0.RELEASE.jar"/>
<classpathentry kind="var" path="KERNEL_IVY_CACHE/org.springframework/org.springframework.beans/3.0.0.RELEASE/org.springframework.beans-3.0.0.RELEASE.jar" sourcepath="/KERNEL_IVY_CACHE/org.springframework/org.springframework.beans/3.0.0.RELEASE/org.springframework.beans-sources-3.0.0.RELEASE.jar"/>
+ <classpathentry kind="src" path="/org.eclipse.virgo.kernel.osgi"/>
<classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse/equinox-event/1.2.100.v20101208/equinox-event-1.2.100.v20101208.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
diff --git a/org.eclipse.virgo.kernel.agent.dm/src/main/java/org/eclipse/virgo/kernel/agent/dm/internal/DeployerFailureListener.java b/org.eclipse.virgo.kernel.agent.dm/src/main/java/org/eclipse/virgo/kernel/agent/dm/internal/DeployerFailureListener.java
index cca255c7..afd39bb9 100644
--- a/org.eclipse.virgo.kernel.agent.dm/src/main/java/org/eclipse/virgo/kernel/agent/dm/internal/DeployerFailureListener.java
+++ b/org.eclipse.virgo.kernel.agent.dm/src/main/java/org/eclipse/virgo/kernel/agent/dm/internal/DeployerFailureListener.java
@@ -11,13 +11,16 @@
package org.eclipse.virgo.kernel.agent.dm.internal;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.medic.eventlog.EventLogger;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
-import org.eclipse.virgo.medic.eventlog.EventLogger;
-
/**
* A {@link EventHandler} implementation that listens for and handles Blueprint container failure events.
* <p />
@@ -37,6 +40,10 @@ final class DeployerFailureListener implements EventHandler {
private final EventLogger eventLogger;
+ private volatile RegionDigraph regionDigraph;
+
+ private volatile Region agentRegion;
+
public DeployerFailureListener(EventLogger eventLogger) {
this.eventLogger = eventLogger;
}
@@ -55,8 +62,25 @@ final class DeployerFailureListener implements EventHandler {
}
private boolean inThisRegion(Bundle bundle) {
- Bundle agentBundle = FrameworkUtil.getBundle(getClass());
- return agentBundle.getBundleContext().getBundle(bundle.getBundleId()) == bundle;
+ if (regionDigraph == null) {
+ Bundle agentBundle = FrameworkUtil.getBundle(getClass());
+ BundleContext bundleContext = agentBundle.getBundleContext();
+ ServiceReference<RegionDigraph> regionMembershipServiceReference = bundleContext.getServiceReference(RegionDigraph.class);
+ if (regionMembershipServiceReference != null) {
+ this.regionDigraph = bundleContext.getService(regionMembershipServiceReference);
+ this.agentRegion = getRegion(agentBundle);
+ }
+ }
+ return this.regionDigraph != null ? getRegion(bundle).equals(this.agentRegion) : true;
+ }
+
+ private Region getRegion(Bundle bundle) {
+ for (Region region : this.regionDigraph) {
+ if (region.contains(bundle)) {
+ return region;
+ }
+ }
+ return null;
}
}
diff --git a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java
index 4c3cd787..18f91d77 100644
--- a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java
+++ b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/AbstractDeployerIntegrationTest.java b/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/AbstractDeployerIntegrationTest.java
index 7c326acd..497bdab5 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/AbstractDeployerIntegrationTest.java
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/AbstractDeployerIntegrationTest.java
@@ -20,6 +20,10 @@ import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import org.eclipse.virgo.kernel.deployer.core.ApplicationDeployer;
+import org.eclipse.virgo.kernel.deployer.core.DeploymentIdentity;
+import org.eclipse.virgo.kernel.osgi.framework.OsgiFramework;
+import org.eclipse.virgo.test.framework.dmkernel.DmKernelTestRunner;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
@@ -31,15 +35,8 @@ import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.framework.SurrogateBundle;
import org.osgi.service.packageadmin.PackageAdmin;
-import org.eclipse.virgo.kernel.osgi.framework.OsgiFramework;
-
-import org.eclipse.virgo.kernel.deployer.core.ApplicationDeployer;
-import org.eclipse.virgo.kernel.deployer.core.DeploymentIdentity;
-import org.eclipse.virgo.test.framework.dmkernel.DmKernelTestRunner;
-
@RunWith(DmKernelTestRunner.class)
@SuppressWarnings("deprecation")
public abstract class AbstractDeployerIntegrationTest {
@@ -66,16 +63,17 @@ public abstract class AbstractDeployerIntegrationTest {
this.deployer = this.context.getService(applicationDeployerServiceReference);
}
- Bundle bundle = this.context.getBundle(1);
- if (bundle instanceof SurrogateBundle) {
- this.kernelContext = ((SurrogateBundle) bundle).getCompositeBundleContext();
- }
+ this.kernelContext = getKernelContext();
ServiceReference<PackageAdmin> packageAdminServiceReference = context.getServiceReference(PackageAdmin.class);
if (packageAdminServiceReference != null) {
this.packageAdmin = context.getService(packageAdminServiceReference);
}
}
+
+ private BundleContext getKernelContext() {
+ return this.context.getBundle(0L).getBundleContext();
+ }
@BeforeClass
public static void awaitKernelStartup() throws Exception {
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/NestedPlanIntegrationTests.java b/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/NestedPlanIntegrationTests.java
index 8bb533c1..6e64d014 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/NestedPlanIntegrationTests.java
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/NestedPlanIntegrationTests.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import org.eclipse.virgo.kernel.deployer.core.DeploymentException;
import org.eclipse.virgo.kernel.deployer.core.DeploymentIdentity;
@@ -276,7 +277,8 @@ public class NestedPlanIntegrationTests extends AbstractDeployerIntegrationTest
private void checkPlanScoping(TestPlanArtifactInfo parent, Model model) {
if (parent.isScoped()) {
Artifact parentPlan = getPlan(parent);
- for (Artifact child : parentPlan.getDependents()) {
+ Set<Artifact> children = parentPlan.getDependents();
+ for (Artifact child : children) {
if (PLAN_TYPE.equals(child.getType())) {
String childPlanName = child.getName();
String unscopedChildPlanName = parent.getChildPlan().getName();
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/MANIFEST.MF b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/MANIFEST.MF
index 1274b8a2..326a811f 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/MANIFEST.MF
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/MANIFEST.MF
@@ -12,6 +12,7 @@ Import-Package: org.eclipse.virgo.kernel.core,
org.eclipse.virgo.kernel.module,
org.eclipse.virgo.kernel.osgi.common,
org.eclipse.virgo.kernel.osgi.framework,
+ org.eclipse.virgo.kernel.osgi.region,
org.eclipse.virgo.kernel.services.work,
org.eclipse.virgo.util.io,
org.eclipse.virgo.util.math,
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/no.heap.dump.test.config.properties b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/no.heap.dump.test.config.properties
index 2b182d63..6dae07e2 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/no.heap.dump.test.config.properties
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/no.heap.dump.test.config.properties
@@ -30,10 +30,12 @@ launcher.bundles =\
file:../ivy-cache/repository/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar,\
file:../org.eclipse.virgo.kernel.artifact/target/classes@start,\
file:../org.eclipse.virgo.kernel.services/target/classes@start,\
- file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
file:../org.eclipse.virgo.kernel.deployer/target/classes@start,\
file:../org.eclipse.virgo.kernel.model/target/classes@start,\
- file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes
+ file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes,\
+ file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
+ file:../org.eclipse.virgo.kernel.userregionfactory/target/classes@start
+
org.eclipse.virgo.test.properties.include=file:../build.versions,file:../build.properties
@@ -43,6 +45,7 @@ osgi.context.bootdelegation=false
osgi.compatibility.bootdelegation=false
osgi.clean=true
osgi.configuration.area=target
+org.osgi.framework.bsnversion=multiple
#osgi.console=2401
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/spring256.test.config.properties b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/spring256.test.config.properties
index fd1db836..a2bfe2d6 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/spring256.test.config.properties
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/spring256.test.config.properties
@@ -30,10 +30,12 @@ launcher.bundles =\
file:../ivy-cache/repository/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar,\
file:../org.eclipse.virgo.kernel.artifact/target/classes@start,\
file:../org.eclipse.virgo.kernel.services/target/classes@start,\
- file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
file:../org.eclipse.virgo.kernel.deployer/target/classes@start,\
file:../org.eclipse.virgo.kernel.model/target/classes@start,\
- file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes
+ file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes,\
+ file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
+ file:../org.eclipse.virgo.kernel.userregionfactory/target/classes@start
+
org.eclipse.virgo.test.properties.include=file:../build.versions,file:../build.properties
@@ -43,6 +45,7 @@ osgi.context.bootdelegation=false
osgi.compatibility.bootdelegation=false
osgi.clean=true
osgi.configuration.area=target
+org.osgi.framework.bsnversion=multiple
#osgi.console=2401
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/test.config.properties b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/test.config.properties
index a50c0d7a..f5f2ac60 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/test.config.properties
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/META-INF/test.config.properties
@@ -30,10 +30,12 @@ launcher.bundles =\
file:../ivy-cache/repository/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar,\
file:../org.eclipse.virgo.kernel.artifact/target/classes@start,\
file:../org.eclipse.virgo.kernel.services/target/classes@start,\
- file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
file:../org.eclipse.virgo.kernel.deployer/target/classes@start,\
file:../org.eclipse.virgo.kernel.model/target/classes@start,\
- file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes
+ file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes,\
+ file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
+ file:../org.eclipse.virgo.kernel.userregionfactory/target/classes@start
+
org.eclipse.virgo.test.properties.include=file:../build.versions,file:../build.properties
@@ -43,6 +45,7 @@ osgi.context.bootdelegation=false
osgi.compatibility.bootdelegation=false
osgi.clean=true
osgi.configuration.area=target
+org.osgi.framework.bsnversion=multiple
#osgi.console=2401
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties
index 3bc406f5..054b32d2 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties
@@ -42,12 +42,21 @@ packageImports =\
org.aspectj.*;version="[1.6.5.RELEASE,2.0.0)",\
org.junit;version="[4.7.0,5.0.0)",\
org.junit.runner;version="[4.7.0,5.0.0)",\
+ org.osgi.*;version="0",\
+ org.ietf.jgss;version="0",\
+ org.omg.*;version="0",\
+ org.w3c.*;version="0",\
+ org.xml.*;version="0",\
+ org.eclipse.osgi.*;version="0",\
+ javax.*;version="0",\
org.osgi.service.cm;version="0",\
org.osgi.service.event;version="0",\
org.osgi.service.log;version="0",\
org.slf4j;version="[1.6.1,2)"
serviceImports =\
+ org.eclipse.virgo.kernel.osgi.region.Region,\
+ org.eclipse.virgo.kernel.osgi.region.RegionDigraph,\
org.eclipse.virgo.kernel.deployer.core.ApplicationDeployer,\
org.eclipse.virgo.kernel.deployer.core.DeployUriNormaliser,\
org.eclipse.virgo.kernel.install.artifact.ScopeServiceRepository,\
@@ -58,36 +67,30 @@ serviceImports =\
org.eclipse.virgo.medic.eventlog.EventLoggerFactory,\
org.eclipse.virgo.repository.Repository,\
org.eclipse.virgo.kernel.core.Shutdown,\
+ org.osgi.framework.hooks.resolver.ResolverHookFactory,\
org.osgi.service.cm.ConfigurationAdmin,\
org.osgi.service.event.EventAdmin,\
+ org.eclipse.virgo.medic.eventlog.EventLogger,\
org.eclipse.virgo.medic.dump.DumpGenerator,\
org.eclipse.virgo.kernel.shim.scope.ScopeFactory,\
org.eclipse.virgo.kernel.shim.serviceability.TracingService,\
- org.eclipse.virgo.kernel.model.RuntimeArtifactRepository
+ org.eclipse.virgo.kernel.model.RuntimeArtifactRepository,\
+ org.eclipse.osgi.service.resolver.PlatformAdmin,\
+ org.osgi.service.packageadmin.PackageAdmin
serviceExports =\
org.eclipse.virgo.kernel.install.artifact.InstallArtifactLifecycleListener,\
org.eclipse.virgo.kernel.install.artifact.ArtifactTypeDeterminer,\
org.eclipse.virgo.kernel.install.pipeline.stage.transform.Transformer,\
+ org.eclipse.virgo.kernel.module.ModuleContextAccessor,\
org.eclipse.virgo.medic.dump.DumpContributor,\
org.eclipse.virgo.kernel.osgi.quasi.QuasiFrameworkFactory,\
org.eclipse.virgo.kernel.osgi.framework.OsgiFramework,\
org.eclipse.virgo.kernel.osgi.framework.ImportExpander,\
org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil,\
+ org.eclipse.virgo.kernel.osgi.region.Region,\
org.osgi.service.event.EventHandler,\
org.osgi.service.cm.ConfigurationListener,\
org.osgi.service.cm.ManagedService,\
- org.osgi.service.cm.ManagedServiceFactory
-
-inheritedFrameworkProperties =\
- eclipse.bundle.setTCCL,\
- eclipse.enableStateSaver,\
- org.eclipse.virgo.suppress.heap.dumps,\
- osgi.java.profile,\
- osgi.parentClassloader,\
- osgi.context.bootdelegation,\
- osgi.compatibility.bootdelegation,\
- osgi.java.profile.bootdelegation,\
- osgi.hook.configurators.include
-
-# osgi.console=2401
+ org.osgi.service.cm.ManagedServiceFactory,\
+ org.osgi.framework.BundleContext
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java
index e53fa476..b3498220 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java
@@ -278,6 +278,8 @@ final class PipelinedApplicationDeployer implements ApplicationDeployer, Applica
} catch (UnableToSatisfyBundleDependenciesException utsbde) {
logDependencySatisfactionException(uri, utsbde);
throw new DeploymentException("Dependency satisfaction failed", utsbde);
+ } finally {
+ installEnvironment.destroy();
}
}
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/RegionAwarePackageAdminAccessor.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/RegionAwarePackageAdminAccessor.java
deleted file mode 100644
index 05adc0d7..00000000
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/RegionAwarePackageAdminAccessor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 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
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VMware Inc. - initial contribution
- *******************************************************************************/
-
-package org.eclipse.virgo.kernel.deployer.core.internal;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.service.packageadmin.PackageAdmin;
-
-import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkUtils;
-import org.eclipse.virgo.kernel.osgi.region.Region;
-
-@SuppressWarnings("deprecation")
-final class RegionAwarePackageAdminAccessor {
- public static PackageAdmin getPackageAdmin(Region region) {
- BundleContext bundleContext = region.getBundleContext();
- return OsgiFrameworkUtils.getService(bundleContext, PackageAdmin.class).getService();
- }
-}
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/StandardInstallArtifactRefreshHandler.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/StandardInstallArtifactRefreshHandler.java
index d53def9e..24f7c03e 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/StandardInstallArtifactRefreshHandler.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/StandardInstallArtifactRefreshHandler.java
@@ -15,6 +15,7 @@ import org.eclipse.virgo.kernel.osgi.framework.UnableToSatisfyBundleDependencies
import org.eclipse.virgo.kernel.deployer.core.DeploymentException;
import org.eclipse.virgo.kernel.install.artifact.InstallArtifact;
+import org.eclipse.virgo.kernel.install.environment.InstallEnvironment;
import org.eclipse.virgo.kernel.install.environment.InstallEnvironmentFactory;
import org.eclipse.virgo.kernel.install.pipeline.Pipeline;
import org.eclipse.virgo.util.common.Tree;
@@ -46,12 +47,15 @@ final class StandardInstallArtifactRefreshHandler implements InstallArtifactRefr
Tree<InstallArtifact> tree = installArtifact.getTree();
boolean refreshed = true;
+ InstallEnvironment installEnvironment = this.installEnvironmentFactory.createInstallEnvironment(installArtifact);
try {
- this.refreshPipeline.process(tree, this.installEnvironmentFactory.createInstallEnvironment(installArtifact));
+ this.refreshPipeline.process(tree, installEnvironment);
} catch (UnableToSatisfyBundleDependenciesException _) {
refreshed = false;
} catch (DeploymentException _) {
refreshed = false;
+ } finally {
+ installEnvironment.destroy();
}
return refreshed;
}
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/InstallEnvironment.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/InstallEnvironment.java
index 60fc7951..15b35a77 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/InstallEnvironment.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/InstallEnvironment.java
@@ -48,4 +48,9 @@ public interface InstallEnvironment {
* @return an OSGi state or <code>null</code>
*/
QuasiFramework getQuasiFramework();
+
+ /**
+ * Delete any resources associated with this {@link InstallEnvironment}.
+ */
+ void destroy();
}
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/internal/StandardInstallEnvironment.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/internal/StandardInstallEnvironment.java
index 6d6cdbb3..b4aa90f2 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/internal/StandardInstallEnvironment.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/environment/internal/StandardInstallEnvironment.java
@@ -61,4 +61,13 @@ final class StandardInstallEnvironment implements InstallEnvironment {
public QuasiFramework getQuasiFramework() {
return this.quasiFramework;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void destroy() {
+ this.quasiFramework.destroy();
+ }
+
}
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/deployer-context.xml b/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/deployer-context.xml
index 0a41f09b..09e3bca0 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/deployer-context.xml
+++ b/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/deployer-context.xml
@@ -156,14 +156,7 @@
<beans:bean id="plumber"
class="org.eclipse.virgo.kernel.deployer.core.internal.Plumber">
- <beans:constructor-arg>
- <beans:bean factory-method="getPackageAdmin"
- class="org.eclipse.virgo.kernel.deployer.core.internal.RegionAwarePackageAdminAccessor">
- <beans:constructor-arg>
- <reference interface="org.eclipse.virgo.kernel.osgi.region.Region" />
- </beans:constructor-arg>
- </beans:bean>
- </beans:constructor-arg>
+ <beans:constructor-arg ref="packageAdmin" />
<beans:constructor-arg ref="bundleContext" />
<beans:constructor-arg ref="pipelineFactory" />
<beans:constructor-arg ref="quasiFrameworkFactory" />
@@ -266,10 +259,12 @@
<beans:constructor-arg ref="bundleStarter" />
<beans:constructor-arg ref="tracingService" />
<beans:constructor-arg ref="packageAdminUtil" />
- <beans:constructor-arg value="#{region.getBundleContext()}" />
+ <beans:constructor-arg ref="userBundleContext" />
<beans:constructor-arg ref="eventLogger" />
<beans:constructor-arg ref="artifactIdentityDeterminer" />
</beans:bean>
+
+ <reference id="userBundleContext" interface="org.osgi.framework.BundleContext" filter="(org.eclipse.virgo.kernel.regionContext=true)"/>
<service ref="bundleInstallArtifactTreeFactory"
interface="org.eclipse.virgo.kernel.install.artifact.InstallArtifactTreeFactory" />
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/internal-osgi-context.xml b/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/internal-osgi-context.xml
index 6c7f7ef0..d5347295 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/internal-osgi-context.xml
+++ b/org.eclipse.virgo.kernel.deployer/src/main/resources/META-INF/spring/internal-osgi-context.xml
@@ -4,18 +4,15 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd">
- <!--
- Configuration for OSGi services that the kernel depends on and
- provides to the framework. These services are not considered part of
- the kernel API.
- -->
+ <!-- Configuration for OSGi services that the kernel depends on and provides
+ to the framework. These services are not considered part of the kernel API. -->
<osgi:reference id="configAdmin"
interface="org.osgi.service.cm.ConfigurationAdmin" />
<osgi:reference id="eventLogger"
interface="org.eclipse.virgo.medic.eventlog.EventLogger" />
-
+
<osgi:reference id="dumpGenerator"
interface="org.eclipse.virgo.medic.dump.DumpGenerator" />
@@ -42,16 +39,21 @@
<osgi:reference id="quasiFrameworkFactory"
interface="org.eclipse.virgo.kernel.osgi.quasi.QuasiFrameworkFactory" />
-
+
<osgi:reference id="eventAdmin" interface="org.osgi.service.event.EventAdmin" />
- <osgi:reference id="bundleStarter" interface="org.eclipse.virgo.kernel.core.BundleStarter" context-class-loader="unmanaged"/>
-
- <osgi:reference id="importExpander" interface="org.eclipse.virgo.kernel.osgi.framework.ImportExpander"/>
-
- <osgi:reference id="region" interface="org.eclipse.virgo.kernel.osgi.region.Region"/>
-
- <!-- services -->
+ <osgi:reference id="bundleStarter"
+ interface="org.eclipse.virgo.kernel.core.BundleStarter"
+ context-class-loader="unmanaged" />
+
+ <osgi:reference id="importExpander"
+ interface="org.eclipse.virgo.kernel.osgi.framework.ImportExpander" />
+
+ <osgi:reference id="region"
+ interface="org.eclipse.virgo.kernel.osgi.region.Region"
+ filter="(org.eclipse.virgo.kernel.region.name=org.eclipse.virgo.region.user)" />
+
+ <!-- services -->
<osgi:service ref="moduleContextEventPublisher"
interface="org.eclipse.virgo.kernel.module.ModuleContextEventPublisher" />
diff --git a/org.eclipse.virgo.kernel.deployer/src/test/java/org/eclipse/virgo/kernel/deployer/core/internal/ManifestUpgraderTests.java b/org.eclipse.virgo.kernel.deployer/src/test/java/org/eclipse/virgo/kernel/deployer/core/internal/ManifestUpgraderTests.java
index 0f7821e5..9a8bc4fd 100644
--- a/org.eclipse.virgo.kernel.deployer/src/test/java/org/eclipse/virgo/kernel/deployer/core/internal/ManifestUpgraderTests.java
+++ b/org.eclipse.virgo.kernel.deployer/src/test/java/org/eclipse/virgo/kernel/deployer/core/internal/ManifestUpgraderTests.java
@@ -162,5 +162,10 @@ public class ManifestUpgraderTests {
throw new UnsupportedOperationException();
}
+ @Override
+ public void destroy() {
+ throw new UnsupportedOperationException();
+ }
+
}
}
diff --git a/org.eclipse.virgo.kernel.model/src/main/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializer.java b/org.eclipse.virgo.kernel.model/src/main/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializer.java
index 7805fbba..813d0fe0 100644
--- a/org.eclipse.virgo.kernel.model/src/main/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializer.java
+++ b/org.eclipse.virgo.kernel.model/src/main/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializer.java
@@ -15,6 +15,7 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.eclipse.virgo.kernel.model.RuntimeArtifactRepository;
+import org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil;
import org.eclipse.virgo.kernel.serviceability.NonNull;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -22,8 +23,6 @@ import org.osgi.framework.BundleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil;
-
/**
* An intializer responsible for registering a {@link ModelBundleListener} and enumerating any existing {@link Bundle}
* objects from the OSGi Framework.
@@ -44,17 +43,20 @@ public final class ModelBundleListenerInitializer {
private final PackageAdminUtil packageAdminUtil;
private final BundleContext kernelBundleContext;
-
+
private final BundleContext userRegionBundleContext;
private final BundleListener bundleListener;
+ private final BundleContext systemBundleContext;
+
public ModelBundleListenerInitializer(@NonNull RuntimeArtifactRepository artifactRepository, @NonNull PackageAdminUtil packageAdminUtil,
@NonNull BundleContext kernelBundleContext, @NonNull BundleContext userRegionBundleContext) {
this.artifactRepository = artifactRepository;
this.packageAdminUtil = packageAdminUtil;
this.kernelBundleContext = kernelBundleContext;
this.userRegionBundleContext = userRegionBundleContext;
+ this.systemBundleContext = kernelBundleContext.getBundle(0L).getBundleContext();
this.bundleListener = new ModelBundleListener(kernelBundleContext, artifactRepository, packageAdminUtil);
}
@@ -64,12 +66,14 @@ public final class ModelBundleListenerInitializer {
*/
@PostConstruct
public void initialize() {
- this.userRegionBundleContext.addBundleListener(bundleListener);
- for (Bundle bundle : userRegionBundleContext.getBundles()) {
+ // Register the listener with the system bundle to see all bundles.
+ this.systemBundleContext.addBundleListener(this.bundleListener);
+ // Find bundles using the user region context as application bundles are added to the user region.
+ for (Bundle bundle : this.userRegionBundleContext.getBundles()) {
try {
- this.artifactRepository.add(new BundleArtifact(kernelBundleContext, packageAdminUtil, bundle));
+ this.artifactRepository.add(new BundleArtifact(this.kernelBundleContext, this.packageAdminUtil, bundle));
} catch (Exception e) {
- logger.error(String.format("Exception adding bundle '%s:%s' to the repository", bundle.getSymbolicName(),
+ this.logger.error(String.format("Exception adding bundle '%s:%s' to the repository", bundle.getSymbolicName(),
bundle.getVersion().toString()), e);
}
}
@@ -80,6 +84,6 @@ public final class ModelBundleListenerInitializer {
*/
@PreDestroy
public void destroy() {
- this.userRegionBundleContext.removeBundleListener(bundleListener);
+ this.systemBundleContext.removeBundleListener(this.bundleListener);
}
}
diff --git a/org.eclipse.virgo.kernel.model/src/test/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializerTests.java b/org.eclipse.virgo.kernel.model/src/test/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializerTests.java
index 760a6e4b..3d6811dc 100644
--- a/org.eclipse.virgo.kernel.model/src/test/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializerTests.java
+++ b/org.eclipse.virgo.kernel.model/src/test/java/org/eclipse/virgo/kernel/model/internal/bundle/ModelBundleListenerInitializerTests.java
@@ -18,6 +18,7 @@ import java.io.IOException;
import org.junit.Test;
import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
import org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil;
@@ -36,12 +37,18 @@ public class ModelBundleListenerInitializerTests {
private final PackageAdminUtil packageAdminUtil = createMock(PackageAdminUtil.class);
private final StubBundleContext bundleContext;
+
+ private final StubBundleContext systemBundleContext;
{
StubBundle bundle = new StubBundle();
this.bundleContext = (StubBundleContext) bundle.getBundleContext();
+ StubBundle stubSystemBundle = new StubBundle(0L, "org.osgi.framework", new Version("0"), "loc");
+ this.systemBundleContext = (StubBundleContext)stubSystemBundle.getBundleContext();
+ this.bundleContext.addInstalledBundle(stubSystemBundle);
+ this.systemBundleContext.addInstalledBundle(bundle);
String filterString = String.format("(&(objectClass=%s)(artifactType=bundle))", DependencyDeterminer.class.getCanonicalName());
this.bundleContext.addFilter(filterString, new TrueFilter(filterString));
- this.bundleContext.addInstalledBundle(bundle);
+ //this.bundleContext.addInstalledBundle(bundle);
}
private final ModelBundleListenerInitializer initializer = new ModelBundleListenerInitializer(artifactRepository, packageAdminUtil, bundleContext, bundleContext);
@@ -62,23 +69,23 @@ public class ModelBundleListenerInitializerTests {
}
@Test(expected = FatalAssertionException.class)
- public void nullUserBundleContext() {
+ public void nullUserRegionBundleContext() {
new ModelBundleListenerInitializer(artifactRepository, packageAdminUtil, bundleContext, null);
}
-
+
@Test
public void initialize() throws IOException, InvalidSyntaxException {
- assertEquals(0, this.bundleContext.getBundleListeners().size());
+ assertEquals(0, this.systemBundleContext.getBundleListeners().size());
this.initializer.initialize();
- assertEquals(1, this.bundleContext.getBundleListeners().size());
+ assertEquals(1, this.systemBundleContext.getBundleListeners().size());
assertEquals(1, this.artifactRepository.getArtifacts().size());
}
@Test
public void destroy() throws IOException, InvalidSyntaxException {
this.initializer.initialize();
- assertEquals(1, this.bundleContext.getBundleListeners().size());
+ assertEquals(1, this.systemBundleContext.getBundleListeners().size());
this.initializer.destroy();
- assertEquals(0, this.bundleContext.getBundleListeners().size());
+ assertEquals(0, this.systemBundleContext.getBundleListeners().size());
}
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/quasi/QuasiFramework.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/quasi/QuasiFramework.java
index 2f12f68a..02163a0b 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/quasi/QuasiFramework.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/quasi/QuasiFramework.java
@@ -15,11 +15,10 @@ import java.net.URI;
import java.util.List;
import org.eclipse.osgi.service.resolver.State;
+import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.osgi.framework.BundleException;
import org.osgi.framework.Version;
-import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
-
/**
* {@link QuasiFramework} is a snapshot of the OSGi framework state into which bundles can be installed and resolved
* and, in the normal case, committed into the OSGi framework.
@@ -103,4 +102,9 @@ public interface QuasiFramework {
*/
void commit() throws BundleException;
+ /**
+ * Delete any resources associated with this {@link QuasiFramework}.
+ */
+ void destroy();
+
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/BundleIdBasedRegion.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/BundleIdBasedRegion.java
new file mode 100644
index 00000000..a1a80512
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/BundleIdBasedRegion.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.serviceability.NonNull;
+import org.eclipse.virgo.util.math.ConcurrentHashSet;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+
+/**
+ * {@link BundleIdBasedRegion} is an implementation of {@link Region} which keeps a track of the bundles in the region
+ * by recording their bundle identifiers.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+public final class BundleIdBasedRegion implements Region {
+
+ private static final String REGION_LOCATION_DELIMITER = "@";
+
+ private static final String REFERENCE_SCHEME = "reference:";
+
+ private static final String FILE_SCHEME = "file:";
+
+ // A concurrent data structure ensures the contains method does not need synchronisation.
+ private final Set<Long> bundleIds = new ConcurrentHashSet<Long>();
+
+ // Updates do need synchronising to avoid races.
+ private final Object updateMonitor = new Object();
+
+ private final String regionName;
+
+ private final RegionDigraph regionDigraph;
+
+ private final BundleContext systemBundleContext;
+
+ public BundleIdBasedRegion(@NonNull String regionName, @NonNull RegionDigraph regionDigraph, @NonNull BundleContext systemBundleContext) {
+ this.regionName = regionName;
+ this.regionDigraph = regionDigraph;
+ this.systemBundleContext = systemBundleContext;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return this.regionName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addBundle(Bundle bundle) throws BundleException {
+ synchronized (this.updateMonitor) {
+ checkBundleNotAssociatedWithAnotherRegion(bundle);
+
+ String symbolicName = bundle.getSymbolicName();
+ Version version = bundle.getVersion();
+
+ checkDuplicateBundleInRegion(bundle, symbolicName, version);
+
+ this.bundleIds.add(bundle.getBundleId());
+ }
+ }
+
+ private void checkBundleNotAssociatedWithAnotherRegion(Bundle bundle) throws BundleException {
+ for (Region r : this.regionDigraph) {
+ if (!this.equals(r) && r.contains(bundle)) {
+ throw new BundleException("Bundle '" + bundle + "' is already associated with region '" + r + "'", BundleException.INVALID_OPERATION);
+ }
+ }
+ }
+
+ private void checkDuplicateBundleInRegion(Bundle bundle, String symbolicName, Version version) throws BundleException {
+ Bundle existingBundle = getBundle(symbolicName, version);
+ if (existingBundle != null && !existingBundle.equals(bundle)) {
+ throw new BundleException("Cannot add bundle '" + bundle + "' to region '" + this
+ + "' as its symbolic name and version conflict with those of bundle '" + existingBundle + "' which is already present in the region",
+ BundleException.DUPLICATE_BUNDLE_ERROR);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addBundle(long bundleId) {
+ synchronized (this.updateMonitor) {
+ this.bundleIds.add(bundleId);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Bundle installBundle(String location, InputStream input) throws BundleException {
+ /*
+ * TODO: use bundle install hook to close the window between the bundle being installed and it belonging to the region.
+ * See bug 333189.
+ */
+ Bundle bundle = this.systemBundleContext.installBundle(this.regionName + REGION_LOCATION_DELIMITER + location, input);
+ addBundle(bundle);
+ return bundle;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Bundle installBundle(String location) throws BundleException {
+ /*
+ * TODO: use bundle install hook to close the window between the bundle being installed and it belonging to the region.
+ * See bug 333189.
+ */
+ Bundle bundle = this.systemBundleContext.installBundle(this.regionName + REGION_LOCATION_DELIMITER + location, openBundleStream(location));
+ addBundle(bundle);
+ return bundle;
+ }
+
+ private InputStream openBundleStream(String location) throws BundleException {
+ String absoluteBundleUriString = getAbsoluteUriString(location);
+
+ try {
+ // Use the reference: scheme to obtain an InputStream for either a file or a directory.
+ return new URL(REFERENCE_SCHEME + absoluteBundleUriString).openStream();
+
+ } catch (MalformedURLException e) {
+ throw new BundleException("Location '" + location + "' resulted in an invalid bundle URI '" + absoluteBundleUriString + "'", e);
+ } catch (IOException e) {
+ throw new BundleException("Location '" + location + "' referred to an invalid bundle at URI '" + absoluteBundleUriString + "'", e);
+ }
+ }
+
+ private String getAbsoluteUriString(String location) throws BundleException {
+ if (!location.startsWith(FILE_SCHEME)) {
+ throw new BundleException("Cannot install from location '" + location + "' which did not start with '" + FILE_SCHEME + "'");
+ }
+
+ String filePath = location.substring(FILE_SCHEME.length());
+
+ return FILE_SCHEME + new File(filePath).getAbsolutePath();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Bundle getBundle(@NonNull String symbolicName, @NonNull Version version) {
+
+ // The following iteration is weakly consistent and will never throw ConcurrentModificationException.
+ for (long bundleId : this.bundleIds) {
+ Bundle bundle = this.systemBundleContext.getBundle(bundleId);
+ if (bundle != null && symbolicName.equals(bundle.getSymbolicName()) && version.equals(bundle.getVersion())) {
+ return bundle;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void connectRegion(Region tailRegion, RegionFilter filter) throws BundleException {
+ synchronized (this.updateMonitor) {
+ this.regionDigraph.connect(this, filter, tailRegion);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean contains(Bundle bundle) {
+ return this.bundleIds.contains(bundle.getBundleId());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.regionName.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof BundleIdBasedRegion)) {
+ return false;
+ }
+ BundleIdBasedRegion other = (BundleIdBasedRegion) obj;
+ return this.regionName.equals(other.regionName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean contains(long bundleId) {
+ return this.bundleIds.contains(bundleId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeBundle(Bundle bundle) {
+ removeBundle(bundle.getBundleId());
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeBundle(long bundleId) {
+ synchronized (this.updateMonitor) {
+ this.bundleIds.remove(bundleId);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getName();
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/IndeterminateRegionException.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/IndeterminateRegionException.java
new file mode 100644
index 00000000..e2109551
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/IndeterminateRegionException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+/**
+ * {@link IndeterminateRegionException} is thrown when the region of a bundle cannot be determined.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread safe.
+ *
+ */
+public abstract class IndeterminateRegionException extends Exception {
+
+ private static final long serialVersionUID = 76745737151453L;
+
+ /**
+ * Construct an {@link IndeterminateRegionException} for the given bundle.
+ *
+ * @param bundleId the id of the bundle whose region cannot be determined
+ */
+ public IndeterminateRegionException(String message) {
+ super(message);
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java
index e737cd2c..f2f4d4f7 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java
@@ -11,30 +11,157 @@
package org.eclipse.virgo.kernel.osgi.region;
+import java.io.InputStream;
+
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
/**
- * A region is an encapsulated OSGi framework. Regions are isolated from each other except by explicitly shared packages
- * and services that are defined when the region is created.
+ * A <i>region</i> is a subset of the bundles of an OSGi framework. A regions is "weakly" isolated from other regions
+ * except that is has full visibility of certain (subject to a {@link RegionFilter}) bundles, packages, and services
+ * from other regions to which it is connected. However a bundle running in a region is not protected from discovering
+ * bundles in other regions, e.g. by following wires using Wire Admin or similar services, so this is why regions are
+ * only weakly isolated from each other.
* <p />
*
* <strong>Concurrent Semantics</strong><br />
*
- * Implementations must be threadsafe.
+ * Implementations must be thread safe.
*
*/
public interface Region {
/**
- * @return the name of the region
+ * Returns the name of the region.
+ *
+ * @return the region name
*/
String getName();
-
+
+ /**
+ * Associates a given bundle, which has therefore already been installed, with this region.
+ * <p>
+ * This method is typically used to associate the system bundle with a region. Note that the system bundle is not
+ * treated specially and in order to be fully visible in a region, it must either be associated with the region or
+ * imported from another region via a connection.
+ * <p>
+ * If the bundle is already associated with this region, takes no action and returns normally.
+ * <p>
+ * If the bundle is already associated with another region, throws BundleException with exception type
+ * INVALID_OPERATION.
+ * <p>
+ * If the bundle has the same bundle symbolic name and version as a bundle already present in the region or as a
+ * bundle import specified on a connection to another region, then BundleException with exception type
+ * DUPLICATE_BUNDLE_ERROR is thrown.
+ *
+ * @param bundle the bundle to be associated with this region
+ * @throws BundleException if the bundle cannot be associated with the region
+ */
+ void addBundle(Bundle bundle) throws BundleException;
+
+ /**
+ * Associates the given bundle id with this region. If the given bundle id is already associated with this region,
+ * this is not an error and there is no effect.
+ * <p>
+ * This is useful when manipulating offline resolver states and bundle descriptions which do not correspond to
+ * bundles.
+ *
+ * @param bundleId the bundle id to be associated with this region
+ */
+ void addBundle(long bundleId);
+
/**
- * Returns a {@link BundleContext} that can be used to access the encapsulated OSGi framework.
+ * Installs a bundle and associates the bundle with this region. The bundle's location will have the region name
+ * prepended to the given location to ensure the location is unique across regions.
+ * <p>
+ * If the bundle has the same bundle symbolic name and version as a bundle already present in the region or as a
+ * bundle import specified on a connection to another region, then BundleException with exception type
+ * DUPLICATE_BUNDLE_ERROR is thrown.
*
- * @return a <code>BundleContext</code>
+ * @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)
*/
- BundleContext getBundleContext();
-
+ Bundle installBundle(String location, InputStream input) throws BundleException;
+
+ /**
+ * Installs a bundle and associates the bundle with this region. The bundle's location will have the region name
+ * prepended to the given location to ensure the location is unique across regions.
+ * <p>
+ * If the bundle has the same bundle symbolic name and version as a bundle already present in the region or as a
+ * bundle import specified on a connection to another region, then BundleException with exception type
+ * DUPLICATE_BUNDLE_ERROR is thrown.
+ *
+ *
+ * @param location the bundle location string
+ * @return the installed Bundle
+ * @throws BundleException if the install fails
+ * @see BundleContext#installBundle(String)
+ */
+ Bundle installBundle(String location) throws BundleException;
+
+ /**
+ * Returns <code>true</code> if and only if the given bundle belongs to this region.
+ *
+ * @param bundle a {@link Bundle}
+ * @return <code>true</code> if the given bundle belongs to this region and <code>false</code> otherwise
+ */
+ boolean contains(Bundle bundle);
+
+ /**
+ * Returns <code>true</code> if and only if a bundle with the given bundle id belongs to this region.
+ *
+ * @param bundleId a bundle id
+ * @return <code>true</code> if a bundle with the given bundle id belongs to this region and <code>false</code>
+ * otherwise
+ */
+ boolean contains(long bundleId);
+
+ /**
+ * Get the bundle in this region with the given symbolic name and version.
+ *
+ * @param symbolicName
+ * @param version
+ * @return the bundle or <code>null</code> if there is no such bundle
+ */
+ Bundle getBundle(String symbolicName, Version version);
+
+ /**
+ * Connects this region to the given tail region and associates the given {@link RegionFilter} with the connection.
+ * This region may then, subject to the region filter, see bundles, packages, and services visible in the tail
+ * region.
+ * <p>
+ * If the filter allows the same bundle symbolic name and version as a bundle already present in this region or a
+ * filter connecting this region to a region other than the tail region, then BundleException with exception type
+ * DUPLICATE_BUNDLE_ERROR is thrown.
+ * <p>
+ * If the given source region is already connected to the given tail region, then BundleException with exception
+ * type UNSUPPORTED_OPERATION is thrown.
+ *
+ * @param tailRegion the region to connect this region to
+ * @param filter a {@link RegionFilter} which controls what is visible across the connection
+ * @throws BundleException if the connection was not created
+ */
+ void connectRegion(Region tailRegion, RegionFilter filter) throws BundleException;
+
+ /**
+ * Removes the given bundle from this region. If the given bundle does not belong to this region, this is not an
+ * error and there is no effect.
+ *
+ * @param bundle the bundle to be removed
+ */
+ void removeBundle(Bundle bundle);
+
+ /**
+ * Removes the given bundle id from this region. If the given bundle id is not associated with this region, this is
+ * not an error and there is no effect.
+ *
+ * @param bundleId the bundle id to be removed
+ */
+ void removeBundle(long bundleId);
+
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java
new file mode 100644
index 00000000..c62708fc
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+/**
+ * {@link RegionDigraph} is a <a href="http://en.wikipedia.org/wiki/Directed_graph">directed graph</a>, or
+ * <i>digraph</i>, of {@link Region Regions}. The regions form the nodes of the graph and the edges connect regions to
+ * other regions.
+ * <p>
+ * Each edge (r, s) of the digraph is directed from region r, known as the <i>tail</i> of the edge, to region s, known
+ * as the <i>head</i> of the edge.
+ * <p>
+ * Each edge is associated with a {@link RegionFilter}, making the digraph a <i>labelled</i> digraph. The region filter
+ * for edge (r, s) allows region r to see certain bundles, packages, and services visible in region s.
+ * <p>
+ * Although the digraph may contain cycles it does not contain any <i>loops</i> which are edges of the form (r, r) for
+ * some region r. Loopless digraphs are known as <i>simple</i> digraphs. So the digraph is a simple, labelled digraph.
+ * <p>
+ * The region digraph extends <code>Iterable<Region></code> and so a foreach statement may be used to iterate over (a
+ * snapshot of) the regions in the digraph, e.g.
+ *
+ * <pre>
+ * for (Region r : regionDigraph) {
+ * ...
+ * }
+ * </pre>
+ * <p>
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations of this interface must be thread safe.
+ *
+ */
+public interface RegionDigraph extends Iterable<Region> {
+
+ public interface FilteredRegion {
+
+ Region getRegion();
+
+ RegionFilter getFilter();
+ }
+
+ /**
+ * Adds the given {@link Region} to the digraph.
+ *
+ * @param region the region to be added
+ */
+ void addRegion(Region region);
+
+ /**
+ * Removes the given {@link Region} from the digraph along with any edges which have the given region as head or
+ * tail. If the given region is not present in the digraph, this is not an error and there is no effect.
+ *
+ * @param coregion the {@link Region} to be removed
+ */
+ void removeRegion(Region coregion);
+
+ /**
+ * Gets the {@link Region} in the digraph with the given name.
+ *
+ * @param regionName the name of the region
+ * @return the {@link Region} or <code>null</code> if no such region is present in the digraph
+ */
+ Region getRegion(String regionName);
+
+ /**
+ * Gets the {@link Region} in the digraph containing the given bundle.
+ *
+ * @param bundle the bundle to search for
+ * @return the {@link Region} which contains the given bundle or <code>null</code> if there is no such region
+ */
+ Region getRegion(Bundle bundle);
+
+ /**
+ * Gets the {@link Region} in the digraph containing a bundle with the given bundle id.
+ *
+ * @param bundleId the bundleId of the bundle to search for
+ * @return the {@link Region} which contains a bundle with the given bundle or <code>null</code> if there is no such
+ * region
+ */
+ Region getRegion(long bundleId);
+
+ /**
+ * Connects a given tail region to a given head region via an edge labelled with the given {@link RegionFilter}. The
+ * tail region may then, subject to the region filter, see bundles, packages, and services visible in the head
+ * region.
+ * <p>
+ * The given head and tail regions are added to the digraph if they are not already present.
+ * <p>
+ * If the filter allows the same bundle symbolic name and version as a bundle already present in the tail region or
+ * as a filter connecting the tail region to a region other than the head region, then BundleException with
+ * exception type DUPLICATE_BUNDLE_ERROR is thrown. This ensures that bundles visible in a region are uniquely
+ * identified by the combination of bundle symbolic name and bundle version.
+ * <p>
+ * If the given tail region is already connected to the given head region, then BundleException with exception type
+ * UNSUPPORTED_OPERATION is thrown.
+ * <p>
+ * If the given head and the given tail are identical, then BundleException with exception type
+ * UNSUPPORTED_OPERATION is thrown.
+ *
+ * @param tailRegion the region at the tail of the new edge
+ * @param filter a {@link RegionFilter} which labels the new edge
+ * @param headRegion the region at the head of the new edge
+ * @throws BundleException if the edge was not created
+ */
+ void connect(Region tailRegion, RegionFilter filter, Region headRegion) throws BundleException;
+
+ /**
+ * Gets a {@link Set} containing a snapshot of the {@link FilteredRegion FilteredRegions} attached to the given tail
+ * region.
+ *
+ * @param tailRegion the tail region whose edges are gotten
+ * @return a {@link Set} of {@link FilteredRegion FilteredRegions} of head regions and region filters
+ */
+ Set<FilteredRegion> getEdges(Region tailRegion);
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java
new file mode 100644
index 00000000..05ebc2a4
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+import java.util.Dictionary;
+import java.util.Map;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+
+/**
+ * A {@link RegionFilter} is associated with a connection from one region to another and determines the bundles,
+ * packages, and services which are visible across the connection.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations must be thread safe.
+ *
+ */
+public interface RegionFilter {
+
+ public static final RegionPackageImportPolicy ALL_PACKAGES = new RegionPackageImportPolicy() {
+
+ @Override
+ public boolean isImported(String packageName, Map<String, Object> attributes, Map<String, String> directives) {
+ return true;
+ }
+ };
+
+ public static final Filter ALL_SERVICES = new Filter() {
+
+ @Override
+ public boolean match(ServiceReference<?> reference) {
+ return true;
+ }
+
+ @Override
+ public boolean match(Dictionary<String, ?> dictionary) {
+ return true;
+ }
+
+ @Override
+ public boolean matchCase(Dictionary<String, ?> dictionary) {
+ return true;
+ }
+
+ @Override
+ public boolean matches(Map<String, ?> map) {
+ return true;
+ }
+ };
+
+ public static final RegionFilter TOP = new RegionFilter() {
+
+ @Override
+ public RegionFilter allowBundle(String bundleSymbolicName, Version bundleVersion) {
+ return this;
+ }
+
+ @Override
+ public boolean isBundleAllowed(String bundleSymbolicName, Version bundleVersion) {
+ return true;
+ }
+
+ @Override
+ public RegionFilter setPackageImportPolicy(RegionPackageImportPolicy packageImportPolicy) {
+ return this;
+ }
+
+ @Override
+ public RegionPackageImportPolicy getPackageImportPolicy() {
+ return ALL_PACKAGES;
+ }
+
+ @Override
+ public RegionFilter setServiceFilter(Filter serviceFilter) {
+ return this;
+ }
+
+ @Override
+ public Filter getServiceFilter() {
+ return ALL_SERVICES;
+ }
+ };
+
+ /**
+ * Allows a bundle with the given bundle symbolic name and version to be imported.
+ *
+ * Note that the system bundle has the OSGi defined symbolic name "system.bundle".
+ *
+ * @param bundleSymbolicName
+ * @param bundleVersion
+ * @return this {@link RegionFilter} for chaining purposes
+ */
+ RegionFilter allowBundle(String bundleSymbolicName, Version bundleVersion);
+
+ /**
+ * Determines whether this filter allows the bundle with the given symbolic name and version
+ *
+ * @param bundleSymbolicName the symbolic name of the bundle
+ * @param bundleVersion the {@link Version} of the bundle
+ * @return <code>true</code> if the bundle is allowed and <code>false</code>otherwise
+ */
+ boolean isBundleAllowed(String bundleSymbolicName, Version bundleVersion);
+
+ /**
+ * Sets the package import policy of this filter.
+ *
+ * @param packageImportPolicy
+ * @return this {@link RegionFilter} for chaining purposes
+ */
+ RegionFilter setPackageImportPolicy(RegionPackageImportPolicy packageImportPolicy);
+
+ /**
+ * Gets the package import policy of this filter.
+ *
+ * @return the package import policy or <code>null</code> if this has not been set
+ */
+ RegionPackageImportPolicy getPackageImportPolicy();
+
+ /**
+ * @param serviceFilter
+ * @return this {@link RegionFilter} for chaining purposes
+ * @see org.osgi.framework.Filter more information about service filters
+ */
+ RegionFilter setServiceFilter(Filter serviceFilter);
+
+ /**
+ * Gets the service filter of this filter.
+ *
+ * @return the service filter or <code>null</code> if this has not been set
+ */
+ Filter getServiceFilter();
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java
index 6e5eb844..54b4430d 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java
@@ -11,36 +11,24 @@
package org.eclipse.virgo.kernel.osgi.region;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
+import org.eclipse.virgo.kernel.osgi.region.hook.RegionBundleEventHook;
+import org.eclipse.virgo.kernel.osgi.region.hook.RegionBundleFindHook;
+import org.eclipse.virgo.kernel.osgi.region.hook.RegionResolverHookFactory;
+import org.eclipse.virgo.kernel.osgi.region.hook.RegionServiceEventHook;
+import org.eclipse.virgo.kernel.osgi.region.hook.RegionServiceFindHook;
+import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph;
+import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.launch.Framework;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.framework.CompositeBundle;
-import org.osgi.service.framework.CompositeBundleFactory;
-import org.osgi.service.framework.SurrogateBundle;
-
-import org.eclipse.virgo.osgi.launcher.parser.ArgumentParser;
-import org.eclipse.virgo.osgi.launcher.parser.BundleEntry;
-import org.eclipse.virgo.medic.eventlog.EventLogger;
-import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
-import org.eclipse.virgo.kernel.core.Shutdown;
-import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkLogEvents;
+import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.hooks.bundle.EventHook;
+import org.osgi.framework.hooks.bundle.FindHook;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
/**
* Creates and manages the user {@link Region regions}.
@@ -51,314 +39,140 @@ import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkLogEvents;
* Threadsafe.
*
*/
-@SuppressWarnings("deprecation")
final class RegionManager {
- private static final String USER_REGION_CONFIGURATION_PID = "org.eclipse.virgo.kernel.userregion";
-
- private static final String PLUGGABLE_CLASS_LOADING_HOOK_CLASS_NAME = "org.eclipse.virgo.osgi.extensions.equinox.hooks.PluggableClassLoadingHook";
-
- private static final String USER_REGION_BASE_BUNDLES_PROPERTY = "baseBundles";
-
- private static final String USER_REGION_PACKAGE_IMPORTS_PROPERTY = "packageImports";
-
- private static final String USER_REGION_SERVICE_IMPORTS_PROPERTY = "serviceImports";
-
- private static final String USER_REGION_SERVICE_EXPORTS_PROPERTY = "serviceExports";
-
- private static final String USER_REGION_PROPERTIES_PROPERTY = "inheritedFrameworkProperties";
-
- private static final String REGION_USER = "org.eclipse.virgo.region.user";
-
- private static final String EVENT_REGION_STARTING = "org/eclipse/virgo/kernel/region/STARTING";
-
- private static final String EVENT_PROPERTY_REGION_BUNDLECONTEXT = "region.bundleContext";
+ private static final String REGION_KERNEL = "org.eclipse.virgo.region.kernel";
private final ServiceRegistrationTracker tracker = new ServiceRegistrationTracker();
private final BundleContext bundleContext;
- private final CompositeBundleFactory compositeBundleFactory;
-
- private final ArgumentParser parser = new ArgumentParser();
-
- private final EventAdmin eventAdmin;
-
- private final ServiceFactory<EventLogger> eventLoggerServiceFactory;
-
- private volatile Framework childFramework;
-
- private Dictionary<String, String> userRegionProperties;
-
- private String regionBundles;
-
- private String regionImports;
-
- private String regionServiceImports;
-
- private String regionServiceExports;
-
- private String regionInheritedProperties;
-
- public RegionManager(BundleContext bundleContext, CompositeBundleFactory compositeBundleFactory, EventAdmin eventAdmin,
- ServiceFactory<EventLogger> eventLoggerServiceFactory, ConfigurationAdmin configAdmin, EventLogger eventLogger, Shutdown shutdown) {
+ public RegionManager(BundleContext bundleContext) {
this.bundleContext = bundleContext;
- this.compositeBundleFactory = compositeBundleFactory;
- this.eventAdmin = eventAdmin;
- this.eventLoggerServiceFactory = eventLoggerServiceFactory;
- getRegionConfiguration(configAdmin, eventLogger, shutdown);
- }
-
- private void getRegionConfiguration(ConfigurationAdmin configAdmin, EventLogger eventLogger, Shutdown shutdown) {
- try {
- Configuration config = configAdmin.getConfiguration(USER_REGION_CONFIGURATION_PID, null);
-
- @SuppressWarnings("unchecked")
- Dictionary<String, String> properties = (Dictionary<String, String>) config.getProperties();
-
- if (properties != null) {
- this.userRegionProperties = properties;
- this.regionBundles = properties.get(USER_REGION_BASE_BUNDLES_PROPERTY);
- this.regionImports = properties.get(USER_REGION_PACKAGE_IMPORTS_PROPERTY);
- this.regionServiceImports = properties.get(USER_REGION_SERVICE_IMPORTS_PROPERTY);
- this.regionServiceExports = properties.get(USER_REGION_SERVICE_EXPORTS_PROPERTY);
- this.regionInheritedProperties = properties.get(USER_REGION_PROPERTIES_PROPERTY);
- } else {
- eventLogger.log(OsgiFrameworkLogEvents.USER_REGION_CONFIGURATION_UNAVAILABLE);
- shutdown.immediateShutdown();
- }
- } catch (Exception e) {
- eventLogger.log(OsgiFrameworkLogEvents.USER_REGION_CONFIGURATION_UNAVAILABLE, e);
- shutdown.immediateShutdown();
- }
}
public void start() throws BundleException {
- createAndPublishUserRegion();
- }
-
- private void createAndPublishUserRegion() throws BundleException {
-
- CompositeBundle compositeBundle = this.compositeBundleFactory.installCompositeBundle(createChildFrameworkConfig(), REGION_USER,
- createCompositeBundleManifest());
-
- childFramework = compositeBundle.getCompositeFramework();
- compositeBundle.start();
- childFramework.start();
-
- SurrogateBundle surrogateBundle = compositeBundle.getSurrogateBundle();
- BundleContext surrogateBundleContext = surrogateBundle.getBundleContext();
-
- Map<String, Object> properties = new HashMap<String, Object>();
- properties.put(EVENT_PROPERTY_REGION_BUNDLECONTEXT, surrogateBundleContext);
- this.eventAdmin.sendEvent(new Event(EVENT_REGION_STARTING, properties));
-
- setUserRegionBundleParentClassLoader(surrogateBundleContext);
-
- registerEventLoggerServiceFactory(surrogateBundleContext);
-
- initialiseUserRegionBundles(surrogateBundleContext);
+ RegionDigraph regionDigraph = createRegionDigraph();
+ registerRegionHooks(regionDigraph);
+ }
+
+ private RegionDigraph createRegionDigraph() throws BundleException {
+ RegionDigraph regionDigraph = new StandardRegionDigraph();
+ Region kernelRegion = createKernelRegion(regionDigraph);
+ registerRegionDigraph(regionDigraph, this.bundleContext);
+ createBundleListener(regionDigraph, kernelRegion);
+ return regionDigraph;
+ }
+
+ private void createBundleListener(final RegionDigraph regionDigraph, final Region kernelRegion) {
+ BundleContext systemBundleContext = getSystemBundleContext();
+ systemBundleContext.addBundleListener(new SynchronousBundleListener() {
+
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ Bundle bundle = event.getBundle();
+ switch (event.getType()) {
+ case BundleEvent.INSTALLED:
+ Bundle originBundle = event.getOrigin();
+ /*
+ * The system bundle is used, by BundleIdBasedRegion, to install bundles into arbitrary regions,
+ * so ignore it as an origin.
+ */
+ if (originBundle.getBundleId() != 0L) {
+ Region originRegion = regionDigraph.getRegion(originBundle);
+ if (originRegion != null) {
+ try {
+ originRegion.addBundle(bundle);
+ } catch (BundleException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ break;
+ case BundleEvent.UNINSTALLED:
+ Region region = regionDigraph.getRegion(bundle);
+ if (region != null) {
+ region.removeBundle(bundle);
+ }
+ break;
+ default:
+ break;
+ }
- registerRegionService(new ImmutableRegion(REGION_USER, surrogateBundleContext));
- publishUserRegionsBundleContext(surrogateBundleContext);
- }
+ }
+ });
- private void registerEventLoggerServiceFactory(BundleContext surrogateBundleContext) {
- surrogateBundleContext.registerService(EventLogger.class.getName(), this.eventLoggerServiceFactory, null);
}
- /**
- * @param surrogateBundleContext
- */
- private void publishUserRegionsBundleContext(BundleContext surrogateBundleContext) {
- Dictionary<String, String> properties = new Hashtable<String, String>();
- properties.put("org.eclipse.virgo.kernel.regionContext", "true");
- this.bundleContext.registerService(BundleContext.class.getName(), surrogateBundleContext, properties);
- }
+ private Region createKernelRegion(RegionDigraph regionDigraph) throws BundleException {
+ Region kernelRegion = new BundleIdBasedRegion(REGION_KERNEL, regionDigraph, getSystemBundleContext());
+ regionDigraph.addRegion(kernelRegion);
- private void setUserRegionBundleParentClassLoader(BundleContext surrogateBundleContext) throws BundleException {
- ClassLoader surrogateClassLoader = surrogateBundleContext.getClass().getClassLoader();
- try {
- setUserRegionHookBundleParentClassLoader(surrogateClassLoader);
- } catch (Exception e) {
- throw new BundleException("Error setting user region hook bundle parent class loader", e);
+ for (Bundle bundle : this.bundleContext.getBundles()) {
+ kernelRegion.addBundle(bundle);
}
- }
-
- private void setUserRegionHookBundleParentClassLoader(ClassLoader parentClassLoader) throws ClassNotFoundException, SecurityException,
- NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
- Class<?> pluggableClassLoadingHookClass = parentClassLoader.loadClass(PLUGGABLE_CLASS_LOADING_HOOK_CLASS_NAME);
- Object pluggableClassLoadingHookInstance = invokeGetInstance(pluggableClassLoadingHookClass);
+ registerRegionService(kernelRegion);
- invokeSetParent(pluggableClassLoadingHookClass, pluggableClassLoadingHookInstance, parentClassLoader);
+ return kernelRegion;
}
- private Object invokeGetInstance(Class<?> pluggableClassLoadingHookClass) throws SecurityException, NoSuchMethodException,
- IllegalArgumentException, IllegalAccessException, InvocationTargetException {
- Class<?>[] parmTypes = {};
- Method getInstanceMethod = pluggableClassLoadingHookClass.getDeclaredMethod("getInstance", parmTypes);
- Object[] args = {};
- return getInstanceMethod.invoke(null, args);
- }
-
- private void invokeSetParent(Class<?> pluggableClassLoadingHookClass, Object pluggableClassLoadingHookInstance, ClassLoader parentClassLoader)
- throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- Class<?>[] parmTypes = { ClassLoader.class };
- Method setParentMethod = pluggableClassLoadingHookClass.getDeclaredMethod("setBundleClassLoaderParent", parmTypes);
- Object[] args = { parentClassLoader };
- setParentMethod.invoke(pluggableClassLoadingHookInstance, args);
- }
+ private void registerRegionHooks(RegionDigraph regionDigraph) {
+ registerResolverHookFactory(new RegionResolverHookFactory(regionDigraph));
- private Map<String, String> createChildFrameworkConfig() {
- HashMap<String, String> frameworkConfig = new HashMap<String, String>();
+ RegionBundleFindHook bundleFindHook = new RegionBundleFindHook(regionDigraph);
- setUserConfiguredUserRegionProperties(frameworkConfig);
+ registerBundleFindHook(bundleFindHook);
- if (this.regionInheritedProperties != null) {
- String[] inheritedProperties = this.regionInheritedProperties.split(",");
- for (String property : inheritedProperties) {
- propagatePropertyToUserRegion(frameworkConfig, property);
- }
- }
+ registerBundleEventHook(new RegionBundleEventHook(bundleFindHook));
- String userRegionImportsProperty = this.bundleContext.getProperty(USER_REGION_PROPERTIES_PROPERTY);
- if (userRegionImportsProperty != null) {
- for (String property : userRegionImportsProperty.split(",")) {
- propagatePropertyToUserRegion(frameworkConfig, property);
- }
- }
+ RegionServiceFindHook serviceFindHook = new RegionServiceFindHook(regionDigraph);
- return frameworkConfig;
- }
+ registerServiceFindHook(serviceFindHook);
- private void setUserConfiguredUserRegionProperties(HashMap<String, String> frameworkConfig) {
- if (this.userRegionProperties != null) {
- Enumeration<String> keys = this.userRegionProperties.keys();
- while (keys.hasMoreElements()) {
- String propertyName = keys.nextElement();
- String propertyValue = this.userRegionProperties.get(propertyName);
- frameworkConfig.put(propertyName, propertyValue);
- }
- }
+ registerServiceEventHook(new RegionServiceEventHook(serviceFindHook));
}
- private void propagatePropertyToUserRegion(HashMap<String, String> frameworkConfig, String propertyName) {
- String propertyValue = this.bundleContext.getProperty(propertyName);
- if (propertyValue != null) {
- frameworkConfig.put(propertyName, propertyValue);
- }
+ private BundleContext getSystemBundleContext() {
+ return this.bundleContext.getBundle(0L).getBundleContext();
}
- private Map<String, String> createCompositeBundleManifest() {
- Map<String, String> compositeManifest = new HashMap<String, String>();
-
- compositeManifest.put(Constants.BUNDLE_SYMBOLICNAME, REGION_USER);
-
- String userRegionImportsProperty = this.regionImports != null ? this.regionImports
- : this.bundleContext.getProperty(USER_REGION_PACKAGE_IMPORTS_PROPERTY);
- if (userRegionImportsProperty != null) {
- String expandedUserRegionImportsProperty = PackageImportWildcardExpander.expandPackageImportsWildcards(userRegionImportsProperty,
- this.bundleContext);
- compositeManifest.put(Constants.IMPORT_PACKAGE, expandedUserRegionImportsProperty);
+ private void registerRegionDigraph(RegionDigraph regionDigraph, BundleContext userRegionBundleContext) {
+ this.tracker.track(this.bundleContext.registerService(RegionDigraph.class, regionDigraph, null));
+ if (userRegionBundleContext != null) {
+ this.tracker.track(userRegionBundleContext.registerService(RegionDigraph.class, regionDigraph, null));
}
-
- configureServiceImportFilter(compositeManifest);
- configureServiceExportFilter(compositeManifest);
-
- return compositeManifest;
}
- private void configureServiceImportFilter(Map<String, String> compositeManifest) {
- String[] serviceImports = splitServices(this.regionServiceImports);
- if (serviceImports != null) {
- compositeManifest.put(CompositeBundleFactory.COMPOSITE_SERVICE_FILTER_IMPORT, createObjectClassesServiceFilter(serviceImports));
- }
+ private void registerServiceFindHook(org.osgi.framework.hooks.service.FindHook serviceFindHook) {
+ this.tracker.track(this.bundleContext.registerService(org.osgi.framework.hooks.service.FindHook.class, serviceFindHook, null));
}
- private void configureServiceExportFilter(Map<String, String> compositeManifest) {
- String[] serviceExports = splitServices(this.regionServiceExports);
- if (serviceExports != null) {
- compositeManifest.put(CompositeBundleFactory.COMPOSITE_SERVICE_FILTER_EXPORT, createObjectClassesServiceFilter(serviceExports));
- }
+ private void registerServiceEventHook(org.osgi.framework.hooks.service.EventHook serviceEventHook) {
+ this.tracker.track(this.bundleContext.registerService(org.osgi.framework.hooks.service.EventHook.class, serviceEventHook, null));
}
- private String[] splitServices(String serviceString) {
- String[] services = null;
- if (serviceString != null) {
- services = serviceString.split(",");
- }
- return services;
+ private void registerBundleFindHook(FindHook findHook) {
+ this.tracker.track(this.bundleContext.registerService(FindHook.class, findHook, null));
}
- private String createObjectClassesServiceFilter(String[] serviceClassNames) {
- StringBuffer importFilter = new StringBuffer();
- importFilter.append("(|");
- for (String className : serviceClassNames) {
- importFilter.append(createObjectClassFilter(className));
- }
- importFilter.append(")");
- return importFilter.toString();
- }
+ private void registerBundleEventHook(EventHook eventHook) {
+ this.tracker.track(this.bundleContext.registerService(EventHook.class, eventHook, null));
- private String createObjectClassFilter(String className) {
- return "(objectClass=" + className + ")";
}
- private void initialiseUserRegionBundles(BundleContext surrogateBundleContext) throws BundleException {
- String userRegionBundlesProperty = this.regionBundles != null ? this.regionBundles
- : this.bundleContext.getProperty(USER_REGION_BASE_BUNDLES_PROPERTY);
-
- if (userRegionBundlesProperty != null) {
- List<Bundle> bundlesToStart = new ArrayList<Bundle>();
-
- for (BundleEntry entry : this.parser.parseBundleEntries(userRegionBundlesProperty)) {
- Bundle bundle = surrogateBundleContext.installBundle(entry.getURI().toString());
-
- if (entry.isAutoStart()) {
- bundlesToStart.add(bundle);
- }
- }
-
- for (Bundle bundle : bundlesToStart) {
- try {
- bundle.start();
- } catch (BundleException e) {
- throw new BundleException("Failed to start bundle " + bundle.getSymbolicName() + " " + bundle.getVersion(), e);
- }
- }
-
- }
+ private void registerResolverHookFactory(ResolverHookFactory resolverHookFactory) {
+ this.tracker.track(this.bundleContext.registerService(ResolverHookFactory.class, resolverHookFactory, null));
}
private void registerRegionService(Region region) {
Dictionary<String, String> props = new Hashtable<String, String>();
props.put("org.eclipse.virgo.kernel.region.name", region.getName());
- this.tracker.track(this.bundleContext.registerService(Region.class.getName(), region, props));
+ this.tracker.track(this.bundleContext.registerService(Region.class, region, props));
}
public void stop() {
this.tracker.unregisterAll();
}
- private static class ImmutableRegion implements Region {
-
- private final String name;
-
- private final BundleContext bundleContext;
-
- public ImmutableRegion(String name, BundleContext bundleContext) {
- this.name = name;
- this.bundleContext = bundleContext;
- }
-
- public String getName() {
- return name;
- }
-
- public BundleContext getBundleContext() {
- return this.bundleContext;
- }
-
- }
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java
new file mode 100644
index 00000000..ff1abc83
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+import java.util.Map;
+
+/**
+ * {@link RegionPackageImportPolicy} determines the package names that are imported into a region.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations of this interface must be thread safe.
+ *
+ */
+public interface RegionPackageImportPolicy {
+
+ /**
+ * Returns <code>true</code> if and only if the package with the specified name exported with the specified
+ * attributes and directives is imported into the region.
+ *
+ * @param packageName the name of the package
+ * @param attributes the package's export attributes
+ * @param directives the package's export directives
+ * @return <code>true</code> if and only if the package is imported
+ */
+ boolean isImported(String packageName, Map<String, Object> attributes, Map<String, String> directives);
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionSpanningException.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionSpanningException.java
new file mode 100644
index 00000000..fa5d4755
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionSpanningException.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * {@link RegionSpanningException} is thrown when an attempt is made to determine the region a bundle belongs when the
+ * bundle spans multiple regions. The principle example is the system bundle which spans all regions.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread safe.
+ *
+ */
+public class RegionSpanningException extends IndeterminateRegionException {
+
+
+ private static final long serialVersionUID = 545234523452345L;
+
+ /**
+ * Construct a {@link RegionSpanningException} for the given bundle.
+ *
+ * @param bundleId the id of the bundle whose region cannot be uniquely determined
+ */
+ public RegionSpanningException(Long bundleId) {
+ super("Bundle with id '" + bundleId + "' spans multiple regions");
+ }
+
+ /**
+ * Construct a {@link RegionSpanningException} for the given bundle.
+ *
+ * @param bundle the bundle whose region cannot be uniquely determined
+ */
+ public RegionSpanningException(Bundle bundle) {
+ super("Bundle '" + bundle + "' spans multiple regions");
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java
new file mode 100644
index 00000000..28132a07
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.virgo.util.math.OrderedPair;
+import org.osgi.framework.Filter;
+import org.osgi.framework.Version;
+
+/**
+ * {@link StandardRegionFilter} is the default implementation of {@link RegionFilter}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+public final class StandardRegionFilter implements RegionFilter {
+
+ private final Object monitor = new Object();
+
+ private final Set<OrderedPair<String, Version>> allowedBundles = new HashSet<OrderedPair<String, Version>>();
+
+ private RegionPackageImportPolicy packageImportPolicy;
+
+ private Filter serviceFilter;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public RegionFilter allowBundle(String bundleSymbolicName, Version bundleVersion) {
+ synchronized (this.monitor) {
+ this.allowedBundles.add(createPair(bundleSymbolicName, bundleVersion));
+ }
+ return this;
+ }
+
+ private OrderedPair<String, Version> createPair(String bundleSymbolicName, Version bundleVersion) {
+ return new OrderedPair<String, Version>(bundleSymbolicName, bundleVersion);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public RegionFilter setServiceFilter(Filter serviceFilter) {
+ synchronized (this.monitor) {
+ this.serviceFilter = serviceFilter;
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Filter getServiceFilter() {
+ synchronized (this.monitor) {
+ return this.serviceFilter;
+ }
+ }
+
+ @Override
+ public RegionPackageImportPolicy getPackageImportPolicy() {
+ synchronized (this.monitor) {
+ return this.packageImportPolicy;
+ }
+ }
+
+ @Override
+ public RegionFilter setPackageImportPolicy(RegionPackageImportPolicy packageImportPolicy) {
+ synchronized (this.monitor) {
+ this.packageImportPolicy = packageImportPolicy;
+ }
+ return this;
+ }
+
+ @Override
+ public boolean isBundleAllowed(String bundleSymbolicName, Version bundleVersion) {
+ synchronized (this.monitor) {
+ return this.allowedBundles.contains(createPair(bundleSymbolicName, bundleVersion));
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHook.java
new file mode 100644
index 00000000..dbd55100
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHook.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the Eclipse Virgo project.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ */
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.hooks.bundle.EventHook;
+import org.osgi.framework.hooks.bundle.FindHook;
+
+/**
+ * {@link RegionBundleEventHook} manages the visibility of bundle events across regions according to the
+ * {@link RegionDigraph}.
+ * <p>
+ * The current implementation delegates to {@link RegionBundleFindHook}. This is likely to perform adequately
+ * because of the low frequency of bundle events and the typically small number of bundle listeners.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+public final class RegionBundleEventHook implements EventHook {
+
+ private final FindHook bundleFindHook;
+
+ public RegionBundleEventHook(FindHook bundleFindBook) {
+ this.bundleFindHook = bundleFindBook;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void event(BundleEvent event, Collection<BundleContext> contexts) {
+ Bundle eventBundle = event.getBundle();
+ Iterator<BundleContext> i = contexts.iterator();
+ while (i.hasNext()) {
+ if (!find(i.next(), eventBundle)) {
+ i.remove();
+ }
+ }
+ }
+
+ private boolean find(BundleContext finderBundleContext, Bundle candidateBundle) {
+ Set<Bundle> candidates = new HashSet<Bundle>();
+ candidates.add(candidateBundle);
+ this.bundleFindHook.find(finderBundleContext, candidates);
+ return !candidates.isEmpty();
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java
new file mode 100644
index 00000000..f126a577
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.hooks.bundle.FindHook;
+
+/**
+ * {@link RegionBundleFindHook} manages the visibility of bundles across regions according to the {@link RegionDigraph}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+public final class RegionBundleFindHook implements FindHook {
+
+ private final RegionDigraph regionDigraph;
+
+ public RegionBundleFindHook(RegionDigraph regionDigraph) {
+ this.regionDigraph = regionDigraph;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void find(BundleContext context, Collection<Bundle> bundles) {
+ if (context.getBundle().getBundleId() == 0L) {
+ return;
+ }
+
+ Region finderRegion = getRegion(context);
+ if (finderRegion == null) {
+ bundles.clear();
+ return;
+ }
+
+ Set<Bundle> allowed = getAllowed(finderRegion, bundles, new HashSet<Region>());
+
+ bundles.retainAll(allowed);
+ }
+
+ private Set<Bundle> getAllowed(Region r, Collection<Bundle> bundles, Set<Region> path) {
+ Set<Bundle> allowed = new HashSet<Bundle>();
+
+ if (!path.contains(r)) {
+ allowBundlesInRegion(allowed, r, bundles);
+ allowImportedBundles(allowed, r, bundles, path);
+ }
+
+ return allowed;
+ }
+
+ private void allowImportedBundles(Set<Bundle> allowed, Region r, Collection<Bundle> bundles, Set<Region> path) {
+ for (FilteredRegion fr : this.regionDigraph.getEdges(r)) {
+ Set<Bundle> a = getAllowed(fr.getRegion(), bundles, extendPath(r, path));
+ filter(a, fr.getFilter());
+ allowed.addAll(a);
+ }
+ }
+
+ private void allowBundlesInRegion(Set<Bundle> allowed, Region r, Collection<Bundle> bundles) {
+ for (Bundle b : bundles) {
+ if (r.contains(b)) {
+ allowed.add(b);
+ }
+ }
+ }
+
+ private Set<Region> extendPath(Region r, Set<Region> path) {
+ Set<Region> newPath = new HashSet<Region>(path);
+ newPath.add(r);
+ return newPath;
+ }
+
+ private void filter(Set<Bundle> bundles, RegionFilter filter) {
+ Iterator<Bundle> i = bundles.iterator();
+ while (i.hasNext()) {
+ Bundle b = i.next();
+ if (!filter.isBundleAllowed(b.getSymbolicName(), b.getVersion())) {
+ i.remove();
+ }
+ }
+ }
+
+ private Region getRegion(BundleContext context) {
+ Bundle b = context.getBundle();
+ for (Region r : this.regionDigraph) {
+ if (r.contains(b)) {
+ return r;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java
new file mode 100644
index 00000000..4b934f56
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.osgi.internal.module.ResolverBundle;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy;
+import org.eclipse.virgo.kernel.serviceability.Assert;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.Capability;
+
+/**
+ * {@link RegionResolverHook} manages the visibility of bundles across regions according to the {@link RegionDigraph}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+final class RegionResolverHook implements ResolverHook {
+
+ private static final long INVALID_BUNDLE_ID = -1L;
+
+ private static final Boolean DEBUG = false;
+
+ private final RegionDigraph regionDigraph;
+
+ RegionResolverHook(RegionDigraph regionDigraph) {
+ this.regionDigraph = regionDigraph;
+ }
+
+ @Override
+ public void filterMatches(BundleRevision requirer, Collection<Capability> candidates) {
+ try {
+ if (DEBUG) {
+ debugEntry(requirer, candidates);
+ }
+
+ if (getBundleId(requirer) == 0L) {
+ return;
+ }
+
+ Region requirerRegion = getRegion(requirer);
+ if (requirerRegion == null) {
+ candidates.clear();
+ return;
+ }
+
+ Set<Capability> allowed = getAllowed(requirerRegion, candidates, new HashSet<Region>());
+
+ candidates.retainAll(allowed);
+ } finally {
+ if (DEBUG) {
+ debugExit(requirer, candidates);
+ }
+ }
+ }
+
+ private Region getRegion(BundleRevision bundleRevision) {
+ Bundle bundle = bundleRevision.getBundle();
+ if (bundle != null) {
+ return getRegion(bundle);
+ }
+ Long bundleId = getBundleId(bundleRevision);
+ return getRegion(bundleId);
+ }
+
+ private Region getRegion(Long bundleId) {
+ return this.regionDigraph.getRegion(bundleId);
+ }
+
+ private Long getBundleId(BundleRevision bundleRevision) {
+ // For testability, use the bundle revision's bundle before casting to ResolverBundle.
+ Bundle bundle = bundleRevision.getBundle();
+ if (bundle != null) {
+ return bundle.getBundleId();
+ }
+ if (bundleRevision instanceof ResolverBundle) {
+ ResolverBundle resolverBundle = (ResolverBundle) bundleRevision;
+ return resolverBundle.getBundleDescription().getBundleId();
+ }
+ Assert.isTrue(false, "Cannot determine bundle id of BundleRevision '%s'", bundleRevision);
+ return INVALID_BUNDLE_ID;
+ }
+
+ private Set<Capability> getAllowed(Region r, Collection<Capability> candidates, Set<Region> path) {
+ Set<Capability> allowed = new HashSet<Capability>();
+
+ if (!path.contains(r)) {
+ allowPackagesInRegion(allowed, r, candidates);
+ allowImportedPackages(allowed, r, candidates, path);
+ }
+
+ return allowed;
+ }
+
+ private void allowImportedPackages(Set<Capability> allowed, Region r, Collection<Capability> candidates, Set<Region> path) {
+ for (FilteredRegion fr : this.regionDigraph.getEdges(r)) {
+ Set<Capability> a = getAllowed(fr.getRegion(), candidates, extendPath(r, path));
+ filter(a, fr.getFilter());
+ allowed.addAll(a);
+ }
+ }
+
+ private void allowPackagesInRegion(Set<Capability> allowed, Region r, Collection<Capability> candidates) {
+ for (Capability b : candidates) {
+ if (r.equals(getRegion(b.getProviderRevision()))) {
+ allowed.add(b);
+ }
+ }
+ }
+
+ private Set<Region> extendPath(Region r, Set<Region> path) {
+ Set<Region> newPath = new HashSet<Region>(path);
+ newPath.add(r);
+ return newPath;
+ }
+
+ private void filter(Set<Capability> capabilities, RegionFilter filter) {
+ RegionPackageImportPolicy packageImportPolicy = filter.getPackageImportPolicy();
+ Iterator<Capability> i = capabilities.iterator();
+ while (i.hasNext()) {
+ Capability c = i.next();
+ String namespace = c.getNamespace();
+ if (Capability.PACKAGE_CAPABILITY.equals(namespace)) {
+ if (!packageImportPolicy.isImported((String) c.getAttributes().get(Capability.PACKAGE_CAPABILITY), c.getAttributes(),
+ c.getDirectives())) {
+ i.remove();
+ }
+ } else {
+ BundleRevision providerRevision = c.getProviderRevision();
+ if (!filter.isBundleAllowed(providerRevision.getSymbolicName(), providerRevision.getVersion())) {
+ i.remove();
+ }
+
+ }
+ }
+ }
+
+ private Region getRegion(Bundle bundle) {
+ for (Region r : this.regionDigraph) {
+ if (r.contains(bundle)) {
+ return r;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void end() {
+ }
+
+ @Override
+ public void filterResolvable(Collection<BundleRevision> candidates) {
+ }
+
+ @Override
+ public void filterSingletonCollisions(Capability singleton, Collection<Capability> collisionCandidates) {
+ }
+
+ private void debugEntry(BundleRevision requirer, Collection<Capability> candidates) {
+ System.out.println("Requirer: " + requirer.getSymbolicName() + "_" + requirer.getVersion() + "[" + getBundleId(requirer) + "]");
+ System.out.println(" Candidates: ");
+ Iterator<Capability> i = candidates.iterator();
+ while (i.hasNext()) {
+ Capability c = i.next();
+ String namespace = c.getNamespace();
+ if (Capability.PACKAGE_CAPABILITY.equals(namespace)) {
+ BundleRevision providerRevision = c.getProviderRevision();
+ String pkg = (String) c.getAttributes().get(Capability.PACKAGE_CAPABILITY);
+ System.out.println(" Package " + pkg + " from provider " + providerRevision.getSymbolicName() + "_"
+ + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]");
+ if (pkg.equals("slow")) {
+ System.out.println(">>> put breakpoint here <<<");
+ }
+ } else {
+ BundleRevision providerRevision = c.getProviderRevision();
+ System.out.println(" Bundle from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "["
+ + getBundleId(providerRevision) + "]");
+ }
+ }
+ }
+
+ private void debugExit(BundleRevision requirer, Collection<Capability> candidates) {
+ System.out.println(" Filtered candidates: ");
+ Iterator<Capability> i = candidates.iterator();
+ while (i.hasNext()) {
+ Capability c = i.next();
+ String namespace = c.getNamespace();
+ if (Capability.PACKAGE_CAPABILITY.equals(namespace)) {
+ BundleRevision providerRevision = c.getProviderRevision();
+ String pkg = (String) c.getAttributes().get(Capability.PACKAGE_CAPABILITY);
+ System.out.println(" Package " + pkg + " from provider " + providerRevision.getSymbolicName() + "_"
+ + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]");
+ if (pkg.equals("slow")) {
+ System.out.println(">>> put breakpoint here <<<");
+ }
+ } else {
+ BundleRevision providerRevision = c.getProviderRevision();
+ System.out.println(" Bundle from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "["
+ + getBundleId(providerRevision) + "]");
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookFactory.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookFactory.java
new file mode 100644
index 00000000..57815cf3
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookFactory.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.osgi.framework.wiring.BundleRevision;
+
+/**
+ * {@link RegionResolverHook} constructs an instance of {@link RegionResolverHook} for a particular resolution
+ * operation.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread safe.
+ */
+public final class RegionResolverHookFactory implements ResolverHookFactory {
+
+ private final RegionDigraph regionDigraph;
+
+ public RegionResolverHookFactory(RegionDigraph regionDigraph) {
+ this.regionDigraph = regionDigraph;
+ }
+
+ @Override
+ public ResolverHook begin(Collection<BundleRevision> triggers) {
+ return new RegionResolverHook(this.regionDigraph);
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java
new file mode 100644
index 00000000..0c1e9279
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the Eclipse Virgo project.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ */
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.service.EventHook;
+import org.osgi.framework.hooks.service.FindHook;
+
+/**
+ * {@link RegionServiceEventHook} manages the visibility of service events across regions according to the
+ * {@link RegionDigraph}.
+ * <p>
+ * The current implementation delegates to {@link RegionServiceFindHook}. This is likely to perform adequately because
+ * of the relatively low frequency (compared to service lookups) of service events and the typically small number of
+ * service listeners.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+public final class RegionServiceEventHook implements EventHook {
+
+ private final FindHook serviceFindHook;
+
+ public RegionServiceEventHook(FindHook bundleFindBook) {
+ this.serviceFindHook = bundleFindBook;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void event(ServiceEvent event, Collection<BundleContext> contexts) {
+ ServiceReference<?> eventBundle = event.getServiceReference();
+ Iterator<BundleContext> i = contexts.iterator();
+ while (i.hasNext()) {
+ if (!find(i.next(), eventBundle)) {
+ i.remove();
+ }
+ }
+ }
+
+ private boolean find(BundleContext finderBundleContext, ServiceReference<?> candidateServiceReference) {
+ Set<ServiceReference<?>> candidates = new HashSet<ServiceReference<?>>();
+ candidates.add(candidateServiceReference);
+ this.serviceFindHook.find(finderBundleContext, "", "", false, candidates);
+ return !candidates.isEmpty();
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java
new file mode 100644
index 00000000..30cf3e18
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.service.FindHook;
+
+/**
+ * {@link RegionServiceFindHook} manages the visibility of services across regions according to the
+ * {@link RegionDigraph}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+public final class RegionServiceFindHook implements FindHook {
+
+ private final RegionDigraph regionDigraph;
+
+ public RegionServiceFindHook(RegionDigraph regionDigraph) {
+ this.regionDigraph = regionDigraph;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void find(BundleContext context, String name, String filter, boolean allServices, Collection<ServiceReference<?>> references) {
+ if (context.getBundle().getBundleId() == 0L) {
+ return;
+ }
+
+ Region finderRegion = getRegion(context);
+ if (finderRegion == null) {
+ references.clear();
+ return;
+ }
+
+ Set<ServiceReference<?>> allowed = getAllowed(finderRegion, references, new HashSet<Region>());
+
+ references.retainAll(allowed);
+ }
+
+ private Set<ServiceReference<?>> getAllowed(Region r, Collection<ServiceReference<?>> references, Set<Region> path) {
+ Set<ServiceReference<?>> allowed = new HashSet<ServiceReference<?>>();
+
+ if (!path.contains(r)) {
+ allowServiceReferencesInRegion(allowed, r, references);
+ allowImportedBundles(allowed, r, references, path);
+ }
+
+ return allowed;
+ }
+
+ private void allowImportedBundles(Set<ServiceReference<?>> allowed, Region r, Collection<ServiceReference<?>> references, Set<Region> path) {
+ for (FilteredRegion fr : this.regionDigraph.getEdges(r)) {
+ Set<ServiceReference<?>> a = getAllowed(fr.getRegion(), references, extendPath(r, path));
+ filter(a, fr.getFilter());
+ allowed.addAll(a);
+ }
+ }
+
+ private void allowServiceReferencesInRegion(Set<ServiceReference<?>> allowed, Region r, Collection<ServiceReference<?>> references) {
+ for (ServiceReference<?> b : references) {
+ if (r.contains(b.getBundle())) {
+ allowed.add(b);
+ }
+ }
+ }
+
+ private Set<Region> extendPath(Region r, Set<Region> path) {
+ Set<Region> newPath = new HashSet<Region>(path);
+ newPath.add(r);
+ return newPath;
+ }
+
+ private void filter(Set<ServiceReference<?>> references, RegionFilter filter) {
+ Filter serviceFilter = filter.getServiceFilter();
+ Iterator<ServiceReference<?>> i = references.iterator();
+ while (i.hasNext()) {
+ ServiceReference<?> sr = i.next();
+ if (!serviceFilter.match(sr)) {
+ i.remove();
+ }
+ }
+ }
+
+ private Region getRegion(BundleContext context) {
+ Bundle b = context.getBundle();
+ for (Region r : this.regionDigraph) {
+ if (r.contains(b)) {
+ return r;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java
new file mode 100644
index 00000000..e0a8ab42
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.internal;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.serviceability.NonNull;
+import org.eclipse.virgo.util.math.OrderedPair;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+/**
+ * {@link StandardRegionDigraph} is the default implementation of {@link RegionDigraph}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread safe.
+ *
+ */
+public final class StandardRegionDigraph implements RegionDigraph {
+
+ private final Object monitor = new Object();
+
+ private final Set<Region> regions = new HashSet<Region>();
+
+ private final Map<OrderedPair<Region, Region>, RegionFilter> filter = new HashMap<OrderedPair<Region, Region>, RegionFilter>();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void connect(@NonNull Region tailRegion, @NonNull RegionFilter filter, @NonNull Region headRegion) throws BundleException {
+ if (headRegion.equals(tailRegion)) {
+ throw new BundleException("Cannot connect region '" + headRegion + "' to itself", BundleException.UNSUPPORTED_OPERATION);
+ }
+ OrderedPair<Region, Region> nodePair = new OrderedPair<Region, Region>(tailRegion, headRegion);
+ synchronized (this.monitor) {
+ if (this.filter.containsKey(nodePair)) {
+ throw new BundleException("Region '" + tailRegion + "' is already connected to region '" + headRegion,
+ BundleException.UNSUPPORTED_OPERATION);
+ } else {
+ checkFilterDoesNotAllowExistingBundle(tailRegion, filter);
+ this.regions.add(tailRegion);
+ this.regions.add(headRegion);
+ this.filter.put(nodePair, filter);
+ }
+ }
+
+ }
+
+ private void checkFilterDoesNotAllowExistingBundle(Region tailRegion, RegionFilter filter) throws BundleException {
+ // TODO: enumerate the bundles in the region and check the filter does not allow any of them
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterator<Region> iterator() {
+ synchronized (this.monitor) {
+ Set<Region> snapshot = new HashSet<Region>(this.regions.size());
+ snapshot.addAll(this.regions);
+ return snapshot.iterator();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addRegion(Region region) {
+ synchronized (this.monitor) {
+ this.regions.add(region);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<FilteredRegion> getEdges(Region tailRegion) {
+ Set<FilteredRegion> edges = new HashSet<FilteredRegion>();
+ synchronized (this.monitor) {
+ Set<OrderedPair<Region, Region>> regionPairs = this.filter.keySet();
+ for (OrderedPair<Region, Region> regionPair : regionPairs) {
+ if (tailRegion.equals(regionPair.getFirst())) {
+ edges.add(new StandardFilteredRegion(regionPair.getSecond(), this.filter.get(regionPair)));
+ }
+ }
+ }
+ return edges;
+ }
+
+ private class StandardFilteredRegion implements FilteredRegion {
+
+ private Region region;
+
+ private RegionFilter regionFilter;
+
+ private StandardFilteredRegion(Region region, RegionFilter regionFilter) {
+ this.region = region;
+ this.regionFilter = regionFilter;
+ }
+
+ @Override
+ public Region getRegion() {
+ return this.region;
+ }
+
+ @Override
+ public RegionFilter getFilter() {
+ return this.regionFilter;
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Region getRegion(@NonNull String regionName) {
+ synchronized (this.monitor) {
+ for (Region region : this) {
+ if (regionName.equals(region.getName())) {
+ return region;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Region getRegion(Bundle bundle) {
+ synchronized (this.monitor) {
+ for (Region region : this) {
+ if (region.contains(bundle)) {
+ return region;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Region getRegion(long bundleId) {
+ synchronized (this.monitor) {
+ for (Region region : this) {
+ if (region.contains(bundleId)) {
+ return region;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeRegion(@NonNull Region coregion) {
+ synchronized (this.monitor) {
+ this.regions.remove(coregion);
+ Iterator<OrderedPair<Region, Region>> i = this.filter.keySet().iterator();
+ while (i.hasNext()) {
+ OrderedPair<Region, Region> regionPair = i.next();
+ if (coregion.equals(regionPair.getFirst()) || coregion.equals(regionPair.getSecond())) {
+ i.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ synchronized (this.monitor) {
+ StringBuffer s = new StringBuffer();
+ boolean first = true;
+ s.append("RegionDigraph{");
+ for (Region r : this) {
+ if (!first) {
+ s.append(", ");
+ }
+ s.append(r);
+ first = false;
+ }
+ s.append("}");
+ s.append("[");
+ first = true;
+ for (OrderedPair<Region, Region> regionPair : this.filter.keySet()) {
+ if (!first) {
+ s.append(", ");
+ }
+ s.append(regionPair.getFirst() + "->" + regionPair.getSecond());
+ first = false;
+ }
+ s.append("]");
+ return s.toString();
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/resources/META-INF/spring/osgi-framework-context.xml b/org.eclipse.virgo.kernel.osgi/src/main/resources/META-INF/spring/osgi-framework-context.xml
index e817546f..1189ba57 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/resources/META-INF/spring/osgi-framework-context.xml
+++ b/org.eclipse.virgo.kernel.osgi/src/main/resources/META-INF/spring/osgi-framework-context.xml
@@ -5,16 +5,6 @@
<bean class="org.eclipse.virgo.kernel.osgi.region.RegionManager" init-method="start" destroy-method="stop">
<constructor-arg ref="bundleContext"/>
- <constructor-arg ref="compositeBundleFactory"/>
- <constructor-arg ref="eventAdmin"/>
- <constructor-arg>
- <bean class="org.eclipse.virgo.kernel.osgi.region.eventlog.RegionAwareEventLoggerServiceFactory">
- <constructor-arg ref="eventLoggerFactory"/>
- </bean>
- </constructor-arg>
- <constructor-arg ref="configAdmin"/>
- <constructor-arg ref="eventLogger"/>
- <constructor-arg ref="shutdown"/>
</bean>
</beans>
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerTests.java
index 3ff33647..573bf898 100644
--- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerTests.java
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerTests.java
@@ -11,83 +11,36 @@
package org.eclipse.virgo.kernel.osgi.region;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.isA;
-import static org.easymock.EasyMock.isNull;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
-import java.util.Dictionary;
-import java.util.Hashtable;
import java.util.List;
-import java.util.Map;
-import org.junit.Test;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.launch.Framework;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.framework.CompositeBundle;
-import org.osgi.service.framework.CompositeBundleFactory;
-import org.osgi.service.framework.SurrogateBundle;
-
-import org.eclipse.virgo.kernel.osgi.region.RegionManager;
-import org.eclipse.virgo.medic.eventlog.EventLogger;
-import org.eclipse.virgo.kernel.core.Shutdown;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
import org.eclipse.virgo.teststubs.osgi.framework.StubServiceRegistration;
+import org.junit.Test;
+import org.osgi.framework.Version;
-/**
- */
-@SuppressWarnings("deprecation")
public class RegionManagerTests {
@Test
public void testStartAndStop() throws Exception {
StubBundleContext bundleContext = new StubBundleContext();
- StubBundleContext surrogateBundleContext = new StubBundleContext();
-
- Framework user = createMock(Framework.class);
- SurrogateBundle surrogate = createMock(SurrogateBundle.class);
- @SuppressWarnings("unchecked")
- ServiceFactory<EventLogger> serviceFactory = createMock(ServiceFactory.class);
-
- CompositeBundleFactory factory = createMock(CompositeBundleFactory.class);
- CompositeBundle bundle = createMock(CompositeBundle.class);
-
- expect(factory.installCompositeBundle(isA(Map.class), isA(String.class), isA(Map.class))).andReturn(bundle);
- expect(bundle.getCompositeFramework()).andReturn(user);
- bundle.start();
- expect(bundle.getSurrogateBundle()).andReturn(surrogate);
-
- expect(surrogate.getBundleContext()).andReturn(surrogateBundleContext);
-
- EventAdmin eventAdmin = createMock(EventAdmin.class);
- eventAdmin.sendEvent(isA(Event.class));
-
- Dictionary<String, String> properties = new Hashtable<String, String>();
- Configuration config = createMock(Configuration.class);
- expect(config.getProperties()).andReturn(properties);
-
- ConfigurationAdmin configAdmin = createMock(ConfigurationAdmin.class);
- expect(configAdmin.getConfiguration(isA(String.class), (String) isNull())).andReturn(config);
- EventLogger eventLogger = createMock(EventLogger.class);
- Shutdown shutdown = createMock(Shutdown.class);
+ StubBundle stubUserRegionFactoryBundle = new StubBundle("org.eclipse.virgo.kernel.userregionfactory", new Version("2.2.0"));
+ bundleContext.addInstalledBundle(stubUserRegionFactoryBundle);
- replay(factory, bundle, surrogate, eventAdmin, configAdmin, config);
- RegionManager manager = new RegionManager(bundleContext, factory, eventAdmin, serviceFactory, configAdmin, eventLogger, shutdown);
+ StubBundle stubSystemBundle = new StubBundle(0L, "org.osgi.framework", new Version("0"), "");
+ bundleContext.addInstalledBundle(stubSystemBundle);
+
+
+ RegionManager manager = new RegionManager(bundleContext);
manager.start();
List<StubServiceRegistration<Object>> serviceRegistrations = bundleContext.getServiceRegistrations();
- assertEquals("Regions not registered", 2, serviceRegistrations.size());
+ assertEquals("Region services not registered", 8, serviceRegistrations.size());
manager.stop();
- verify(factory, bundle, surrogate, eventAdmin, configAdmin, config);
}
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHookTests.java
new file mode 100644
index 00000000..ace07941
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleEventHookTests.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the Eclipse Virgo project.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ */
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.easymock.EasyMock;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.hooks.bundle.EventHook;
+import org.osgi.framework.hooks.bundle.FindHook;
+
+public class RegionBundleEventHookTests {
+
+ private FindHook mockFindHook;
+
+ private BundleEvent bundleEvent;
+
+ private Collection<BundleContext> contexts;
+
+ private Bundle eventBundle;
+
+ @Before
+ public void setUp() throws Exception {
+ this.mockFindHook = EasyMock.createMock(FindHook.class);
+ this.eventBundle = new StubBundle();
+ this.bundleEvent = new BundleEvent(BundleEvent.STARTED, this.eventBundle, this.eventBundle);
+ this.contexts = new HashSet<BundleContext>();
+ StubBundleContext stubListenerBundleContext = new StubBundleContext();
+ this.contexts.add(stubListenerBundleContext);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testEventAllowed() {
+ this.mockFindHook = new FindHook() {
+
+ @Override
+ public void find(BundleContext context, Collection<Bundle> bundles) {
+ }
+ };
+ EventHook eventHook = new RegionBundleEventHook(this.mockFindHook);
+ eventHook.event(this.bundleEvent, this.contexts);
+ assertEquals(1, this.contexts.size());
+ }
+
+ @Test
+ public void testEventNotAllowed() {
+ this.mockFindHook = new FindHook() {
+
+ @Override
+ public void find(BundleContext context, Collection<Bundle> bundles) {
+ bundles.clear();
+ }
+ };
+ EventHook eventHook = new RegionBundleEventHook(this.mockFindHook);
+ eventHook.event(this.bundleEvent, this.contexts);
+ assertTrue(this.contexts.isEmpty());
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java
new file mode 100644
index 00000000..ef9a3810
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.bundle.FindHook;
+
+public class RegionBundleFindHookTests {
+
+ private static final String BUNDLE_X = "X";
+
+ private static final Version BUNDLE_VERSION = new Version("0");
+
+ private long bundleId;
+
+ private static final String REGION_A = "RegionA";
+
+ private static final String BUNDLE_A = "BundleA";
+
+ private static final String REGION_B = "RegionB";
+
+ private static final String BUNDLE_B = "BundleB";
+
+ private static final String REGION_C = "RegionC";
+
+ private static final String BUNDLE_C = "BundleC";
+
+ private static final String REGION_D = "RegionD";
+
+ private static final String BUNDLE_D = "BundleD";
+
+ private StandardRegionDigraph digraph;
+
+ private StubBundleContext stubBundleContext;
+
+ private FindHook bundleFindHook;
+
+ private Map<String, Region> regions;
+
+ private Map<String, Bundle> bundles;
+
+ private Collection<Bundle> candidates;
+
+ @Before
+ public void setUp() throws Exception {
+ this.bundleId = 1L;
+ this.regions = new HashMap<String, Region>();
+ this.bundles = new HashMap<String, Bundle>();
+ this.digraph = new StandardRegionDigraph();
+ this.stubBundleContext = new StubBundleContext();
+ this.bundleFindHook = new RegionBundleFindHook(this.digraph);
+ this.candidates = new HashSet<Bundle>();
+
+ // Create regions A, B, C, D containing bundles A, B, C, D, respectively.
+ createRegion(REGION_A, BUNDLE_A);
+ createRegion(REGION_B, BUNDLE_B);
+ createRegion(REGION_C, BUNDLE_C);
+ createRegion(REGION_D, BUNDLE_D);
+
+ createBundle(BUNDLE_X);
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testFindInSameRegion() {
+ this.candidates.add(bundle(BUNDLE_A));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(bundle(BUNDLE_A)));
+ }
+
+ @Test
+ public void testFindInDisconnectedRegion() {
+ this.candidates.add(bundle(BUNDLE_B));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), this.candidates);
+ assertFalse(this.candidates.contains(bundle(BUNDLE_B)));
+ }
+
+ @Test
+ public void testFindConnectedRegionAllowed() throws BundleException {
+ RegionFilter filter = createFilter(BUNDLE_B);
+ region(REGION_A).connectRegion(region(REGION_B), filter);
+
+ this.candidates.add(bundle(BUNDLE_B));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(bundle(BUNDLE_B)));
+ }
+
+ @Test
+ public void testFindConnectedRegionFiltering() throws BundleException {
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_B));
+ Bundle x = createBundle(BUNDLE_X);
+ region(REGION_B).addBundle(x);
+
+ this.candidates.add(bundle(BUNDLE_B));
+ this.candidates.add(x);
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(bundle(BUNDLE_B)));
+ assertFalse(this.candidates.contains(x));
+ }
+
+ @Test
+ public void testFindTransitive() throws BundleException {
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_C));
+ region(REGION_B).connectRegion(region(REGION_C), createFilter(BUNDLE_C));
+ region(REGION_C).addBundle(bundle(BUNDLE_X));
+
+ this.candidates.add(bundle(BUNDLE_B));
+ this.candidates.add(bundle(BUNDLE_C));
+ this.candidates.add(bundle(BUNDLE_X));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(bundle(BUNDLE_C)));
+ assertFalse(this.candidates.contains(bundle(BUNDLE_B)));
+ assertFalse(this.candidates.contains(bundle(BUNDLE_X)));
+
+ }
+
+ @Test
+ public void testFindInCyclicGraph() throws BundleException {
+ region(REGION_D).addBundle(bundle(BUNDLE_X));
+
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_D, BUNDLE_X));
+ region(REGION_B).connectRegion(region(REGION_A), createFilter());
+
+ region(REGION_B).connectRegion(region(REGION_D), createFilter(BUNDLE_D));
+ region(REGION_D).connectRegion(region(REGION_B), createFilter());
+
+ region(REGION_B).connectRegion(region(REGION_C), createFilter(BUNDLE_X));
+ region(REGION_C).connectRegion(region(REGION_B), createFilter());
+
+ region(REGION_C).connectRegion(region(REGION_D), createFilter(BUNDLE_X));
+ region(REGION_D).connectRegion(region(REGION_C), createFilter());
+
+ region(REGION_A).connectRegion(region(REGION_C), createFilter());
+ region(REGION_C).connectRegion(region(REGION_A), createFilter());
+
+ region(REGION_D).connectRegion(region(REGION_A), createFilter());
+ region(REGION_A).connectRegion(region(REGION_D), createFilter());
+
+ // Find from region A.
+ this.candidates.add(bundle(BUNDLE_B));
+ this.candidates.add(bundle(BUNDLE_C));
+ this.candidates.add(bundle(BUNDLE_D));
+ this.candidates.add(bundle(BUNDLE_X));
+
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), this.candidates);
+ assertEquals(2, this.candidates.size());
+ assertTrue(this.candidates.contains(bundle(BUNDLE_D)));
+ assertTrue(this.candidates.contains(bundle(BUNDLE_X)));
+
+ // Find from region B
+ this.candidates.add(bundle(BUNDLE_B));
+ this.candidates.add(bundle(BUNDLE_C));
+ this.candidates.add(bundle(BUNDLE_D));
+ this.candidates.add(bundle(BUNDLE_X));
+
+ this.bundleFindHook.find(bundleContext(BUNDLE_B), this.candidates);
+ assertEquals(3, this.candidates.size());
+ assertTrue(this.candidates.contains(bundle(BUNDLE_B)));
+ assertTrue(this.candidates.contains(bundle(BUNDLE_D)));
+ assertTrue(this.candidates.contains(bundle(BUNDLE_X)));
+ }
+
+ @Test
+ public void testFindFromSystemBundle() {
+ this.candidates.add(bundle(BUNDLE_A));
+
+ Bundle stubBundle = new StubBundle(0L, "sys", BUNDLE_VERSION, "");
+ this.bundleFindHook.find(stubBundle.getBundleContext(), this.candidates);
+ assertEquals(1, this.candidates.size());
+ assertTrue(this.candidates.contains(bundle(BUNDLE_A)));
+ }
+
+ @Test
+ public void testFindFromBundleInNoRegion() {
+ this.candidates.add(bundle(BUNDLE_A));
+
+ Bundle stranger = createBundle("stranger");
+ this.bundleFindHook.find(stranger.getBundleContext(), this.candidates);
+ assertEquals(0, this.candidates.size());
+ }
+
+
+ private Region createRegion(String regionName, String... bundleSymbolicNames) throws BundleException {
+ Region region = new BundleIdBasedRegion(regionName, this.digraph, this.stubBundleContext);
+ for (String bundleSymbolicName : bundleSymbolicNames) {
+ Bundle stubBundle = createBundle(bundleSymbolicName);
+ region.addBundle(stubBundle);
+ }
+ this.regions.put(regionName, region);
+ this.digraph.addRegion(region);
+ return region;
+ }
+
+ private Region region(String regionName) {
+ return this.regions.get(regionName);
+ }
+
+ private RegionFilter createFilter(String... bundleSymbolicNames) {
+ RegionFilter filter = new StandardRegionFilter();
+ for (String bundleSymbolicName : bundleSymbolicNames) {
+ filter.allowBundle(bundleSymbolicName, BUNDLE_VERSION);
+ }
+ return filter;
+ }
+
+ private Bundle createBundle(String bundleSymbolicName) {
+ Bundle stubBundle = new StubBundle(this.bundleId++, bundleSymbolicName, BUNDLE_VERSION, "loc:" + bundleSymbolicName);
+ this.bundles.put(bundleSymbolicName, stubBundle);
+ return stubBundle;
+ }
+
+ private BundleContext bundleContext(String bundleSymbolicName) {
+ return bundle(bundleSymbolicName).getBundleContext();
+ }
+
+ private Bundle bundle(String bundleSymbolicName) {
+ Bundle bundleA = this.bundles.get(bundleSymbolicName);
+ return bundleA;
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java
new file mode 100644
index 00000000..32db48a4
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java
@@ -0,0 +1,501 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy;
+import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.Capability;
+
+public class RegionResolverHookTests {
+
+ private static final String PACKAGE_A = "package.a";
+
+ private static final String PACKAGE_B = "package.b";
+
+ private static final String PACKAGE_C = "package.c";
+
+ private static final String PACKAGE_D = "package.d";
+
+ private static final String PACKAGE_X = "package.x";
+
+ private static final String BUNDLE_X = "X";
+
+ private static final Version BUNDLE_VERSION = new Version("0");
+
+ private long bundleId;
+
+ private static final String REGION_A = "RegionA";
+
+ private static final String BUNDLE_A = "BundleA";
+
+ private static final String REGION_B = "RegionB";
+
+ private static final String BUNDLE_B = "BundleB";
+
+ private static final String REGION_C = "RegionC";
+
+ private static final String BUNDLE_C = "BundleC";
+
+ private static final String REGION_D = "RegionD";
+
+ private static final String BUNDLE_D = "BundleD";
+
+ private StandardRegionDigraph digraph;
+
+ private StubBundleContext stubBundleContext;
+
+ private ResolverHook resolverHook;
+
+ private Map<String, Region> regions;
+
+ private Map<String, Bundle> bundles;
+
+ private Collection<Capability> candidates;
+
+ @Before
+ public void setUp() throws Exception {
+ this.bundleId = 1L;
+ this.regions = new HashMap<String, Region>();
+ this.bundles = new HashMap<String, Bundle>();
+ this.digraph = new StandardRegionDigraph();
+ this.stubBundleContext = new StubBundleContext();
+ this.resolverHook = new RegionResolverHook(this.digraph);
+ this.candidates = new HashSet<Capability>();
+
+ // Create regions A, B, C, D containing bundles A, B, C, D, respectively.
+ createRegion(REGION_A, BUNDLE_A);
+ createRegion(REGION_B, BUNDLE_B);
+ createRegion(REGION_C, BUNDLE_C);
+ createRegion(REGION_D, BUNDLE_D);
+
+ createBundle(BUNDLE_X);
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testResolveInSameRegion() {
+ this.candidates.add(packageCapability(BUNDLE_A, PACKAGE_A));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_A, PACKAGE_A)));
+ }
+
+ @Test
+ public void testResolveInDisconnectedRegion() {
+ this.candidates.add(packageCapability(BUNDLE_B, PACKAGE_B));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertFalse(this.candidates.contains(packageCapability(BUNDLE_B, PACKAGE_B)));
+ }
+
+ @Test
+ public void testResolveConnectedRegionAllowed() throws BundleException {
+ RegionFilter filter = createFilter(PACKAGE_B);
+ region(REGION_A).connectRegion(region(REGION_B), filter);
+
+ this.candidates.add(packageCapability(BUNDLE_B, PACKAGE_B));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_B, PACKAGE_B)));
+ }
+
+ @Test
+ public void testResolveBundleCapabilityConnectedRegionAllowed() throws BundleException {
+ RegionFilter filter = createBundleFilter(BUNDLE_B, BUNDLE_VERSION);
+ region(REGION_A).connectRegion(region(REGION_B), filter);
+
+ this.candidates.add(bundleCapability(BUNDLE_B));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(bundleCapability(BUNDLE_B)));
+ }
+
+ @Test
+ public void testResolveConnectedRegionFiltering() throws BundleException {
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(PACKAGE_B));
+ Bundle x = createBundle(BUNDLE_X);
+ region(REGION_B).addBundle(x);
+
+ this.candidates.add(packageCapability(BUNDLE_B, PACKAGE_B));
+ this.candidates.add(packageCapability(BUNDLE_X, PACKAGE_X));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_B, PACKAGE_B)));
+ assertFalse(this.candidates.contains(packageCapability(BUNDLE_X, PACKAGE_X)));
+ }
+
+ @Test
+ public void testResolveBundleConnectedRegionFiltering() throws BundleException {
+ RegionFilter filter = createBundleFilter(BUNDLE_B, BUNDLE_VERSION);
+ region(REGION_A).connectRegion(region(REGION_B), filter);
+ Bundle x = createBundle(BUNDLE_X);
+ region(REGION_B).addBundle(x);
+
+ this.candidates.add(bundleCapability(BUNDLE_B));
+ this.candidates.add(bundleCapability(BUNDLE_X));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(bundleCapability(BUNDLE_B)));
+ assertFalse(this.candidates.contains(bundleCapability(BUNDLE_X)));
+ }
+
+ @Test
+ public void testResolveTransitive() throws BundleException {
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(PACKAGE_C));
+ region(REGION_B).connectRegion(region(REGION_C), createFilter(PACKAGE_C));
+ region(REGION_C).addBundle(bundle(BUNDLE_X));
+
+ this.candidates.add(packageCapability(BUNDLE_B, PACKAGE_B));
+ this.candidates.add(packageCapability(BUNDLE_C, PACKAGE_C));
+ this.candidates.add(packageCapability(BUNDLE_X, PACKAGE_X));
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_C, PACKAGE_C)));
+ assertFalse(this.candidates.contains(packageCapability(BUNDLE_B, PACKAGE_B)));
+ assertFalse(this.candidates.contains(packageCapability(BUNDLE_X, PACKAGE_X)));
+
+ }
+
+ @Test
+ public void testResolveInCyclicGraph() throws BundleException {
+ region(REGION_D).addBundle(bundle(BUNDLE_X));
+
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(PACKAGE_D, PACKAGE_X));
+ region(REGION_B).connectRegion(region(REGION_A), createFilter());
+
+ region(REGION_B).connectRegion(region(REGION_D), createFilter(PACKAGE_D));
+ region(REGION_D).connectRegion(region(REGION_B), createFilter());
+
+ region(REGION_B).connectRegion(region(REGION_C), createFilter(PACKAGE_X));
+ region(REGION_C).connectRegion(region(REGION_B), createFilter());
+
+ region(REGION_C).connectRegion(region(REGION_D), createFilter(PACKAGE_X));
+ region(REGION_D).connectRegion(region(REGION_C), createFilter());
+
+ region(REGION_A).connectRegion(region(REGION_C), createFilter());
+ region(REGION_C).connectRegion(region(REGION_A), createFilter());
+
+ region(REGION_D).connectRegion(region(REGION_A), createFilter());
+ region(REGION_A).connectRegion(region(REGION_D), createFilter());
+
+ // Find from region A.
+ this.candidates.add(packageCapability(BUNDLE_B, PACKAGE_B));
+ this.candidates.add(packageCapability(BUNDLE_C, PACKAGE_C));
+ this.candidates.add(packageCapability(BUNDLE_D, PACKAGE_D));
+ this.candidates.add(packageCapability(BUNDLE_X, PACKAGE_X));
+
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_A), this.candidates);
+ assertEquals(2, this.candidates.size());
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_D, PACKAGE_D)));
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_X, PACKAGE_X)));
+
+ // Find from region B
+ this.candidates.add(packageCapability(BUNDLE_B, PACKAGE_B));
+ this.candidates.add(packageCapability(BUNDLE_C, PACKAGE_C));
+ this.candidates.add(packageCapability(BUNDLE_D, PACKAGE_D));
+ this.candidates.add(packageCapability(BUNDLE_X, PACKAGE_X));
+
+ this.resolverHook.filterMatches(bundleRevision(BUNDLE_B), this.candidates);
+ assertEquals(3, this.candidates.size());
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_B, PACKAGE_B)));
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_D, PACKAGE_D)));
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_X, PACKAGE_X)));
+ }
+
+ @Test
+ public void testResolveFromSystemBundle() {
+ this.candidates.add(packageCapability(BUNDLE_A, PACKAGE_A));
+
+ Bundle stubBundle = new StubBundle(0L, "sys", BUNDLE_VERSION, "");
+ this.resolverHook.filterMatches(new StubBundleRevision(stubBundle), this.candidates);
+ assertEquals(1, this.candidates.size());
+ assertTrue(this.candidates.contains(packageCapability(BUNDLE_A, PACKAGE_A)));
+ }
+
+ @Test
+ public void testResolveFromBundleInNoRegion() {
+ this.candidates.add(packageCapability(BUNDLE_A, PACKAGE_A));
+
+ Bundle stranger = createBundle("stranger");
+ this.resolverHook.filterMatches(new StubBundleRevision(stranger), this.candidates);
+ assertEquals(0, this.candidates.size());
+ }
+
+ @Test
+ public void testUnimplementedMethods() {
+ this.resolverHook.filterResolvable(null);
+ this.resolverHook.filterSingletonCollisions(null, null);
+ this.resolverHook.end();
+ }
+
+ private Capability packageCapability(final String bundleSymbolicName, String packageName) {
+ return new StubPackageCapability(bundleSymbolicName, packageName);
+ }
+
+ private Capability bundleCapability(String bundleSymbolicName) {
+ return new StubBundleCapability(bundleSymbolicName);
+ }
+
+ private Region createRegion(String regionName, String... bundleSymbolicNames) throws BundleException {
+ Region region = new BundleIdBasedRegion(regionName, this.digraph, this.stubBundleContext);
+ for (String bundleSymbolicName : bundleSymbolicNames) {
+ Bundle stubBundle = createBundle(bundleSymbolicName);
+ region.addBundle(stubBundle);
+ }
+ this.regions.put(regionName, region);
+ this.digraph.addRegion(region);
+ return region;
+ }
+
+ private Region region(String regionName) {
+ return this.regions.get(regionName);
+ }
+
+ private RegionFilter createFilter(final String... packageNames) {
+ RegionFilter filter = new StandardRegionFilter();
+ filter.setPackageImportPolicy(new RegionPackageImportPolicy() {
+
+ @Override
+ public boolean isImported(String packageName, Map<String, Object> attributes, Map<String, String> directives) {
+ for (String pkg : packageNames) {
+ if (packageName.equals(pkg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ return filter;
+ }
+
+ private RegionFilter createBundleFilter(String bundleSymbolicName, Version bundleVersion) {
+ RegionFilter filter = new StandardRegionFilter();
+ filter.allowBundle(bundleSymbolicName, bundleVersion);
+ return filter;
+ }
+
+ private Bundle createBundle(String bundleSymbolicName) {
+ Bundle stubBundle = new StubBundle(this.bundleId++, bundleSymbolicName, BUNDLE_VERSION, "loc:" + bundleSymbolicName);
+ this.bundles.put(bundleSymbolicName, stubBundle);
+ return stubBundle;
+ }
+
+ private BundleRevision bundleRevision(String bundleSymbolicName) {
+ return new StubBundleRevision(bundle(bundleSymbolicName));
+ }
+
+ private Bundle bundle(String bundleSymbolicName) {
+ Bundle bundleA = this.bundles.get(bundleSymbolicName);
+ return bundleA;
+ }
+
+ private final class StubPackageCapability implements Capability {
+
+ private final String bundleSymbolicName;
+
+ private final String packageName;
+
+ private StubPackageCapability(String bundleSymbolicName, String packageName) {
+ this.bundleSymbolicName = bundleSymbolicName;
+ this.packageName = packageName;
+ }
+
+ @Override
+ public String getNamespace() {
+ return Capability.PACKAGE_CAPABILITY;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return new HashMap<String, String>();
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ HashMap<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Capability.PACKAGE_CAPABILITY, this.packageName);
+ return attributes;
+ }
+
+ @Override
+ public BundleRevision getProviderRevision() {
+ return new StubBundleRevision(bundle(this.bundleSymbolicName));
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + getOuterType().hashCode();
+ result = prime * result + (this.bundleSymbolicName == null ? 0 : this.bundleSymbolicName.hashCode());
+ result = prime * result + (this.packageName == null ? 0 : this.packageName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof StubPackageCapability)) {
+ return false;
+ }
+ StubPackageCapability other = (StubPackageCapability) obj;
+ if (!getOuterType().equals(other.getOuterType())) {
+ return false;
+ }
+ if (this.bundleSymbolicName == null) {
+ if (other.bundleSymbolicName != null) {
+ return false;
+ }
+ } else if (!this.bundleSymbolicName.equals(other.bundleSymbolicName)) {
+ return false;
+ }
+ if (this.packageName == null) {
+ if (other.packageName != null) {
+ return false;
+ }
+ } else if (!this.packageName.equals(other.packageName)) {
+ return false;
+ }
+ return true;
+ }
+
+ private RegionResolverHookTests getOuterType() {
+ return RegionResolverHookTests.this;
+ }
+
+ }
+
+ private final class StubBundleCapability implements Capability {
+
+ private final String bundleSymbolicName;
+
+ private StubBundleCapability(String bundleSymbolicName) {
+ this.bundleSymbolicName = bundleSymbolicName;
+ }
+
+ @Override
+ public String getNamespace() {
+ return Capability.BUNDLE_CAPABILITY;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return new HashMap<String, String>();
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ HashMap<String, Object> attributes = new HashMap<String, Object>();
+ return attributes;
+ }
+
+ @Override
+ public BundleRevision getProviderRevision() {
+ return new StubBundleRevision(bundle(this.bundleSymbolicName));
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + getOuterType().hashCode();
+ result = prime * result + ((bundleSymbolicName == null) ? 0 : bundleSymbolicName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof StubBundleCapability))
+ return false;
+ StubBundleCapability other = (StubBundleCapability) obj;
+ if (!getOuterType().equals(other.getOuterType()))
+ return false;
+ if (bundleSymbolicName == null) {
+ if (other.bundleSymbolicName != null)
+ return false;
+ } else if (!bundleSymbolicName.equals(other.bundleSymbolicName))
+ return false;
+ return true;
+ }
+
+ private RegionResolverHookTests getOuterType() {
+ return RegionResolverHookTests.this;
+ }
+
+ }
+
+ private final class StubBundleRevision implements BundleRevision {
+
+ private final Bundle bundle;
+
+ private StubBundleRevision(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return this.bundle;
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return this.bundle.getSymbolicName();
+ }
+
+ @Override
+ public Version getVersion() {
+ return this.bundle.getVersion();
+ }
+
+ @Override
+ public List<Capability> getDeclaredCapabilities(String namespace) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getTypes() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java
new file mode 100644
index 00000000..f8b0402c
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the Eclipse Virgo project.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ */
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.easymock.EasyMock;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.teststubs.osgi.framework.StubServiceReference;
+import org.eclipse.virgo.teststubs.osgi.framework.StubServiceRegistration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.service.EventHook;
+import org.osgi.framework.hooks.service.FindHook;
+
+public class RegionServiceEventHookTests {
+
+ private FindHook mockFindHook;
+
+ private ServiceEvent serviceEvent;
+
+ private Collection<BundleContext> contexts;
+
+ private Bundle eventBundle;
+
+ @Before
+ public void setUp() throws Exception {
+ this.mockFindHook = EasyMock.createMock(FindHook.class);
+ this.eventBundle = new StubBundle();
+ StubServiceReference<Object> stubServiceReference = new StubServiceReference<Object>(new StubServiceRegistration<Object>(
+ (StubBundleContext) this.eventBundle.getBundleContext(), Object.class.getName()));
+ this.serviceEvent = new ServiceEvent(ServiceEvent.REGISTERED, stubServiceReference);
+ this.contexts = new HashSet<BundleContext>();
+ StubBundleContext stubListenerBundleContext = new StubBundleContext();
+ this.contexts.add(stubListenerBundleContext);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testEventAllowed() {
+ this.mockFindHook = new FindHook() {
+
+ @Override
+ public void find(BundleContext context, String name, String filter, boolean allServices, Collection<ServiceReference<?>> references) {
+ }
+ };
+ EventHook eventHook = new RegionServiceEventHook(this.mockFindHook);
+ eventHook.event(this.serviceEvent, this.contexts);
+ assertEquals(1, this.contexts.size());
+ }
+
+ @Test
+ public void testEventNotAllowed() {
+ this.mockFindHook = new FindHook() {
+
+ @Override
+ public void find(BundleContext context, String name, String filter, boolean allServices, Collection<ServiceReference<?>> references) {
+ references.clear();
+ }
+ };
+ EventHook eventHook = new RegionServiceEventHook(this.mockFindHook);
+ eventHook.event(this.serviceEvent, this.contexts);
+ assertTrue(this.contexts.isEmpty());
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java
new file mode 100644
index 00000000..26907f52
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.teststubs.osgi.framework.StubServiceReference;
+import org.eclipse.virgo.teststubs.osgi.framework.StubServiceRegistration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.service.FindHook;
+
+/**
+ * This testcase was based on {@link RegionBundleFindHookTests}.
+ */
+public class RegionServiceFindHookTests {
+
+ private static final String BUNDLE_X = "X";
+
+ private static final Version BUNDLE_VERSION = new Version("0");
+
+ private long bundleId;
+
+ private static final String REGION_A = "RegionA";
+
+ private static final String BUNDLE_A = "BundleA";
+
+ private static final String REGION_B = "RegionB";
+
+ private static final String BUNDLE_B = "BundleB";
+
+ private static final String REGION_C = "RegionC";
+
+ private static final String BUNDLE_C = "BundleC";
+
+ private static final String REGION_D = "RegionD";
+
+ private static final String BUNDLE_D = "BundleD";
+
+ private StandardRegionDigraph digraph;
+
+ private StubBundleContext stubBundleContext;
+
+ private FindHook bundleFindHook;
+
+ private Map<String, Region> regions;
+
+ private Map<String, Bundle> bundles;
+
+ private Map<String, ServiceReference<Object>> serviceReferences;
+
+ private Collection<ServiceReference<?>> candidates;
+
+ @Before
+ public void setUp() throws Exception {
+ this.bundleId = 1L;
+ this.regions = new HashMap<String, Region>();
+ this.bundles = new HashMap<String, Bundle>();
+ this.serviceReferences = new HashMap<String, ServiceReference<Object>>();
+ this.digraph = new StandardRegionDigraph();
+ this.stubBundleContext = new StubBundleContext();
+ this.bundleFindHook = new RegionServiceFindHook(this.digraph);
+ this.candidates = new HashSet<ServiceReference<?>>();
+
+ // Create regions A, B, C, D containing bundles A, B, C, D, respectively.
+ createRegion(REGION_A, BUNDLE_A);
+ createRegion(REGION_B, BUNDLE_B);
+ createRegion(REGION_C, BUNDLE_C);
+ createRegion(REGION_D, BUNDLE_D);
+
+ createBundle(BUNDLE_X);
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testFindInSameRegion() {
+ this.candidates.add(serviceReference(BUNDLE_A));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), "", "", false, this.candidates);
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_A)));
+ }
+
+ @Test
+ public void testFindInDisconnectedRegion() {
+ this.candidates.add(serviceReference(BUNDLE_B));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), "", "", false, this.candidates);
+ assertFalse(this.candidates.contains(serviceReference(BUNDLE_B)));
+ }
+
+ @Test
+ public void testFindConnectedRegionAllowed() throws BundleException {
+ RegionFilter filter = createFilter(BUNDLE_B);
+ region(REGION_A).connectRegion(region(REGION_B), filter);
+
+ this.candidates.add(serviceReference(BUNDLE_B));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), "", "", false, this.candidates);
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_B)));
+ }
+
+ @Test
+ public void testFindConnectedRegionFiltering() throws BundleException {
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_B));
+ Bundle x = createBundle(BUNDLE_X);
+ region(REGION_B).addBundle(x);
+
+ this.candidates.add(serviceReference(BUNDLE_B));
+ this.candidates.add(serviceReference(BUNDLE_X));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), "", "", false, this.candidates);
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_B)));
+ assertFalse(this.candidates.contains(serviceReference(BUNDLE_X)));
+ }
+
+ @Test
+ public void testFindTransitive() throws BundleException {
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_C));
+ region(REGION_B).connectRegion(region(REGION_C), createFilter(BUNDLE_C));
+ region(REGION_C).addBundle(bundle(BUNDLE_X));
+
+ this.candidates.add(serviceReference(BUNDLE_B));
+ this.candidates.add(serviceReference(BUNDLE_C));
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), "", "", false, this.candidates);
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_C)));
+ assertFalse(this.candidates.contains(serviceReference(BUNDLE_B)));
+ assertFalse(this.candidates.contains(serviceReference(BUNDLE_X)));
+
+ }
+
+ @Test
+ public void testFindInCyclicGraph() throws BundleException {
+ region(REGION_D).addBundle(bundle(BUNDLE_X));
+
+ region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_D, BUNDLE_X));
+ region(REGION_B).connectRegion(region(REGION_A), createFilter());
+
+ region(REGION_B).connectRegion(region(REGION_D), createFilter(BUNDLE_D));
+ region(REGION_D).connectRegion(region(REGION_B), createFilter());
+
+ region(REGION_B).connectRegion(region(REGION_C), createFilter(BUNDLE_X));
+ region(REGION_C).connectRegion(region(REGION_B), createFilter());
+
+ region(REGION_C).connectRegion(region(REGION_D), createFilter(BUNDLE_X));
+ region(REGION_D).connectRegion(region(REGION_C), createFilter());
+
+ region(REGION_A).connectRegion(region(REGION_C), createFilter());
+ region(REGION_C).connectRegion(region(REGION_A), createFilter());
+
+ region(REGION_D).connectRegion(region(REGION_A), createFilter());
+ region(REGION_A).connectRegion(region(REGION_D), createFilter());
+
+ // Find from region A.
+ this.candidates.add(serviceReference(BUNDLE_B));
+ this.candidates.add(serviceReference(BUNDLE_C));
+ this.candidates.add(serviceReference(BUNDLE_D));
+ this.candidates.add(serviceReference(BUNDLE_X));
+
+ this.bundleFindHook.find(bundleContext(BUNDLE_A), "", "", false, this.candidates);
+ assertEquals(2, this.candidates.size());
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_D)));
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_X)));
+
+ // Find from region B
+ this.candidates.add(serviceReference(BUNDLE_B));
+ this.candidates.add(serviceReference(BUNDLE_C));
+ this.candidates.add(serviceReference(BUNDLE_D));
+ this.candidates.add(serviceReference(BUNDLE_X));
+
+ this.bundleFindHook.find(bundleContext(BUNDLE_B), "", "", false, this.candidates);
+ assertEquals(3, this.candidates.size());
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_B)));
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_D)));
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_X)));
+ }
+
+ @Test
+ public void testFindFromSystemBundle() {
+ this.candidates.add(serviceReference(BUNDLE_A));
+
+ Bundle stubBundle = new StubBundle(0L, "sys", BUNDLE_VERSION, "");
+ this.bundleFindHook.find(stubBundle.getBundleContext(), "", "", false, this.candidates);
+ assertEquals(1, this.candidates.size());
+ assertTrue(this.candidates.contains(serviceReference(BUNDLE_A)));
+ }
+
+ @Test
+ public void testFindFromBundleInNoRegion() {
+ this.candidates.add(serviceReference(BUNDLE_A));
+
+ Bundle stranger = createBundle("stranger");
+ this.bundleFindHook.find(stranger.getBundleContext(), "", "", false, this.candidates);
+ assertEquals(0, this.candidates.size());
+ }
+
+ private Region createRegion(String regionName, String... bundleSymbolicNames) throws BundleException {
+ Region region = new BundleIdBasedRegion(regionName, this.digraph, this.stubBundleContext);
+ for (String bundleSymbolicName : bundleSymbolicNames) {
+ Bundle stubBundle = createBundle(bundleSymbolicName);
+ region.addBundle(stubBundle);
+ }
+ this.regions.put(regionName, region);
+ this.digraph.addRegion(region);
+ return region;
+ }
+
+ private Region region(String regionName) {
+ return this.regions.get(regionName);
+ }
+
+ private RegionFilter createFilter(final String... referenceNames) {
+ RegionFilter filter = new StandardRegionFilter();
+ Filter f = new Filter() {
+
+ @Override
+ public boolean match(ServiceReference<?> reference) {
+ for (String referenceName : referenceNames) {
+ if (reference.getBundle().getSymbolicName().equals(referenceName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean match(Dictionary<String, ?> dictionary) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean matchCase(Dictionary<String, ?> dictionary) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean matches(Map<String, ?> map) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ };
+ filter.setServiceFilter(f);
+ return filter;
+ }
+
+ private Bundle createBundle(String bundleSymbolicName) {
+ Bundle stubBundle = new StubBundle(this.bundleId++, bundleSymbolicName, BUNDLE_VERSION, "loc:" + bundleSymbolicName);
+ this.bundles.put(bundleSymbolicName, stubBundle);
+ createServiceReference(stubBundle, bundleSymbolicName);
+ return stubBundle;
+ }
+
+ private StubServiceReference<Object> createServiceReference(Bundle stubBundle, String referenceName) {
+ StubServiceRegistration<Object> stubServiceRegistration = new StubServiceRegistration<Object>(
+ (StubBundleContext) stubBundle.getBundleContext(), Object.class.getName());
+ StubServiceReference<Object> stubServiceReference = new StubServiceReference<Object>(stubServiceRegistration);
+ this.serviceReferences.put(referenceName, stubServiceReference);
+ return stubServiceReference;
+ }
+
+ private BundleContext bundleContext(String bundleSymbolicName) {
+ return bundle(bundleSymbolicName).getBundleContext();
+ }
+
+ private Bundle bundle(String bundleSymbolicName) {
+ Bundle bundleA = this.bundles.get(bundleSymbolicName);
+ return bundleA;
+ }
+
+ private ServiceReference<Object> serviceReference(String referenceName) {
+ return this.serviceReferences.get(referenceName);
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegionTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegionTests.java
new file mode 100644
index 00000000..893744c2
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegionTests.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.internal;
+
+import static org.junit.Assert.*;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.easymock.EasyMock;
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+import org.eclipse.virgo.util.math.OrderedPair;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+
+public class BundleIdBasedRegionTests {
+
+ private static final String OTHER_REGION_NAME = "other";
+
+ private static final String BUNDLE_SYMBOLIC_NAME = "b";
+
+ private static final String BUNDLE_SYMBOLIC_NAME_2 = "c";
+
+ private static final Version BUNDLE_VERSION = new Version("1");
+
+ private static final long BUNDLE_ID = 1L;
+
+ private static final long BUNDLE_ID_2 = 2L;
+
+ private static final String REGION_NAME = "reg";
+
+ private static final long TEST_BUNDLE_ID = 99L;
+
+ private Bundle mockBundle;
+
+ private RegionDigraph mockGraph;
+
+ private Iterator<Region> regionIterator;
+
+ private BundleContext mockBundleContext;
+
+ private Region mockRegion;
+
+ private Region mockRegion2;
+
+ private RegionFilter mockRegionFilter;
+
+ @Before
+ public void setUp() throws Exception {
+ this.mockBundle = EasyMock.createMock(Bundle.class);
+ EasyMock.expect(this.mockBundle.getSymbolicName()).andReturn(BUNDLE_SYMBOLIC_NAME).anyTimes();
+ EasyMock.expect(this.mockBundle.getVersion()).andReturn(BUNDLE_VERSION).anyTimes();
+ EasyMock.expect(this.mockBundle.getBundleId()).andReturn(BUNDLE_ID).anyTimes();
+
+ this.mockBundleContext = EasyMock.createMock(BundleContext.class);
+ EasyMock.expect(this.mockBundleContext.getBundle(BUNDLE_ID)).andReturn(this.mockBundle).anyTimes();
+
+ this.mockRegion = EasyMock.createMock(Region.class);
+ this.mockRegion2 = EasyMock.createMock(Region.class);
+
+ this.mockRegionFilter = EasyMock.createMock(RegionFilter.class);
+
+ this.regionIterator = new Iterator<Region>() {
+
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public Region next() {
+ return null;
+ }
+
+ @Override
+ public void remove() {
+ }
+ };
+ this.mockGraph = EasyMock.createMock(RegionDigraph.class);
+ this.mockGraph.connect(EasyMock.isA(Region.class), EasyMock.eq(this.mockRegionFilter), EasyMock.eq(this.mockRegion));
+ EasyMock.expectLastCall().anyTimes();
+ }
+
+ private void replayMocks() {
+ EasyMock.replay(this.mockBundleContext, this.mockBundle, this.mockRegion, this.mockRegion2, this.mockRegionFilter,
+ this.mockGraph);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EasyMock.verify(this.mockBundleContext, this.mockBundle, this.mockRegion, this.mockRegion2, this.mockRegionFilter,
+ this.mockGraph);
+ }
+
+ @Test
+ public void testGetName() {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ assertEquals(REGION_NAME, r.getName());
+ }
+
+ private void defaultSetUp() {
+ EasyMock.expect(this.mockGraph.iterator()).andReturn(this.regionIterator).anyTimes();
+ EasyMock.expect(this.mockGraph.getEdges(EasyMock.isA(Region.class))).andReturn(new HashSet<FilteredRegion>()).anyTimes();
+ replayMocks();
+ }
+
+ @Test
+ public void testAddBundle() throws BundleException {
+ EasyMock.expect(this.mockGraph.iterator()).andReturn(this.regionIterator).anyTimes();
+
+ HashSet<FilteredRegion> edges = new HashSet<FilteredRegion>();
+ edges.add(new FilteredRegion() {
+
+ @Override
+ public Region getRegion() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public RegionFilter getFilter() {
+ return mockRegionFilter;
+ }
+ });
+ EasyMock.expect(this.mockGraph.getEdges(EasyMock.isA(Region.class))).andReturn(edges).anyTimes();
+ Set<OrderedPair<String, Version>> allowedBundles = new HashSet<OrderedPair<String, Version>>();
+ allowedBundles.add(new OrderedPair<String, Version>(BUNDLE_SYMBOLIC_NAME_2, BUNDLE_VERSION));
+ replayMocks();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ }
+
+ @Test
+ public void testAddExistingBundle() throws BundleException {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ r.addBundle(this.mockBundle);
+ }
+
+ @Test(expected = BundleException.class)
+ public void testAddConflictingBundle() throws BundleException {
+ defaultSetUp();
+
+ Bundle mockBundle2 = EasyMock.createMock(Bundle.class);
+ EasyMock.expect(mockBundle2.getSymbolicName()).andReturn(BUNDLE_SYMBOLIC_NAME).anyTimes();
+ EasyMock.expect(mockBundle2.getVersion()).andReturn(BUNDLE_VERSION).anyTimes();
+ EasyMock.expect(mockBundle2.getBundleId()).andReturn(BUNDLE_ID_2).anyTimes();
+ EasyMock.replay(mockBundle2);
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ r.addBundle(mockBundle2);
+ }
+
+
+ @Test(expected = BundleException.class)
+ public void testAddBundlePresentInAnotherRegion() throws BundleException {
+ this.regionIterator = new Iterator<Region>() {
+
+ private int next = 2;
+
+ @Override
+ public boolean hasNext() {
+ return this.next > 0;
+ }
+
+ @Override
+ public Region next() {
+ switch (next--) {
+ case 2:
+ return mockRegion;
+ default:
+ return mockRegion2;
+ }
+ }
+
+ @Override
+ public void remove() {
+ }
+ };
+ EasyMock.expect(this.mockGraph.iterator()).andReturn(this.regionIterator).anyTimes();
+ EasyMock.expect(this.mockGraph.getEdges(EasyMock.isA(Region.class))).andReturn(new HashSet<FilteredRegion>()).anyTimes();
+ EasyMock.expect(this.mockRegion.contains(EasyMock.eq(this.mockBundle))).andReturn(true).anyTimes();
+ EasyMock.expect(this.mockRegion2.contains(EasyMock.eq(this.mockBundle))).andReturn(false).anyTimes();
+
+ replayMocks();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ }
+
+ @Test
+ public void testInstallBundleStringInputStream() {
+ defaultSetUp();
+
+ // TODO
+ }
+
+ @Test
+ public void testInstallBundleString() {
+ defaultSetUp();
+
+ // TODO
+ }
+
+ @Test
+ public void testContains() throws BundleException {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ assertTrue(r.contains(this.mockBundle));
+ }
+
+ @Test
+ public void testDoesNotContain() throws BundleException {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ assertFalse(r.contains(this.mockBundle));
+ }
+
+ @Test
+ public void testGetBundle() throws BundleException {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ assertEquals(this.mockBundle, r.getBundle(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION));
+ }
+
+ @Test
+ public void testGetBundleNotFound() throws BundleException {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(this.mockBundle);
+ assertNull(r.getBundle(BUNDLE_SYMBOLIC_NAME_2, BUNDLE_VERSION));
+ }
+
+ @Test
+ public void testConnectRegion() throws BundleException {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.connectRegion(this.mockRegion, this.mockRegionFilter);
+ }
+
+ @Test
+ public void testEquals() {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ Region s = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ assertEquals(r, r);
+ assertEquals(r, s);
+ assertEquals(r.hashCode(), s.hashCode());
+ }
+
+ @Test
+ public void testNotEqual() {
+ defaultSetUp();
+
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ Region s = new BundleIdBasedRegion(OTHER_REGION_NAME, this.mockGraph, this.mockBundleContext);
+ assertFalse(r.equals(s));
+ assertFalse(r.equals(null));
+ }
+
+ @Test
+ public void testAddRemoveBundleId() {
+ defaultSetUp();
+ Region r = new BundleIdBasedRegion(REGION_NAME, this.mockGraph, this.mockBundleContext);
+ r.addBundle(TEST_BUNDLE_ID);
+ assertTrue(r.contains(TEST_BUNDLE_ID));
+ r.removeBundle(TEST_BUNDLE_ID);
+ assertFalse(r.contains(TEST_BUNDLE_ID));
+
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java
new file mode 100644
index 00000000..0eb4bb56
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Set;
+
+import org.easymock.EasyMock;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.util.math.OrderedPair;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+
+public class StandardRegionDigraphTests {
+
+ private RegionDigraph digraph;
+
+ private Region mockRegion1;
+
+ private Region mockRegion2;
+
+ private Region mockRegion3;
+
+ private RegionFilter regionFilter1;
+
+ private RegionFilter regionFilter2;
+
+ private Bundle mockBundle;
+
+ @Before
+ public void setUp() throws Exception {
+ this.digraph = new StandardRegionDigraph();
+
+ this.mockRegion1 = EasyMock.createMock(Region.class);
+ EasyMock.expect(this.mockRegion1.getName()).andReturn("mockRegion1").anyTimes();
+
+ this.mockRegion2 = EasyMock.createMock(Region.class);
+ EasyMock.expect(this.mockRegion2.getName()).andReturn("mockRegion2").anyTimes();
+
+ this.mockRegion3 = EasyMock.createMock(Region.class);
+ EasyMock.expect(this.mockRegion3.getName()).andReturn("mockRegion3").anyTimes();
+
+ this.regionFilter1 = EasyMock.createMock(RegionFilter.class);
+ this.regionFilter2 = EasyMock.createMock(RegionFilter.class);
+ this.mockBundle = EasyMock.createMock(Bundle.class);
+ }
+
+ private void setDefaultMockFilters() {
+ setMockFilterAllowedBundles(this.regionFilter1);
+ setMockFilterAllowedBundles(this.regionFilter2);
+ }
+
+ private void setMockFilterAllowedBundles(RegionFilter regionFilter) {
+ EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.isA(String.class), EasyMock.isA(Version.class))).andReturn(false).anyTimes();
+ }
+
+ private void setMockFilterAllowedBundle(RegionFilter regionFilter, OrderedPair<String, Version> bundle) {
+ EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.eq(bundle.getFirst()), EasyMock.eq(bundle.getSecond()))).andReturn(true).anyTimes();
+ EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.not(EasyMock.eq(bundle.getFirst())), EasyMock.eq(bundle.getSecond()))).andReturn(false).anyTimes();
+ EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.eq(bundle.getFirst()), EasyMock.not(EasyMock.eq(bundle.getSecond())))).andReturn(false).anyTimes();
+ EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.not(EasyMock.eq(bundle.getFirst())), EasyMock.not(EasyMock.eq(bundle.getSecond())))).andReturn(false).anyTimes();
+ }
+
+ private void replayMocks() {
+ EasyMock.replay(this.mockRegion1, this.mockRegion2, this.mockRegion3, this.regionFilter1, this.regionFilter2, this.mockBundle);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EasyMock.verify(this.mockRegion1, this.mockRegion2, this.mockRegion3, this.regionFilter1, this.regionFilter2, this.mockBundle);
+ }
+
+ @Test
+ public void testConnect() throws BundleException {
+ setDefaultMockFilters();
+ replayMocks();
+
+ this.digraph.connect(this.mockRegion1, this.regionFilter1, this.mockRegion2);
+ }
+
+ @Test
+ public void testConnectWithFilterContents() throws BundleException {
+ OrderedPair<String, Version> b1 = new OrderedPair<String, Version>("b1", new Version("0"));
+ setMockFilterAllowedBundle(this.regionFilter1, b1);
+ EasyMock.expect(this.mockRegion1.getBundle(b1.getFirst(), b1.getSecond())).andReturn(null).anyTimes();
+
+ OrderedPair<String, Version> b2 = new OrderedPair<String, Version>("b2", new Version("0"));
+ setMockFilterAllowedBundle(this.regionFilter2, b2);
+ EasyMock.expect(this.mockRegion1.getBundle(b2.getFirst(), b2.getSecond())).andReturn(null).anyTimes();
+
+ replayMocks();
+
+ this.digraph.connect(this.mockRegion1, this.regionFilter1, this.mockRegion2);
+ this.digraph.connect(this.mockRegion1, this.regionFilter2, this.mockRegion3);
+ }
+
+ @Test(expected = BundleException.class)
+ public void testConnectLoop() throws BundleException {
+ setDefaultMockFilters();
+ replayMocks();
+
+ this.digraph.connect(this.mockRegion1, this.regionFilter1, this.mockRegion1);
+ }
+
+ @Test(expected = BundleException.class)
+ public void testDuplicateConnection() throws BundleException {
+ setDefaultMockFilters();
+ replayMocks();
+
+ this.digraph.connect(this.mockRegion1, this.regionFilter1, this.mockRegion2);
+ this.digraph.connect(this.mockRegion1, this.regionFilter2, this.mockRegion2);
+ }
+
+ @Test
+ public void testAddRegion() {
+ setDefaultMockFilters();
+ replayMocks();
+
+ this.digraph.addRegion(this.mockRegion1);
+ boolean found = false;
+ for (Region region : this.digraph) {
+ if (this.mockRegion1.equals(region)) {
+ found = true;
+ }
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testGetEdges() throws BundleException {
+ setDefaultMockFilters();
+ replayMocks();
+
+ this.digraph.connect(this.mockRegion1, this.regionFilter1, this.mockRegion2);
+ this.digraph.connect(this.mockRegion1, this.regionFilter2, this.mockRegion3);
+ this.digraph.connect(this.mockRegion2, this.regionFilter2, this.mockRegion1);
+
+ Set<FilteredRegion> edges = this.digraph.getEdges(this.mockRegion1);
+
+ assertEquals(2, edges.size());
+
+ for (FilteredRegion edge : edges) {
+ if (edge.getRegion().equals(this.mockRegion2)) {
+ assertEquals(this.regionFilter1, edge.getFilter());
+ } else if (edge.getRegion().equals(this.mockRegion3)) {
+ assertEquals(this.regionFilter2, edge.getFilter());
+ } else {
+ fail("unexpected edge");
+ }
+ }
+ }
+
+ @Test
+ public void testRemoveRegion() throws BundleException {
+ setDefaultMockFilters();
+ replayMocks();
+
+ this.digraph.connect(this.mockRegion1, this.regionFilter1, this.mockRegion2);
+ this.digraph.connect(this.mockRegion2, this.regionFilter2, this.mockRegion1);
+ assertNotNull(this.digraph.getRegion("mockRegion1"));
+ assertNotNull(this.digraph.getRegion("mockRegion2"));
+ this.digraph.removeRegion(this.mockRegion1);
+ assertNull(this.digraph.getRegion("mockRegion1"));
+ assertNotNull(this.digraph.getRegion("mockRegion2"));
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java
new file mode 100644
index 00000000..b8936829
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the Eclipse Virgo project.
+ *
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VMware Inc. - initial contribution
+ */
+
+package org.eclipse.virgo.kernel.osgi.region.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.easymock.EasyMock;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy;
+import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Filter;
+import org.osgi.framework.Version;
+
+public class StandardRegionFilterTests {
+
+ private static final String BUNDLE_SYMBOLIC_NAME = "A";
+
+ private static final Version BUNDLE_VERSION = new Version("0");
+
+ private RegionFilter regionFilter;
+
+ private Filter mockFilter;
+
+ private RegionPackageImportPolicy packageImportPolicy;
+
+ @Before
+ public void setUp() throws Exception {
+ this.regionFilter = new StandardRegionFilter();
+ this.mockFilter = EasyMock.createMock(Filter.class);
+ this.packageImportPolicy = EasyMock.createMock(RegionPackageImportPolicy.class);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testAllowBundle() {
+ this.regionFilter.allowBundle(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION);
+ assertTrue(this.regionFilter.isBundleAllowed(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION));
+ }
+
+ @Test
+ public void testSetPackageImportPolicy() {
+ this.regionFilter.setPackageImportPolicy(this.packageImportPolicy);
+ assertEquals(this.packageImportPolicy, this.regionFilter.getPackageImportPolicy());
+ }
+
+ @Test
+ public void testSetServiceFilter() {
+ this.regionFilter.setServiceFilter(this.mockFilter);
+ assertEquals(this.mockFilter, this.regionFilter.getServiceFilter());
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/Activator.java b/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/Activator.java
index ebd6d8ae..c041d3a6 100644
--- a/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/Activator.java
+++ b/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/Activator.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/internal/OsgiKernelShellCommand.java b/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/internal/OsgiKernelShellCommand.java
index 43868202..6971b339 100644
--- a/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/internal/OsgiKernelShellCommand.java
+++ b/org.eclipse.virgo.kernel.osgicommand/src/main/java/org/eclipse/virgo/kernel/osgicommand/internal/OsgiKernelShellCommand.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.shell/.classpath b/org.eclipse.virgo.kernel.shell/.classpath
index b2213bdb..30d172d5 100644
--- a/org.eclipse.virgo.kernel.shell/.classpath
+++ b/org.eclipse.virgo.kernel.shell/.classpath
@@ -46,6 +46,7 @@
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.kernel.deployer"/>
<classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.virgo.repository/org.eclipse.virgo.repository/3.0.0.D-20110201142541/org.eclipse.virgo.repository-3.0.0.D-20110201142541.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.virgo.repository/org.eclipse.virgo.repository/3.0.0.D-20110201142541/org.eclipse.virgo.repository-sources-3.0.0.D-20110201142541.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.kernel.model"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi.services/3.3.0.v20101018/org.eclipse.osgi.services-3.3.0.v20101018.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi.services/3.3.0.v20101018/org.eclipse.osgi.services-sources-3.3.0.v20101018.jar"/>
<classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse/equinox-event/1.2.100.v20101208/equinox-event-1.2.100.v20101208.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
diff --git a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/CommandExecutor.java b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/CommandExecutor.java
index f0aa3c64..8fc7bb5c 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/CommandExecutor.java
+++ b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/CommandExecutor.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/LinePrinter.java b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/LinePrinter.java
index 33f41a8b..ffc97cc7 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/LinePrinter.java
+++ b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/LinePrinter.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SessionCommandExecutor.java b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SessionCommandExecutor.java
index 26eba1a0..aa0aab32 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SessionCommandExecutor.java
+++ b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SessionCommandExecutor.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SingleSessionCommandExecutor.java b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SingleSessionCommandExecutor.java
index d41129f2..21258b80 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SingleSessionCommandExecutor.java
+++ b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/internal/SingleSessionCommandExecutor.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardQuasiLiveFramework.java b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardQuasiLiveFramework.java
index 66e4772e..f03b466d 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardQuasiLiveFramework.java
+++ b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardQuasiLiveFramework.java
@@ -120,4 +120,11 @@ final class StandardQuasiLiveFramework implements QuasiFramework {
return this.quasiFramework.getBundle(name, version);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void destroy() {
+ }
+
}
diff --git a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateService.java b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateService.java
index a7ccadd5..3e020088 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateService.java
+++ b/org.eclipse.virgo.kernel.shell/src/main/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateService.java
@@ -14,14 +14,9 @@ package org.eclipse.virgo.kernel.shell.state.internal;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
-import java.util.Map.Entry;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.springframework.util.AntPathMatcher;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiBundle;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiExportPackage;
@@ -29,30 +24,64 @@ import org.eclipse.virgo.kernel.osgi.quasi.QuasiFramework;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFrameworkFactory;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiImportPackage;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiResolutionFailure;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
import org.eclipse.virgo.kernel.shell.state.QuasiLiveBundle;
import org.eclipse.virgo.kernel.shell.state.QuasiLiveService;
import org.eclipse.virgo.kernel.shell.state.QuasiPackage;
import org.eclipse.virgo.kernel.shell.state.StateService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.springframework.util.AntPathMatcher;
/**
*
*/
final public class StandardStateService implements StateService {
+
+ private static final String REGION_KERNEL = "org.eclipse.virgo.region.kernel";
private final QuasiFrameworkFactory quasiFrameworkFactory;
private final BundleContext bundleContext;
- public StandardStateService(QuasiFrameworkFactory quasiFrameworkFactory, BundleContext bundleContext) {
+ private final RegionDigraph regionDigraph;
+
+ private final Region kernelRegion;
+
+ public StandardStateService(QuasiFrameworkFactory quasiFrameworkFactory, BundleContext bundleContext, RegionDigraph regionDigraph) {
this.quasiFrameworkFactory = quasiFrameworkFactory;
this.bundleContext = bundleContext;
+ this.regionDigraph = regionDigraph;
+ this.kernelRegion = getKernelRegion(regionDigraph);
+ }
+
+ private Region getKernelRegion(RegionDigraph regionDigraph) {
+ return regionDigraph.getRegion(REGION_KERNEL);
}
/**
* {@inheritDoc}
*/
public List<QuasiBundle> getAllBundles(File source) {
- return this.getQuasiFramework(source).getBundles();
+ List<QuasiBundle> bundles = this.getQuasiFramework(source).getBundles();
+ if (source == null) {
+ List<QuasiBundle> userRegionBundles = new ArrayList<QuasiBundle>();
+ for (QuasiBundle bundle : bundles) {
+ long bundleId = bundle.getBundleId();
+ if (bundleId == 0L || !this.kernelRegion.equals(getRegion(bundleId))) {
+ userRegionBundles.add(bundle);
+ }
+ }
+ return userRegionBundles;
+ } else {
+ return bundles;
+ }
+ }
+
+ private Region getRegion(long bundleId) {
+ return this.regionDigraph.getRegion(bundleId);
}
/**
diff --git a/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/module-context.xml b/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/module-context.xml
index 76b8fe30..6835911e 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/module-context.xml
+++ b/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/module-context.xml
@@ -28,8 +28,9 @@
<bean id="stateService" class="org.eclipse.virgo.kernel.shell.state.internal.StandardStateService">
<constructor-arg ref="quasiFrameworkFactory" />
<constructor-arg ref="userRegionBundleContext" />
+ <constructor-arg ref="regionDigraph" />
</bean>
-
+
<bean id="installCommand" class="org.eclipse.virgo.kernel.shell.internal.commands.InstallCommand"/>
<bean id="bundleCommands" class="org.eclipse.virgo.kernel.shell.internal.commands.BundleCommands">
diff --git a/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/osgi-context.xml b/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/osgi-context.xml
index bc6bfb14..11c74046 100644
--- a/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/osgi-context.xml
+++ b/org.eclipse.virgo.kernel.shell/src/main/resources/META-INF/spring/osgi-context.xml
@@ -28,7 +28,9 @@
<osgi:reference id="deployer" interface="org.eclipse.virgo.kernel.deployer.core.ApplicationDeployer"/>
<osgi:service ref="modelAccessorHelper" interface="org.eclipse.virgo.kernel.shell.model.helper.RamAccessorHelper" />
-
+
+ <osgi:reference id="regionDigraph" interface="org.eclipse.virgo.kernel.osgi.region.RegionDigraph" />
+
<!-- SERVICES FOR THE TYPE CONVERTERS -->
<osgi:service ref="longConverter" interface="org.eclipse.virgo.kernel.shell.Converter">
diff --git a/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateServiceTests.java b/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateServiceTests.java
index a6096e93..0745cacb 100644
--- a/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateServiceTests.java
+++ b/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/state/internal/StandardStateServiceTests.java
@@ -18,16 +18,16 @@ import static org.junit.Assert.assertNull;
import java.io.File;
import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-
+import org.easymock.EasyMock;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiBundle;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFrameworkFactory;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
import org.eclipse.virgo.kernel.shell.state.QuasiLiveService;
-import org.eclipse.virgo.kernel.shell.state.internal.StandardStateService;
import org.eclipse.virgo.kernel.shell.stubs.StubQuasiFrameworkFactory;
-
import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.junit.Before;
+import org.junit.Test;
/**
* <p>
@@ -48,25 +48,37 @@ public class StandardStateServiceTests {
private StubBundleContext stubBundleContext;
private QuasiFrameworkFactory stubQuasiFrameworkFactory;
-
- /**
- * @throws java.lang.Exception
- */
- @Before
- public void setUp() throws Exception {
- this.stubBundleContext = new StubBundleContext();
- this.stubQuasiFrameworkFactory = new StubQuasiFrameworkFactory();
- this.standardStateService = new StandardStateService(this.stubQuasiFrameworkFactory, this.stubBundleContext);
- }
-
- @Test
- public void getAllBundlesNullDump() {
- List<QuasiBundle> result = this.standardStateService.getAllBundles(null);
- assertNotNull(result);
- assertEquals(1, result.size());
- }
-
- @Test
+
+ private Region mockUserRegion;
+
+ private RegionDigraph mockRegionDigraph;
+
+ private Region mockKernelRegion;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ this.stubBundleContext = new StubBundleContext();
+ this.stubQuasiFrameworkFactory = new StubQuasiFrameworkFactory();
+ this.mockUserRegion = EasyMock.createMock(Region.class);
+ this.mockKernelRegion = EasyMock.createMock(Region.class);
+ this.mockRegionDigraph = EasyMock.createMock(RegionDigraph.class);
+ EasyMock.expect(this.mockRegionDigraph.getRegion(EasyMock.anyLong())).andReturn(this.mockUserRegion).anyTimes();
+ EasyMock.expect(this.mockRegionDigraph.getRegion(EasyMock.eq("org.eclipse.virgo.region.kernel"))).andReturn(this.mockKernelRegion).anyTimes();
+ EasyMock.replay(this.mockUserRegion, this.mockKernelRegion, this.mockRegionDigraph);
+ this.standardStateService = new StandardStateService(this.stubQuasiFrameworkFactory, this.stubBundleContext, this.mockRegionDigraph);
+ }
+
+ @Test
+ public void getAllBundlesNullDump() {
+ List<QuasiBundle> result = this.standardStateService.getAllBundles(null);
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ }
+
+ @Test
public void getAllBundlesFromDump() {
List<QuasiBundle> result = this.standardStateService.getAllBundles(TEST_DUMP_FILE);
assertNotNull(result);
diff --git a/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/stubs/StubQuasiFramework.java b/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/stubs/StubQuasiFramework.java
index 702a8688..b6ad4707 100644
--- a/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/stubs/StubQuasiFramework.java
+++ b/org.eclipse.virgo.kernel.shell/src/test/java/org/eclipse/virgo/kernel/shell/stubs/StubQuasiFramework.java
@@ -83,4 +83,8 @@ public class StubQuasiFramework implements QuasiFramework{
return null;
}
+ @Override
+ public void destroy() {
+ }
+
}
diff --git a/org.eclipse.virgo.kernel.shutdown/src/main/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfiguration.java b/org.eclipse.virgo.kernel.shutdown/src/main/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfiguration.java
index 31800471..7f30af01 100644
--- a/org.eclipse.virgo.kernel.shutdown/src/main/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfiguration.java
+++ b/org.eclipse.virgo.kernel.shutdown/src/main/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfiguration.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.shutdown/src/test/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfigurationTests.java b/org.eclipse.virgo.kernel.shutdown/src/test/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfigurationTests.java
index 9571918d..5d29d43b 100644
--- a/org.eclipse.virgo.kernel.shutdown/src/test/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfigurationTests.java
+++ b/org.eclipse.virgo.kernel.shutdown/src/test/java/org/eclipse/virgo/kernel/shutdown/KernelAuthenticationConfigurationTests.java
@@ -1,7 +1,7 @@
/*******************************************************************************
* This file is part of the Virgo Web Server.
*
- * Copyright (c) 2010 Eclipse Foundation.
+ * Copyright (c) 2010 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
diff --git a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/QuasiFrameworkIntegrationTests.java b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/QuasiFrameworkIntegrationTests.java
index 5b1b4bbc..774067a1 100644
--- a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/QuasiFrameworkIntegrationTests.java
+++ b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/QuasiFrameworkIntegrationTests.java
@@ -15,6 +15,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -69,6 +70,11 @@ public class QuasiFrameworkIntegrationTests extends AbstractKernelIntegrationTes
this.quasiFramework = this.quasiFrameworkFactory.create();
Assert.assertNotNull(this.quasiFramework);
}
+
+ @After
+ public void tearDown() {
+ this.quasiFramework.destroy();
+ }
@Test
public void testInstall() throws Exception {
diff --git a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/RegionTests.java b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/RegionTests.java
index eb668b1b..6bf51bc4 100644
--- a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/RegionTests.java
+++ b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgi/test/RegionTests.java
@@ -36,7 +36,6 @@ public class RegionTests extends AbstractKernelIntegrationTest {
Region userRegion = (Region) this.kernelContext.getService(serviceReferences[0]);
assertNotNull(userRegion);
- assertNotNull(userRegion.getBundleContext());
}
private ServiceReference<?>[] lookupRegionServices(String name) throws InvalidSyntaxException {
diff --git a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgicommand/helper/test/ClassLoadingHelperIntegrationTests.java b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgicommand/helper/test/ClassLoadingHelperIntegrationTests.java
index 205ee8a7..7d3bfa23 100644
--- a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgicommand/helper/test/ClassLoadingHelperIntegrationTests.java
+++ b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/osgicommand/helper/test/ClassLoadingHelperIntegrationTests.java
@@ -56,15 +56,14 @@ public class ClassLoadingHelperIntegrationTests extends AbstractKernelIntegratio
// execute initialization code
super.setup();
- // get osgicommand bundle
- ServiceReference<PackageAdmin> reference = context.getServiceReference(PackageAdmin.class);
- PackageAdmin packageAdmin = context.getService(reference);
- Bundle[] bundles = packageAdmin.getBundles(SHELL_COMMANDS_BUNDLE_NAME, null);
- assertNotNull("No bundles with symbolic name [" + SHELL_COMMANDS_BUNDLE_NAME + "] found in bundles set " + Arrays.toString(context.getBundles()),
- bundles);
- assertTrue("Found [" + bundles.length + "] bundles with symbolic name [" + SHELL_COMMANDS_BUNDLE_NAME + "] in bundles set " + Arrays.toString(context.getBundles()),
- bundles.length == 1);
- this.shellCommandsBundle = bundles[0];
+ for (Bundle bundle : context.getBundles()) {
+ if (SHELL_COMMANDS_BUNDLE_NAME.equals(bundle.getSymbolicName())) {
+ this.shellCommandsBundle = bundle;
+ }
+ }
+
+ assertNotNull("No bundles with symbolic name [" + SHELL_COMMANDS_BUNDLE_NAME + "] found in bundles " + context.getBundles(),
+ this.shellCommandsBundle);
// get this bundle
this.currentBundle = context.getBundle();
diff --git a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/test/AbstractKernelIntegrationTest.java b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/test/AbstractKernelIntegrationTest.java
index ad8f4617..d52a11f6 100644
--- a/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/test/AbstractKernelIntegrationTest.java
+++ b/org.eclipse.virgo.kernel.test/src/test/java/org/eclipse/virgo/kernel/test/AbstractKernelIntegrationTest.java
@@ -16,20 +16,16 @@ import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import org.eclipse.virgo.kernel.osgi.framework.OsgiFramework;
+import org.eclipse.virgo.test.framework.dmkernel.DmKernelTestRunner;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
-import org.osgi.service.framework.SurrogateBundle;
-
-import org.eclipse.virgo.kernel.osgi.framework.OsgiFramework;
-import org.eclipse.virgo.test.framework.dmkernel.DmKernelTestRunner;
@RunWith(DmKernelTestRunner.class)
-@SuppressWarnings("deprecation")
public abstract class AbstractKernelIntegrationTest {
protected volatile BundleContext kernelContext;
@@ -45,10 +41,11 @@ public abstract class AbstractKernelIntegrationTest {
this.framework = this.context.getService(serviceReference);
}
- Bundle bundle = this.context.getBundle(1);
- if (bundle instanceof SurrogateBundle) {
- this.kernelContext = ((SurrogateBundle)bundle).getCompositeBundleContext();
- }
+ this.kernelContext = getKernelContext();
+ }
+
+ private BundleContext getKernelContext() {
+ return this.context.getBundle(0L).getBundleContext();
}
@BeforeClass
diff --git a/org.eclipse.virgo.kernel.test/src/test/resources/META-INF/test.config.properties b/org.eclipse.virgo.kernel.test/src/test/resources/META-INF/test.config.properties
index 4f7f2675..7cf66608 100644
--- a/org.eclipse.virgo.kernel.test/src/test/resources/META-INF/test.config.properties
+++ b/org.eclipse.virgo.kernel.test/src/test/resources/META-INF/test.config.properties
@@ -30,11 +30,12 @@ launcher.bundles =\
file:../ivy-cache/repository/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar,\
file:../org.eclipse.virgo.kernel.artifact/target/classes@start,\
file:../org.eclipse.virgo.kernel.services/target/classes@start,\
- file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
file:../org.eclipse.virgo.kernel.deployer/target/classes@start,\
file:../org.eclipse.virgo.kernel.model/target/classes@start,\
file:../org.eclipse.virgo.kernel.kerneldmfragment/target/classes,\
file:../org.eclipse.virgo.kernel.shell/target/classes@start,\
+ file:../org.eclipse.virgo.kernel.osgi/target/classes@start,\
+ file:../org.eclipse.virgo.kernel.userregionfactory/target/classes@start,\
file:../org.eclipse.virgo.kernel.osgicommand/target/classes@start
org.eclipse.virgo.test.properties.include=file:../build.versions,file:../build.properties
@@ -45,6 +46,9 @@ osgi.context.bootdelegation=false
osgi.compatibility.bootdelegation=false
osgi.clean=true
osgi.configuration.area=target
+org.osgi.framework.bsnversion=multiple
+
+osgi.console=2401
org.apache.felix.eventadmin.Timeout=0
diff --git a/org.eclipse.virgo.kernel.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties b/org.eclipse.virgo.kernel.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties
index 860c183a..126a02b7 100644
--- a/org.eclipse.virgo.kernel.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties
+++ b/org.eclipse.virgo.kernel.test/src/test/resources/config/org.eclipse.virgo.kernel.userregion.properties
@@ -37,6 +37,10 @@ packageImports =\
org.aspectj.*;version="[1.6.5.RELEASE,2.0.0)",\
org.junit;version="[4.7.0,5.0.0)",\
org.junit.runner;version="[4.7.0,5.0.0)",\
+ org.osgi.*;version="0",\
+ org.eclipse.osgi.*;version="0",\
+ javax.management;version="0",\
+ javax.management.*;version="0",\
org.osgi.service.cm;version="0",\
org.osgi.service.log;version="0",\
org.osgi.service.event;version="0",\
@@ -44,6 +48,8 @@ packageImports =\
org.slf4j.spi;version="[1.6.1,2)"
serviceImports =\
+ org.eclipse.virgo.kernel.osgi.region.Region,\
+ org.eclipse.virgo.kernel.osgi.region.RegionDigraph,\
org.eclipse.virgo.kernel.deployer.core.ApplicationDeployer,\
org.eclipse.virgo.kernel.deployer.core.DeployUriNormaliser,\
org.eclipse.virgo.kernel.install.artifact.ScopeServiceRepository,\
@@ -55,11 +61,15 @@ serviceImports =\
org.eclipse.virgo.medic.eventlog.EventLoggerFactory,\
org.eclipse.virgo.repository.Repository,\
org.eclipse.virgo.kernel.core.Shutdown,\
+ org.osgi.framework.hooks.resolver.ResolverHookFactory,\
org.osgi.service.cm.ConfigurationAdmin,\
org.osgi.service.event.EventAdmin,\
+ org.eclipse.virgo.medic.eventlog.EventLogger,\
org.eclipse.virgo.medic.dump.DumpGenerator,\
org.eclipse.virgo.kernel.shim.scope.ScopeFactory,\
- org.eclipse.virgo.kernel.shim.serviceability.TracingService
+ org.eclipse.virgo.kernel.shim.serviceability.TracingService,\
+ org.eclipse.osgi.service.resolver.PlatformAdmin,\
+ org.osgi.service.packageadmin.PackageAdmin
serviceExports =\
org.eclipse.virgo.kernel.install.artifact.InstallArtifactLifecycleListener,\
@@ -71,15 +81,9 @@ serviceExports =\
org.eclipse.virgo.kernel.osgi.framework.OsgiFramework,\
org.eclipse.virgo.kernel.osgi.framework.ImportExpander,\
org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil,\
+ org.eclipse.virgo.kernel.osgi.region.Region,\
org.osgi.service.event.EventHandler,\
org.osgi.service.cm.ConfigurationListener,\
org.osgi.service.cm.ManagedService,\
- org.osgi.service.cm.ManagedServiceFactory
-
-inheritedFrameworkProperties =\
- osgi.java.profile,\
- osgi.parentClassloader,\
- osgi.context.bootdelegation,\
- osgi.compatibility.bootdelegation,\
- osgi.java.profile.bootdelegation,\
- osgi.hook.configurators.include
+ org.osgi.service.cm.ManagedServiceFactory,\
+ org.osgi.framework.BundleContext
diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/Activator.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/Activator.java
index dadecb47..2f16caee 100644
--- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/Activator.java
+++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/Activator.java
@@ -31,6 +31,8 @@ import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkUtils;
import org.eclipse.virgo.kernel.osgi.framework.OsgiServiceHolder;
import org.eclipse.virgo.kernel.osgi.framework.PackageAdminUtil;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFrameworkFactory;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
import org.eclipse.virgo.kernel.shim.scope.ScopeFactory;
import org.eclipse.virgo.kernel.userregion.internal.equinox.EquinoxHookRegistrar;
import org.eclipse.virgo.kernel.userregion.internal.equinox.EquinoxOsgiFramework;
@@ -43,6 +45,7 @@ import org.eclipse.virgo.kernel.userregion.internal.quasi.StandardQuasiFramework
import org.eclipse.virgo.kernel.userregion.internal.quasi.StandardResolutionFailureDetective;
import org.eclipse.virgo.medic.dump.DumpContributor;
import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
import org.eclipse.virgo.osgi.extensions.equinox.hooks.MetaInfResourceClassLoaderDelegateHook;
import org.eclipse.virgo.repository.Repository;
import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
@@ -91,7 +94,9 @@ public class Activator implements BundleActivator {
Repository repository = OsgiFrameworkUtils.getService(context, Repository.class).getService();
PackageAdmin packageAdmin = OsgiFrameworkUtils.getService(context, PackageAdmin.class).getService();
- EventLogger eventLogger = OsgiFrameworkUtils.getService(context, EventLogger.class).getService();
+ EventLogger eventLogger = OsgiFrameworkUtils.getService(context, EventLoggerFactory.class).getService().createEventLogger(context.getBundle());
+
+ RegionDigraph regionDigraph = OsgiFrameworkUtils.getService(context, RegionDigraph.class).getService();
ImportExpansionHandler importExpansionHandler = createImportExpansionHandler(context, packageAdmin, repository, eventLogger);
this.registrationTracker.track(context.registerService(ImportExpander.class.getName(), importExpansionHandler, null));
@@ -104,7 +109,7 @@ public class Activator implements BundleActivator {
DumpContributor dumpContributor = createResolutionDumpContributor(context);
this.registrationTracker.track(context.registerService(DumpContributor.class.getName(), dumpContributor, null));
- QuasiFrameworkFactory quasiFrameworkFactory = createQuasiFrameworkFactory(context, rfd, repository, bundleTransformerHandler);
+ QuasiFrameworkFactory quasiFrameworkFactory = createQuasiFrameworkFactory(context, rfd, repository, bundleTransformerHandler, regionDigraph);
this.registrationTracker.track(context.registerService(QuasiFrameworkFactory.class.getName(), quasiFrameworkFactory, null));
EquinoxHookRegistrar hookRegistrar = createHookRegistrar(context, packageAdmin, bundleTransformerHandler);
@@ -138,8 +143,8 @@ public class Activator implements BundleActivator {
}
private QuasiFrameworkFactory createQuasiFrameworkFactory(BundleContext bundleContext, ResolutionFailureDetective detective,
- Repository repository, TransformedManifestProvidingBundleFileWrapper bundleTransformerHandler) {
- return new StandardQuasiFrameworkFactory(bundleContext, detective, repository, bundleTransformerHandler);
+ Repository repository, TransformedManifestProvidingBundleFileWrapper bundleTransformerHandler, RegionDigraph regionDigraph) {
+ return new StandardQuasiFrameworkFactory(bundleContext, detective, repository, bundleTransformerHandler, regionDigraph);
}
private TransformedManifestProvidingBundleFileWrapper createBundleTransformationHandler(ImportExpansionHandler importExpander) {
diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/equinox/UsesAnalyser.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/equinox/UsesAnalyser.java
index 18331325..9e5dacf9 100644
--- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/equinox/UsesAnalyser.java
+++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/equinox/UsesAnalyser.java
@@ -292,7 +292,7 @@ public final class UsesAnalyser {
private final static String stringOf(BundleDescription bundle) {
StringBuilder sb = new StringBuilder("'");
- sb.append(bundle.getSymbolicName()).append("_").append(bundle.getVersion()).append("'");
+ sb.append(bundle.getSymbolicName()).append("_").append(bundle.getVersion()).append("[").append(bundle.getBundleId()).append("]").append("'");
return sb.toString();
}
diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java
index 6bd9bc90..599bc9c7 100644
--- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java
+++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java
@@ -37,23 +37,22 @@ import org.eclipse.osgi.service.resolver.StateDelta;
import org.eclipse.osgi.service.resolver.StateObjectFactory;
import org.eclipse.osgi.service.resolver.VersionConstraint;
import org.eclipse.osgi.service.resolver.VersionRange;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import org.eclipse.virgo.kernel.artifact.bundle.BundleBridge;
import org.eclipse.virgo.kernel.osgi.framework.UnableToSatisfyBundleDependenciesException;
import org.eclipse.virgo.kernel.osgi.framework.UnableToSatisfyDependenciesException;
+import org.eclipse.virgo.kernel.osgi.region.Region;
import org.eclipse.virgo.kernel.userregion.internal.equinox.ResolutionDumpContributor;
import org.eclipse.virgo.kernel.userregion.internal.quasi.ResolutionFailureDetective.ResolverErrorsHolder;
-
-import org.eclipse.virgo.kernel.artifact.bundle.BundleBridge;
import org.eclipse.virgo.medic.dump.DumpGenerator;
import org.eclipse.virgo.repository.ArtifactDescriptor;
import org.eclipse.virgo.repository.Attribute;
import org.eclipse.virgo.repository.Query;
import org.eclipse.virgo.repository.Repository;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Calculates the dependencies of a given set of {@link BundleDescription BundleDescriptions}.
@@ -66,6 +65,8 @@ import org.eclipse.virgo.repository.Repository;
*/
public final class DependencyCalculator {
+ private static final String REGION_LOCATION_DELIMITER = "@";
+
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final ResolutionFailureDetective detective;
@@ -80,12 +81,14 @@ public final class DependencyCalculator {
private final DumpGenerator dumpGenerator;
+ private Region coregion;
+
public DependencyCalculator(StateObjectFactory stateObjectFactory, ResolutionFailureDetective detective, Repository repository,
BundleContext bundleContext) {
this.repository = repository;
this.detective = detective;
this.stateObjectFactory = stateObjectFactory;
- this.dumpGenerator = (DumpGenerator) bundleContext.getService(bundleContext.getServiceReference(DumpGenerator.class.getName()));
+ this.dumpGenerator = bundleContext.getService(bundleContext.getServiceReference(DumpGenerator.class));
}
/**
@@ -108,16 +111,18 @@ public final class DependencyCalculator {
* returned depending on whether cloning some bundles may improve the chances of satisfying the constraints.
*
* @param state the <code>State</code> to satisfy against.
+ * @param coregion the coregion containing the side-state bundles
* @param bundles the bundles to calculate dependencies for.
* @return an array of descriptions of bundles that need to be added to the state to satisfy constraints.
- * @throws BundleException
- * @throws UnableToSatisfyDependenciesException
+ * @throws BundleException
+ * @throws UnableToSatisfyDependenciesException
*/
- public BundleDescription[] calculateDependencies(State state, BundleDescription[] bundles) throws BundleException,
+ public BundleDescription[] calculateDependencies(State state, Region coregion, BundleDescription[] bundles) throws BundleException,
UnableToSatisfyDependenciesException {
this.logger.info("Calculating missing dependencies of bundle(s) '{}'", bundles);
synchronized (this.monitor) {
-
+ this.coregion = coregion;
+ try {
doSatisfyConstraints(bundles, state);
StateDelta delta = state.resolve(bundles);
@@ -134,7 +139,7 @@ public final class DependencyCalculator {
for (ResolverError resolverError : resolverErrors) {
if (resolverError.getType() == ResolverError.IMPORT_PACKAGE_USES_CONFLICT) {
VersionConstraint unsatisfiedConstraint = resolverError.getUnsatisfiedConstraint();
- if ((unsatisfiedConstraint instanceof ImportPackageSpecification)) {
+ if (unsatisfiedConstraint instanceof ImportPackageSpecification) {
ImportPackageSpecification importPackageSpecification = (ImportPackageSpecification) unsatisfiedConstraint;
this.logger.debug("Uses conflict: package '{}' version '{}' bundle '{}' version '{}'", new Object[] {
importPackageSpecification.getName(), importPackageSpecification.getVersionRange(),
@@ -165,6 +170,9 @@ public final class DependencyCalculator {
BundleDescription[] dependencyDescriptions = dependencies.toArray(new BundleDescription[dependencies.size()]);
return dependencyDescriptions;
+ } finally {
+ this.coregion = null;
+ }
}
}
@@ -249,6 +257,7 @@ public final class DependencyCalculator {
for (BundleDescription constraintSatisfier : constraintsSatisfiers) {
if (!isBundlePresentInState(constraintSatisfier.getName(), constraintSatisfier.getVersion(), state)) {
state.addBundle(constraintSatisfier);
+ this.coregion.addBundle(constraintSatisfier.getBundleId());
doSatisfyConstraints(constraintSatisfier, state);
}
}
@@ -347,16 +356,15 @@ public final class DependencyCalculator {
Dictionary<String, String> manifest = BundleBridge.convertToDictionary(artifact);
try {
URI uri = artifact.getUri();
- if ("file".equals(uri.getScheme())) {
- return this.stateObjectFactory.createBundleDescription(state, manifest, new File(uri).getAbsolutePath(),
- this.bundleId.getAndIncrement());
- } else {
- return this.stateObjectFactory.createBundleDescription(state, manifest, uri.toString(), this.bundleId.getAndIncrement());
- }
+ String installLocation = "file".equals(uri.getScheme()) ? new File(uri).getAbsolutePath() : uri.toString();
+ BundleDescription bundleDescription = this.stateObjectFactory.createBundleDescription(state, manifest, this.coregion.getName()
+ + REGION_LOCATION_DELIMITER + installLocation, this.bundleId.getAndIncrement());
+ this.coregion.addBundle(bundleDescription.getBundleId());
+ return bundleDescription;
} catch (RuntimeException e) {
throw new BundleException("Unable to read bundle at '" + artifact.getUri() + "'", e);
} catch (BundleException be) {
- throw new BundleException("Failed to create BundleDescriptor for artifact at '" + artifact.getUri() + "'", be);
+ throw new BundleException("Failed to create BundleDescriptor for artifact at '" + artifact.getUri() + "'", be);
}
}
diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFramework.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFramework.java
index edb8fe90..33014a56 100644
--- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFramework.java
+++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFramework.java
@@ -12,7 +12,11 @@
package org.eclipse.virgo.kernel.userregion.internal.quasi;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
import java.net.URI;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
@@ -20,6 +24,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.eclipse.osgi.internal.resolver.StateImpl;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
@@ -28,25 +33,31 @@ import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.service.resolver.StateHelper;
import org.eclipse.osgi.service.resolver.StateObjectFactory;
import org.eclipse.osgi.service.resolver.VersionConstraint;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import org.eclipse.virgo.kernel.core.FatalKernelException;
import org.eclipse.virgo.kernel.osgi.framework.ManifestTransformer;
import org.eclipse.virgo.kernel.osgi.framework.UnableToSatisfyDependenciesException;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiBundle;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFramework;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiResolutionFailure;
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
import org.eclipse.virgo.kernel.userregion.internal.equinox.TransformedManifestProvidingBundleFileWrapper;
import org.eclipse.virgo.kernel.userregion.internal.quasi.ResolutionFailureDetective.ResolverErrorsHolder;
import org.eclipse.virgo.repository.Repository;
import org.eclipse.virgo.util.common.StringUtils;
import org.eclipse.virgo.util.osgi.VersionRange;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* {@link StandardQuasiFramework} is the default implementation of {@link QuasiFramework}.
@@ -59,6 +70,14 @@ import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
*/
final class StandardQuasiFramework implements QuasiFramework {
+ private static final String REGION_LOCATION_DELIMITER = "@";
+
+ private static final String COREGION_SUFFIX = ".coregion";
+
+ private static final String REFERENCE_SCHEME = "reference:";
+
+ private static final String FILE_SCHEME = "file:";
+
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final Object monitor = new Object();
@@ -71,7 +90,7 @@ final class StandardQuasiFramework implements QuasiFramework {
* Track the bundles which are explicitly installed. These are input to the resolve method.
*/
private final List<StandardQuasiBundle> installedQuasiBundles = new ArrayList<StandardQuasiBundle>();
-
+
private volatile BundleDescription[] otherBundles;
private final ResolutionFailureDetective detective;
@@ -81,17 +100,44 @@ final class StandardQuasiFramework implements QuasiFramework {
private final DependencyCalculator dependencyCalculator;
private final StateHelper stateHelper;
-
+
private final TransformedManifestProvidingBundleFileWrapper bundleTransformationHandler;
- StandardQuasiFramework(BundleContext bundleContext, State state, PlatformAdmin platformAdmin, ResolutionFailureDetective detective, Repository repository, TransformedManifestProvidingBundleFileWrapper bundleTransformationHandler) {
+ private final RegionDigraph regionDigraph;
+
+ private Region coregion;
+
+ private final Region userRegion;
+
+ StandardQuasiFramework(BundleContext bundleContext, State state, PlatformAdmin platformAdmin, ResolutionFailureDetective detective,
+ Repository repository, TransformedManifestProvidingBundleFileWrapper bundleTransformationHandler, RegionDigraph regionDiagraph) {
this.bundleContext = bundleContext;
this.state = state;
this.stateObjectFactory = platformAdmin.getFactory();
this.detective = detective;
- this.dependencyCalculator = new DependencyCalculator(platformAdmin.getFactory(), this.detective, repository, this.bundleContext);
this.stateHelper = platformAdmin.getStateHelper();
this.bundleTransformationHandler = bundleTransformationHandler;
+ this.regionDigraph = regionDiagraph;
+ this.userRegion = regionDigraph.getRegion("org.eclipse.virgo.region.user");
+ setResolverHookFactory();
+
+ this.dependencyCalculator = new DependencyCalculator(platformAdmin.getFactory(), this.detective, repository, this.bundleContext);
+ }
+
+ private void setResolverHookFactory() {
+ // XXX Bug 332771: Temporary workaround since the resolver hook is not driven by default for State resolutions
+ if (this.state instanceof StateImpl) {
+ // Following not used as ServiceRegistry is a bit fiddly to get
+ // ResolverHookFactory resolverHookFactory = new CoreResolverHookFactory(xx,yy);
+ // ((StateImpl) this.state).setResolverHookFactory(resolverHookFactory);
+
+ ServiceReference<ResolverHookFactory> ref = this.bundleContext.getServiceReference(ResolverHookFactory.class);
+ if (ref != null) {
+ ResolverHookFactory resolverHookFactory = this.bundleContext.getService(ref);
+ ((StateImpl) this.state).setResolverHookFactory(resolverHookFactory);
+ this.bundleContext.ungetService(ref);
+ }
+ }
}
/**
@@ -99,19 +145,37 @@ final class StandardQuasiFramework implements QuasiFramework {
*/
public QuasiBundle install(URI location, BundleManifest bundleManifest) throws BundleException {
synchronized (this.monitor) {
+ createCoregionIfNecessary();
StandardQuasiBundle qb = doInstall(location, bundleManifest);
this.installedQuasiBundles.add(qb);
return qb;
}
}
+ private void createCoregionIfNecessary() {
+ synchronized (this.monitor) {
+ if (this.coregion == null) {
+ this.coregion = new BundleIdBasedRegion(this.userRegion.getName() + COREGION_SUFFIX, this.regionDigraph,
+ this.bundleContext.getBundle(0L).getBundleContext());
+ try {
+ this.userRegion.connectRegion(this.coregion, RegionFilter.TOP);
+ this.coregion.connectRegion(this.userRegion, RegionFilter.TOP);
+ } catch (BundleException e) {
+ // should never happen
+ throw new FatalKernelException("Failed to create coregion", e);
+ }
+ }
+ }
+ }
+
private StandardQuasiBundle doInstall(URI location, BundleManifest bundleManifest) throws BundleException {
try {
Dictionary<String, String> manifest = bundleManifest.toDictionary();
String installLocation = "file".equals(location.getScheme()) ? new File(location).getAbsolutePath() : location.toString();
- BundleDescription bundleDescription = this.stateObjectFactory.createBundleDescription(this.state, manifest, installLocation,
- nextBundleId());
+ BundleDescription bundleDescription = this.stateObjectFactory.createBundleDescription(this.state, manifest, this.coregion.getName()
+ + REGION_LOCATION_DELIMITER + installLocation, nextBundleId());
this.state.addBundle(bundleDescription);
+ this.coregion.addBundle(bundleDescription.getBundleId());
return new StandardQuasiBundle(bundleDescription, bundleManifest, this.stateHelper);
} catch (RuntimeException e) {
throw new BundleException("Unable to read bundle at '" + location + "'", e);
@@ -145,7 +209,7 @@ final class StandardQuasiFramework implements QuasiFramework {
public QuasiBundle getBundle(long bundleId) {
QuasiBundle quasiBundle = null;
BundleDescription bundleDescription = this.state.getBundle(bundleId);
- if (bundleDescription!= null) {
+ if (bundleDescription != null) {
quasiBundle = new StandardQuasiBundle(bundleDescription, null, this.stateHelper);
}
return quasiBundle;
@@ -157,7 +221,7 @@ final class StandardQuasiFramework implements QuasiFramework {
public QuasiBundle getBundle(String name, Version version) {
QuasiBundle quasiBundle = null;
BundleDescription bundleDescription = this.state.getBundle(name, version);
- if (bundleDescription!= null) {
+ if (bundleDescription != null) {
quasiBundle = new StandardQuasiBundle(bundleDescription, null, this.stateHelper);
}
return quasiBundle;
@@ -169,8 +233,8 @@ final class StandardQuasiFramework implements QuasiFramework {
public List<QuasiResolutionFailure> resolve() {
synchronized (this.monitor) {
BundleDescription[] bundles = getBundleDescriptionArray();
- BundleDescription[] dependencies = getDependencies(bundles);
-
+ BundleDescription[] dependencies = getDependencies(bundles);
+
this.otherBundles = dependencies;
List<QuasiResolutionFailure> failures = getFailures();
@@ -189,12 +253,14 @@ final class StandardQuasiFramework implements QuasiFramework {
BundleDescription bundleDescription = this.state.getBundle(bundleId);
ResolverErrorsHolder reh = new ResolverErrorsHolder();
String failureDescription = this.detective.generateFailureDescription(this.state, bundleDescription, reh);
- return this.processResolverErrors(reh.getResolverErrors(), new StandardQuasiBundle(bundleDescription, null, this.stateHelper), failureDescription);
+ return this.processResolverErrors(reh.getResolverErrors(), new StandardQuasiBundle(bundleDescription, null, this.stateHelper),
+ failureDescription);
}
private BundleDescription[] getDependencies(BundleDescription[] bundles) {
+ createCoregionIfNecessary();
try {
- return this.dependencyCalculator.calculateDependencies(this.state, bundles);
+ return this.dependencyCalculator.calculateDependencies(this.state, this.coregion, bundles);
} catch (BundleException e) {
return new BundleDescription[0];
} catch (UnableToSatisfyDependenciesException utsde) {
@@ -215,8 +281,8 @@ final class StandardQuasiFramework implements QuasiFramework {
}
return failures;
}
-
- private List<QuasiResolutionFailure> processResolverErrors(ResolverError[] resolverErrors, QuasiBundle quasiBundle, String failureDescription){
+
+ private List<QuasiResolutionFailure> processResolverErrors(ResolverError[] resolverErrors, QuasiBundle quasiBundle, String failureDescription) {
List<QuasiResolutionFailure> processedResolverErrors = new ArrayList<QuasiResolutionFailure>();
boolean added = false;
if (resolverErrors != null) {
@@ -242,16 +308,17 @@ final class StandardQuasiFramework implements QuasiFramework {
return processedResolverErrors;
}
- private PackageQuasiResolutionFailure createPackageResolutionFailure(QuasiBundle quasiBundle, String failureDescription, VersionConstraint unsatisfiedConstraint) {
+ private PackageQuasiResolutionFailure createPackageResolutionFailure(QuasiBundle quasiBundle, String failureDescription,
+ VersionConstraint unsatisfiedConstraint) {
ImportPackageSpecification importPackageSpecification = (ImportPackageSpecification) unsatisfiedConstraint;
String pkgName = importPackageSpecification.getName();
VersionRange pkgVersionRange = convertVersionRange(importPackageSpecification.getVersionRange());
String bundleSymbolicName = importPackageSpecification.getBundleSymbolicName();
VersionRange bundleVersionRange = convertVersionRange(importPackageSpecification.getBundleVersionRange());
- this.logger.debug("Missing import: package '{}' version '{}' bundle '{}' version '{}'", new Object[] { pkgName, pkgVersionRange,
- bundleSymbolicName, bundleVersionRange });
- return new PackageQuasiResolutionFailure(failureDescription, quasiBundle, pkgName, pkgVersionRange,
- bundleSymbolicName, bundleVersionRange);
+ long bundleId = importPackageSpecification.getBundle().getBundleId();
+ this.logger.debug("Missing import: package '{}' version '{}' bundle '{}' version '{}' id '{}'", new Object[] { pkgName, pkgVersionRange,
+ bundleSymbolicName, bundleVersionRange, bundleId });
+ return new PackageQuasiResolutionFailure(failureDescription, quasiBundle, pkgName, pkgVersionRange, bundleSymbolicName, bundleVersionRange);
}
private PackageUsesQuasiResolutionFailure createPackagesUsesResolutionFailure(QuasiBundle quasiBundle, String failureDescription,
@@ -261,10 +328,11 @@ final class StandardQuasiFramework implements QuasiFramework {
VersionRange pkgVersionRange = convertVersionRange(importPackageSpecification.getVersionRange());
String bundleSymbolicName = importPackageSpecification.getBundleSymbolicName();
VersionRange bundleVersionRange = convertVersionRange(importPackageSpecification.getBundleVersionRange());
- this.logger.debug("Uses conflict: package '{}' version '{}' bundle '{}' version '{}'", new Object[] { pkgName, pkgVersionRange,
- bundleSymbolicName, bundleVersionRange });
- return new PackageUsesQuasiResolutionFailure(failureDescription, quasiBundle, pkgName,
- pkgVersionRange, bundleSymbolicName, bundleVersionRange);
+ long bundleId = importPackageSpecification.getBundle().getBundleId();
+ this.logger.debug("Uses conflict: package '{}' version '{}' bundle '{}' version '{}' id '{}'", new Object[] { pkgName, pkgVersionRange,
+ bundleSymbolicName, bundleVersionRange, bundleId });
+ return new PackageUsesQuasiResolutionFailure(failureDescription, quasiBundle, pkgName, pkgVersionRange, bundleSymbolicName,
+ bundleVersionRange);
}
private static VersionRange convertVersionRange(org.eclipse.osgi.service.resolver.VersionRange versionRange) {
@@ -291,7 +359,7 @@ final class StandardQuasiFramework implements QuasiFramework {
if (!failures.isEmpty()) {
throw new BundleException("Commit resolution failed: '" + failures.toString() + "'");
}
- } else {
+ } else {
try {
Set<Long> installedQuasiBundles = installQuasiBundles();
List<Bundle> installedDependencies = installOtherBundles(installedQuasiBundles);
@@ -322,8 +390,7 @@ final class StandardQuasiFramework implements QuasiFramework {
}
}
}
-
-
+
// TODO Move this method into utils project
private static boolean isFragmentBundle(Bundle bundle) {
String fragmentHostHeader = (String) bundle.getHeaders().get(Constants.FRAGMENT_HOST);
@@ -336,7 +403,7 @@ final class StandardQuasiFramework implements QuasiFramework {
if (!installedQuasiBundles.contains(otherBundle.getBundleId())) {
try {
Bundle bundle = installBundleDescription(otherBundle);
- installedBundles.add(bundle);
+ installedBundles.add(bundle);
} catch (BundleException e) {
for (Bundle bundle : installedBundles) {
try {
@@ -359,20 +426,28 @@ final class StandardQuasiFramework implements QuasiFramework {
String location = description.getLocation();
ManifestTransformer manifestTransformer = new QuasiManifestTransformer(quasiBundle.getBundleManifest());
this.bundleTransformationHandler.pushManifestTransformer(manifestTransformer);
-
+
try {
- URI locationUri = new File(location).toURI();
- Bundle bundle = this.bundleContext.installBundle(locationUri.toString());
+ URI locationUri = new File(stripRegionTag(location)).toURI();
+ Bundle bundle = doInstallBundleInternal(locationUri.toString());
quasiBundle.setBundle(bundle);
installed.add(description.getBundleId());
} finally {
this.bundleTransformationHandler.popManifestTransformer();
}
-
+
}
return installed;
}
+ private String stripRegionTag(String location) {
+ int atPos = location.indexOf(REGION_LOCATION_DELIMITER);
+ if (atPos != -1) {
+ return location.substring(atPos + 1);
+ }
+ return location;
+ }
+
private static final class QuasiManifestTransformer implements ManifestTransformer {
private final BundleManifest bundleManifest;
@@ -390,13 +465,38 @@ final class StandardQuasiFramework implements QuasiFramework {
}
private Bundle installBundleDescription(BundleDescription description) throws BundleException {
- String location = description.getLocation();
+ String location = stripRegionTag(description.getLocation());
String installLocation = location.startsWith("http:") ? location : new File(location).toURI().toString();
return doInstallBundleInternal(installLocation);
}
private Bundle doInstallBundleInternal(String location) throws BundleException {
- return this.bundleContext.installBundle(location);
+ return this.userRegion.installBundle(location, openBundleStream(location));
+ }
+
+ private InputStream openBundleStream(String location) throws BundleException {
+ String absoluteBundleUriString = getAbsoluteUriString(location);
+
+ try {
+ // Use the reference: scheme to obtain an InputStream for either a file or a directory.
+ return new URL(REFERENCE_SCHEME + absoluteBundleUriString).openStream();
+
+ } catch (MalformedURLException e) {
+ throw new BundleException("Invalid bundle URI '" + absoluteBundleUriString + "'", e);
+ } catch (IOException e) {
+ throw new BundleException("Invalid bundle at URI '" + absoluteBundleUriString + "'", e);
+ }
+ }
+
+ private String getAbsoluteUriString(String bundleUriString) throws BundleException {
+
+ if (!bundleUriString.startsWith(FILE_SCHEME)) {
+ throw new BundleException("'" + bundleUriString + "' which did not start with '" + FILE_SCHEME + "'");
+ }
+
+ String filePath = bundleUriString.substring(FILE_SCHEME.length());
+
+ return FILE_SCHEME + new File(filePath).getAbsolutePath();
}
private void uninstallQuasiBundles() {
@@ -412,4 +512,16 @@ final class StandardQuasiFramework implements QuasiFramework {
}
}
}
+
+ @Override
+ public void destroy() {
+ Region coregionCopy;
+ synchronized (this.monitor) {
+ coregionCopy = this.coregion;
+ this.coregion = null;
+ }
+ if (coregionCopy != null) {
+ this.regionDigraph.removeRegion(coregionCopy);
+ }
+ }
}
diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFrameworkFactory.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFrameworkFactory.java
index ec910884..78297c9f 100644
--- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFrameworkFactory.java
+++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardQuasiFrameworkFactory.java
@@ -20,18 +20,18 @@ import org.eclipse.osgi.internal.baseadaptor.StateManager;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.service.resolver.StateObjectFactory;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkUtils;
import org.eclipse.virgo.kernel.osgi.framework.OsgiServiceHolder;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFramework;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFrameworkFactory;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
import org.eclipse.virgo.kernel.userregion.internal.equinox.TransformedManifestProvidingBundleFileWrapper;
import org.eclipse.virgo.repository.Repository;
import org.eclipse.virgo.util.io.FileSystemUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* {@link StandardQuasiFrameworkFactory} is the default implementation of {@link QuasiFrameworkFactory}.
@@ -58,7 +58,9 @@ public final class StandardQuasiFrameworkFactory implements QuasiFrameworkFactor
private final TransformedManifestProvidingBundleFileWrapper bundleTransformationHandler;
- public StandardQuasiFrameworkFactory(BundleContext bundleContext, ResolutionFailureDetective detective, Repository repository, TransformedManifestProvidingBundleFileWrapper bundleTransformationHandler) {
+ private final RegionDigraph userRegion;
+
+ public StandardQuasiFrameworkFactory(BundleContext bundleContext, ResolutionFailureDetective detective, Repository repository, TransformedManifestProvidingBundleFileWrapper bundleTransformationHandler, RegionDigraph regionDigraph) {
this.bundleContext = bundleContext;
this.platformAdmin = getPlatformAdminService(bundleContext);
this.detective = detective;
@@ -66,20 +68,21 @@ public final class StandardQuasiFrameworkFactory implements QuasiFrameworkFactor
ServiceReference<PlatformAdmin> platformAdminServiceReference = bundleContext.getServiceReference(PlatformAdmin.class);
this.stateManager = (StateManager) bundleContext.getService(platformAdminServiceReference);
this.bundleTransformationHandler = bundleTransformationHandler;
+ this.userRegion = regionDigraph;
}
/**
* {@inheritDoc}
*/
public QuasiFramework create() {
- return new StandardQuasiFramework(this.bundleContext, createState(), this.platformAdmin, this.detective, this.repository, this.bundleTransformationHandler);
+ return new StandardQuasiFramework(this.bundleContext, createState(), this.platformAdmin, this.detective, this.repository, this.bundleTransformationHandler, this.userRegion);
}
/**
* {@inheritDoc}
*/
public QuasiFramework create(File stateDump) {
- return new StandardQuasiFramework(this.bundleContext, readStateDump(stateDump), this.platformAdmin, this.detective, this.repository, this.bundleTransformationHandler);
+ return new StandardQuasiFramework(this.bundleContext, readStateDump(stateDump), this.platformAdmin, this.detective, this.repository, this.bundleTransformationHandler, this.userRegion);
}
@SuppressWarnings("deprecation")
diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardResolutionFailureDetective.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardResolutionFailureDetective.java
index 638b4eda..488f3f7f 100644
--- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardResolutionFailureDetective.java
+++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/StandardResolutionFailureDetective.java
@@ -221,8 +221,9 @@ public final class StandardResolutionFailureDetective implements ResolutionFailu
private void formatUsesConflict(ResolverError resolverError, StringBuilder sb, State state) {
VersionConstraint unsatisfiedConstraint = resolverError.getUnsatisfiedConstraint();
+ BundleDescription bundle = resolverError.getBundle();
sb.append("Uses violation: <").append(unsatisfiedConstraint)
- .append("> in bundle <").append(resolverError.getBundle()).append(">\n");
+ .append("> in bundle <").append(bundle).append("[").append(bundle.getBundleId()).append("]").append(">\n");
AnalysedUsesConflict[] usesConflicts = this.usesAnalyser.getUsesConflicts(state, resolverError);
if (usesConflicts==null || usesConflicts.length==0) {
diff --git a/org.eclipse.virgo.kernel.userregion/src/test/java/org/eclipse/virgo/kernel/userregion/internal/equinox/AbstractOsgiFrameworkLaunchingTests.java b/org.eclipse.virgo.kernel.userregion/src/test/java/org/eclipse/virgo/kernel/userregion/internal/equinox/AbstractOsgiFrameworkLaunchingTests.java
index 9f1285ee..866c6635 100644
--- a/org.eclipse.virgo.kernel.userregion/src/test/java/org/eclipse/virgo/kernel/userregion/internal/equinox/AbstractOsgiFrameworkLaunchingTests.java
+++ b/org.eclipse.virgo.kernel.userregion/src/test/java/org/eclipse/virgo/kernel/userregion/internal/equinox/AbstractOsgiFrameworkLaunchingTests.java
@@ -23,37 +23,36 @@ import java.util.Set;
import org.eclipse.osgi.launch.Equinox;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
-import org.junit.After;
-import org.junit.Before;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-
+import org.eclipse.virgo.kernel.artifact.bundle.BundleBridge;
+import org.eclipse.virgo.kernel.artifact.library.LibraryBridge;
import org.eclipse.virgo.kernel.osgi.framework.ImportExpander;
import org.eclipse.virgo.kernel.osgi.quasi.QuasiFramework;
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph;
import org.eclipse.virgo.kernel.services.repository.internal.RepositoryFactoryBean;
-import org.eclipse.virgo.kernel.userregion.internal.equinox.EquinoxOsgiFramework;
-import org.eclipse.virgo.kernel.userregion.internal.equinox.KernelClassLoaderCreator;
-import org.eclipse.virgo.kernel.userregion.internal.equinox.TransformedManifestProvidingBundleFileWrapper;
import org.eclipse.virgo.kernel.userregion.internal.importexpansion.ImportExpansionHandler;
import org.eclipse.virgo.kernel.userregion.internal.quasi.StandardQuasiFrameworkFactory;
import org.eclipse.virgo.kernel.userregion.internal.quasi.StandardResolutionFailureDetective;
-
-import org.eclipse.virgo.osgi.extensions.equinox.EquinoxLauncherConfiguration;
-import org.eclipse.virgo.osgi.extensions.equinox.ExtendedEquinoxLauncher;
-import org.eclipse.virgo.osgi.extensions.equinox.hooks.PluggableClassLoadingHook;
-import org.eclipse.virgo.kernel.artifact.bundle.BundleBridge;
-import org.eclipse.virgo.kernel.artifact.library.LibraryBridge;
import org.eclipse.virgo.medic.dump.DumpGenerator;
import org.eclipse.virgo.medic.eventlog.EventLogger;
import org.eclipse.virgo.medic.test.eventlog.MockEventLogger;
+import org.eclipse.virgo.osgi.extensions.equinox.EquinoxLauncherConfiguration;
+import org.eclipse.virgo.osgi.extensions.equinox.ExtendedEquinoxLauncher;
+import org.eclipse.virgo.osgi.extensions.equinox.hooks.PluggableClassLoadingHook;
import org.eclipse.virgo.repository.ArtifactBridge;
import org.eclipse.virgo.repository.Repository;
import org.eclipse.virgo.repository.RepositoryFactory;
import org.eclipse.virgo.repository.internal.RepositoryBundleActivator;
import org.eclipse.virgo.util.io.FileSystemUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
@SuppressWarnings("deprecation")
public abstract class AbstractOsgiFrameworkLaunchingTests {
@@ -74,6 +73,8 @@ public abstract class AbstractOsgiFrameworkLaunchingTests {
private ServiceRegistration<DumpGenerator> dumpGeneratorRegistration;
+ private ServiceRegistration<RegionDigraph> regionDigraphRegistration;
+
private Equinox equinox;
protected QuasiFramework quasiFramework;
@@ -89,6 +90,9 @@ public abstract class AbstractOsgiFrameworkLaunchingTests {
// Uncomment this line to enable Equinox debugging
// FrameworkProperties.setProperty("osgi.debug", "src/test/resources/debug.options");
+
+ // Uncomment thils line to enable Equinox console
+ // FrameworkProperties.setProperty("osgi.console", "2401");
EquinoxLauncherConfiguration launcherConfiguration = new EquinoxLauncherConfiguration();
launcherConfiguration.setClean(true);
URI targetURI = new File("./target").toURI();
@@ -109,10 +113,17 @@ public abstract class AbstractOsgiFrameworkLaunchingTests {
};
+ RegionDigraph regionDigraph = new StandardRegionDigraph();
+
+ Region userRegion = new BundleIdBasedRegion("org.eclipse.virgo.region.user", regionDigraph, bundleContext.getBundle(0L).getBundleContext());
+ regionDigraph.addRegion(userRegion);
+ userRegion.addBundle(this.bundleContext.getBundle());
+
final EventLogger mockEventLogger = new MockEventLogger();
eventLoggerRegistration = bundleContext.registerService(EventLogger.class, mockEventLogger, null);
dumpGeneratorRegistration = bundleContext.registerService(DumpGenerator.class, dumpGenerator, null);
+ regionDigraphRegistration = bundleContext.registerService(RegionDigraph.class, regionDigraph, null);
this.repositoryBundleActivator = new RepositoryBundleActivator();
this.repositoryBundleActivator.start(bundleContext);
@@ -145,7 +156,7 @@ public abstract class AbstractOsgiFrameworkLaunchingTests {
PluggableClassLoadingHook.getInstance().setClassLoaderCreator(new KernelClassLoaderCreator());
StandardResolutionFailureDetective detective = new StandardResolutionFailureDetective(platformAdmin);
- this.quasiFramework = new StandardQuasiFrameworkFactory(bundleContext, detective, repository, bundleFileWrapper).create();
+ this.quasiFramework = new StandardQuasiFrameworkFactory(bundleContext, detective, repository, bundleFileWrapper, regionDigraph).create();
}
private ImportExpander createImportExpander(PackageAdmin packageAdmin) {
@@ -172,6 +183,11 @@ public abstract class AbstractOsgiFrameworkLaunchingTests {
this.dumpGeneratorRegistration = null;
}
+ if (this.regionDigraphRegistration != null) {
+ this.regionDigraphRegistration.unregister();
+ this.regionDigraphRegistration = null;
+ }
+
if (this.eventLoggerRegistration != null) {
this.eventLoggerRegistration.unregister();
this.eventLoggerRegistration = null;
diff --git a/org.eclipse.virgo.kernel.userregion/template.mf b/org.eclipse.virgo.kernel.userregion/template.mf
index b90f1203..749c9daf 100644
--- a/org.eclipse.virgo.kernel.userregion/template.mf
+++ b/org.eclipse.virgo.kernel.userregion/template.mf
@@ -22,3 +22,4 @@ Import-Template:
org.slf4j.*;version="${org.slf4j:[=.=.=, +1)}",
org.springframework.*;version="${org.springframework:[2.5.6, =.+1)}"
Bundle-Activator: org.eclipse.virgo.kernel.userregion.internal.Activator
+Import-Package: org.eclipse.virgo.medic.log;version="0"
diff --git a/org.eclipse.virgo.kernel.userregionfactory/.classpath b/org.eclipse.virgo.kernel.userregionfactory/.classpath
new file mode 100644
index 00000000..8e66eb61
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/.classpath
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry kind="src" path="src/main/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/KERNEL_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.7.0.v20101022/org.eclipse.osgi-3.7.0.v20101022.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.7.0.v20101022/org.eclipse.osgi-sources-3.7.0.v20101022.jar"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-2.3.0.jar" sourcepath="/KERNEL_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-sources-2.3.0.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.kernel.core"/>
+ <classpathentry kind="src" path="/org.eclipse.virgo.kernel.osgi"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.apache.felix/org.apache.felix.eventadmin/1.0.0/org.apache.felix.eventadmin-1.0.0.jar" sourcepath="/KERNEL_IVY_CACHE/org.apache.felix/org.apache.felix.eventadmin/1.0.0/org.apache.felix.eventadmin-sources-1.0.0.jar"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.virgo.medic/org.eclipse.virgo.medic/2.2.0.D-20110113044904/org.eclipse.virgo.medic-2.2.0.D-20110113044904.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.virgo.medic/org.eclipse.virgo.medic/1.0.0.CI-B20/org.eclipse.virgo.medic-sources-1.0.0.CI-B20.jar">
+ <attributes>
+ <attribute name="org.eclipse.ajdt.aspectpath" value="org.eclipse.ajdt.aspectpath"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.virgo.osgi/org.eclipse.virgo.osgi.launcher/2.2.0.D-20101207145732/org.eclipse.virgo.osgi.launcher-2.2.0.D-20101207145732.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.virgo.osgi/org.eclipse.virgo.osgi.launcher/2.2.0.D-20101207145732/org.eclipse.virgo.osgi.launcher-sources-2.2.0.D-20101207145732.jar"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.osgi/2.2.0.D-20101207150035/org.eclipse.virgo.util.osgi-2.2.0.D-20101207150035.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.osgi/2.2.0.D-20101207150035/org.eclipse.virgo.util.osgi-sources-2.2.0.D-20101207150035.jar"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.parser.manifest/2.2.0.D-20101207150035/org.eclipse.virgo.util.parser.manifest-2.2.0.D-20101207150035.jar" sourcepath="/KERNEL_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.parser.manifest/2.2.0.D-20101207150035/org.eclipse.virgo.util.parser.manifest-sources-2.2.0.D-20101207150035.jar"/>
+ <classpathentry kind="var" path="KERNEL_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/2.2.0.D-20101207145338/org.eclipse.virgo.teststubs.osgi-2.2.0.D-20101207145338.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/.project b/org.eclipse.virgo.kernel.userregionfactory/.project
new file mode 100644
index 00000000..95e65506
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.kernel.userregionfactory</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.kernel.userregionfactory/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 00000000..97cdd5ed
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Mon Oct 18 12:33:27 BST 2010
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=false
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.properties;../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.kernel.userregionfactory/.settings/org.eclipse.wst.common.project.facet.core.xml b/org.eclipse.virgo.kernel.userregionfactory/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 00000000..801f856c
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="com.springsource.server.bundle" version="1.0"/>
+</faceted-project>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/.springBeans b/org.eclipse.virgo.kernel.userregionfactory/.springBeans
new file mode 100644
index 00000000..55e47c55
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.5.0.201010141000-RC1]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/build.xml b/org.eclipse.virgo.kernel.userregionfactory/build.xml
new file mode 100644
index 00000000..dba01970
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.kernel.userregionfactory">
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+ <import file="${basedir}/../virgo-build/standard/default.xml"/>
+
+</project>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/ivy.xml b/org.eclipse.virgo.kernel.userregionfactory/ivy.xml
new file mode 100644
index 00000000..aae53846
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/ivy.xml
@@ -0,0 +1,34 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='http://incubator.apache.org/ivy/schemas/ivy.xsd' version='1.3'>
+
+ <info organisation='org.eclipse.virgo.kernel' module='${ant.project.name}'/>
+
+ <configurations>
+ <include file='${virgo.build.dir}/common/default-ivy-configurations.xml'/>
+ </configurations>
+
+ <publications>
+ <artifact name='${ant.project.name}'/>
+ <artifact name='${ant.project.name}-sources' ext='jar' type='src'/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.osgi" name='org.eclipse.osgi' rev='${org.eclipse.osgi}' conf='compile->compile' />
+ <dependency org='org.eclipse.virgo.medic' name='org.eclipse.virgo.medic' rev='${org.eclipse.virgo.medic}' conf='aspects, compile->runtime'/>
+ <dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.core" rev="latest.integration" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.launcher" rev="${org.eclipse.virgo.osgi}" conf="compile->compile"/>
+ <dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.osgi' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
+ <!-- TEST -->
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ <dependency org="org.slf4j" name="com.springsource.slf4j.nop" rev="${org.slf4j}" conf="test->runtime"/>
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ <dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.test" rev="${org.eclipse.virgo.medic}" conf="test->runtime"/>
+ <dependency org='org.eclipse.virgo.teststubs' name='org.eclipse.virgo.teststubs.osgi' rev='${org.eclipse.virgo.teststubs}' conf='test->runtime'/>
+
+ <override org="org.slf4j" rev="${org.slf4j}"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/.gitignore b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/.gitignore
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java
new file mode 100644
index 00000000..d3b35fad
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.userregionfactory;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.virgo.kernel.core.Shutdown;
+import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkLogEvents;
+import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkUtils;
+import org.eclipse.virgo.kernel.osgi.framework.OsgiServiceHolder;
+import org.eclipse.virgo.kernel.osgi.region.BundleIdBasedRegion;
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter;
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.osgi.launcher.parser.ArgumentParser;
+import org.eclipse.virgo.osgi.launcher.parser.BundleEntry;
+import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+/**
+ * {@link Activator} initialises the user region factory bundle.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Not thread safe.
+ *
+ */
+public final class Activator implements BundleActivator {
+
+ private static final String CLASS_LIST_SEPARATOR = ",";
+
+ private static final long MAX_SECONDS_WAIT_FOR_SERVICE = 30;
+
+ private static final long MAX_MILLIS_WAIT_FOR_SERVICE = TimeUnit.SECONDS.toMillis(MAX_SECONDS_WAIT_FOR_SERVICE);
+
+ private static final String USER_REGION_CONFIGURATION_PID = "org.eclipse.virgo.kernel.userregion";
+
+ private static final String USER_REGION_BASE_BUNDLES_PROPERTY = "baseBundles";
+
+ private static final String USER_REGION_PACKAGE_IMPORTS_PROPERTY = "packageImports";
+
+ private static final String USER_REGION_SERVICE_IMPORTS_PROPERTY = "serviceImports";
+
+ private static final String USER_REGION_SERVICE_EXPORTS_PROPERTY = "serviceExports";
+
+ private static final String USER_REGION_BUNDLE_CONTEXT_SERVICE_PROPERTY = "org.eclipse.virgo.kernel.regionContext";
+
+ private static final String REGION_USER = "org.eclipse.virgo.region.user";
+
+ private static final String EVENT_REGION_STARTING = "org/eclipse/virgo/kernel/region/STARTING";
+
+ private static final String EVENT_PROPERTY_REGION_BUNDLECONTEXT = "region.bundleContext";
+
+ private EventAdmin eventAdmin;
+
+ private String regionBundles;
+
+ private String regionImports;
+
+ private String regionServiceImports;
+
+ private String regionServiceExports;
+
+ private BundleContext bundleContext;
+
+ private final ArgumentParser parser = new ArgumentParser();
+
+ private final ServiceRegistrationTracker tracker = new ServiceRegistrationTracker();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ this.bundleContext = bundleContext;
+ RegionDigraph regionDigraph = getPotentiallyDelayedService(bundleContext, RegionDigraph.class);
+ this.eventAdmin = getPotentiallyDelayedService(bundleContext, EventAdmin.class);
+ ConfigurationAdmin configAdmin = getPotentiallyDelayedService(bundleContext, ConfigurationAdmin.class);
+ EventLogger eventLogger = getPotentiallyDelayedService(bundleContext, EventLogger.class);
+ Shutdown shutdown = getPotentiallyDelayedService(bundleContext, Shutdown.class);
+ getRegionConfiguration(configAdmin, eventLogger, shutdown);
+
+ createUserRegion(bundleContext, regionDigraph);
+ }
+
+ private void getRegionConfiguration(ConfigurationAdmin configAdmin, EventLogger eventLogger, Shutdown shutdown) {
+ try {
+ Configuration config = configAdmin.getConfiguration(USER_REGION_CONFIGURATION_PID, null);
+
+ @SuppressWarnings("unchecked")
+ Dictionary<String, String> properties = config.getProperties();
+
+ if (properties != null) {
+ this.regionBundles = properties.get(USER_REGION_BASE_BUNDLES_PROPERTY);
+ this.regionImports = properties.get(USER_REGION_PACKAGE_IMPORTS_PROPERTY);
+ this.regionServiceImports = properties.get(USER_REGION_SERVICE_IMPORTS_PROPERTY);
+ this.regionServiceExports = properties.get(USER_REGION_SERVICE_EXPORTS_PROPERTY);
+ } else {
+ eventLogger.log(OsgiFrameworkLogEvents.USER_REGION_CONFIGURATION_UNAVAILABLE);
+ shutdown.immediateShutdown();
+ }
+ } catch (Exception e) {
+ eventLogger.log(OsgiFrameworkLogEvents.USER_REGION_CONFIGURATION_UNAVAILABLE, e);
+ shutdown.immediateShutdown();
+ }
+ }
+
+ private void createUserRegion(BundleContext userRegionBundleContext, RegionDigraph regionDigraph) throws BundleException {
+
+ BundleContext systemBundleContext = getSystemBundleContext();
+ Bundle userRegionFactoryBundle = userRegionBundleContext.getBundle();
+
+ Region kernelRegion = getKernelRegion(regionDigraph);
+ kernelRegion.removeBundle(userRegionFactoryBundle);
+
+ Region userRegion = new BundleIdBasedRegion(REGION_USER, regionDigraph, systemBundleContext);
+ regionDigraph.addRegion(userRegion);
+ userRegion.addBundle(userRegionFactoryBundle);
+
+ RegionFilter kernelFilter = createKernelFilter(systemBundleContext);
+ userRegion.connectRegion(kernelRegion, kernelFilter);
+
+ RegionFilter userRegionFilter = createUserRegionFilter();
+ kernelRegion.connectRegion(userRegion, userRegionFilter);
+
+ notifyUserRegionStarting(userRegionBundleContext);
+
+ initialiseUserRegionBundles(userRegion);
+
+ registerRegionService(userRegion);
+ publishUserRegionBundleContext(userRegionBundleContext);
+ }
+
+ private RegionFilter createUserRegionFilter() throws BundleException {
+ RegionFilter userRegionFilter = new StandardRegionFilter();
+ Filter serviceFilter;
+ try {
+ serviceFilter = this.bundleContext.createFilter(classesToFilter(this.regionServiceExports));
+ } catch (InvalidSyntaxException e) {
+ throw new BundleException("Invalid " + USER_REGION_SERVICE_EXPORTS_PROPERTY + "in user region configuration: '"
+ + this.regionServiceExports + "'", e);
+ }
+ userRegionFilter.setServiceFilter(serviceFilter);
+
+ return userRegionFilter;
+ }
+
+ private Region getKernelRegion(RegionDigraph regionDigraph) {
+ return regionDigraph.iterator().next();
+ }
+
+ private RegionFilter createKernelFilter(BundleContext systemBundleContext) throws BundleException {
+ RegionFilter kernelFilter = new StandardRegionFilter();
+ Bundle systemBundle = systemBundleContext.getBundle();
+ kernelFilter.allowBundle(systemBundle.getSymbolicName(), systemBundle.getVersion());
+ kernelFilter.setPackageImportPolicy(createUserRegionPackageImportPolicy(systemBundleContext));
+ Filter serviceFilter;
+ try {
+ serviceFilter = this.bundleContext.createFilter(classesToFilter(this.regionServiceImports));
+ } catch (InvalidSyntaxException e) {
+ throw new BundleException("Invalid " + USER_REGION_SERVICE_IMPORTS_PROPERTY + "in user region configuration: '"
+ + this.regionServiceImports + "'", e);
+ }
+ kernelFilter.setServiceFilter(serviceFilter);
+ return kernelFilter;
+ }
+
+ private String classesToFilter(String classList) {
+ if (classList == null) {
+ return "";
+ }
+ String[] classes = classList.split(CLASS_LIST_SEPARATOR);
+ if (classes.length == 0) {
+ return "";
+ }
+ StringBuffer filter = new StringBuffer();
+ filter.append("(|");
+ for (String className : classes) {
+ filter.append("(objectClass=" + className + ")");
+ }
+ filter.append(")");
+ return filter.toString();
+ }
+
+ private UserRegionPackageImportPolicy createUserRegionPackageImportPolicy(BundleContext systemBundleContext) {
+ String userRegionImportsProperty = this.regionImports != null ? this.regionImports
+ : this.bundleContext.getProperty(USER_REGION_PACKAGE_IMPORTS_PROPERTY);
+ String expandedUserRegionImportsProperty = null;
+ if (userRegionImportsProperty != null) {
+ expandedUserRegionImportsProperty = PackageImportWildcardExpander.expandPackageImportsWildcards(userRegionImportsProperty,
+ systemBundleContext);
+ }
+
+ UserRegionPackageImportPolicy userRegionPackageImportPolicy = new UserRegionPackageImportPolicy(expandedUserRegionImportsProperty);
+ return userRegionPackageImportPolicy;
+ }
+
+ private BundleContext getSystemBundleContext() {
+ return this.bundleContext.getBundle(0L).getBundleContext();
+ }
+
+ private void notifyUserRegionStarting(BundleContext userRegionBundleContext) {
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put(EVENT_PROPERTY_REGION_BUNDLECONTEXT, userRegionBundleContext);
+ this.eventAdmin.sendEvent(new Event(EVENT_REGION_STARTING, properties));
+ }
+
+ private void initialiseUserRegionBundles(Region userRegion) throws BundleException {
+
+ String userRegionBundlesProperty = this.regionBundles != null ? this.regionBundles
+ : this.bundleContext.getProperty(USER_REGION_BASE_BUNDLES_PROPERTY);
+
+ if (userRegionBundlesProperty != null) {
+ List<Bundle> bundlesToStart = new ArrayList<Bundle>();
+
+ for (BundleEntry entry : this.parser.parseBundleEntries(userRegionBundlesProperty)) {
+ URI uri = entry.getURI();
+ Bundle bundle = userRegion.installBundle(uri.toString());
+
+ if (entry.isAutoStart()) {
+ bundlesToStart.add(bundle);
+ }
+ }
+
+ for (Bundle bundle : bundlesToStart) {
+ try {
+ bundle.start();
+ } catch (BundleException e) {
+ throw new BundleException("Failed to start bundle " + bundle.getSymbolicName() + " " + bundle.getVersion(), e);
+ }
+ }
+ }
+ }
+
+ private void registerRegionService(Region region) {
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("org.eclipse.virgo.kernel.region.name", region.getName());
+ this.tracker.track(this.bundleContext.registerService(Region.class, region, props));
+ }
+
+ private void publishUserRegionBundleContext(BundleContext userRegionBundleContext) {
+ Dictionary<String, String> properties = new Hashtable<String, String>();
+ properties.put(USER_REGION_BUNDLE_CONTEXT_SERVICE_PROPERTY, "true");
+ this.bundleContext.registerService(BundleContext.class, userRegionBundleContext, properties);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ }
+
+ private static <T> T getPotentiallyDelayedService(BundleContext context, Class<T> serviceClass) throws TimeoutException, InterruptedException {
+ T service = null;
+ OsgiServiceHolder<T> serviceHolder;
+ long millisWaited = 0;
+ while (service == null && millisWaited <= MAX_MILLIS_WAIT_FOR_SERVICE) {
+ try {
+ serviceHolder = OsgiFrameworkUtils.getService(context, serviceClass);
+ if (serviceHolder != null) {
+ service = serviceHolder.getService();
+ } else {
+ millisWaited += sleepABitMore();
+ }
+ } catch (IllegalStateException e) {
+ }
+ }
+ if (service == null) {
+ throw new TimeoutException(serviceClass.getName());
+ }
+ return service;
+ }
+
+ private static long sleepABitMore() throws InterruptedException {
+ long before = System.currentTimeMillis();
+ Thread.sleep(100);
+ return System.currentTimeMillis() - before;
+ }
+}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/PackageImportWildcardExpander.java b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/PackageImportWildcardExpander.java
index 8888f3df..92cbbf27 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/PackageImportWildcardExpander.java
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/PackageImportWildcardExpander.java
@@ -9,7 +9,7 @@
* VMware Inc. - initial contribution
*******************************************************************************/
-package org.eclipse.virgo.kernel.osgi.region;
+package org.eclipse.virgo.kernel.userregionfactory;
import java.util.ArrayList;
import java.util.Dictionary;
@@ -18,13 +18,6 @@ import java.util.Hashtable;
import java.util.List;
import java.util.Set;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-
-
import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkLogEvents;
import org.eclipse.virgo.kernel.serviceability.Assert;
import org.eclipse.virgo.medic.eventlog.EventLogger;
@@ -32,6 +25,11 @@ import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
import org.eclipse.virgo.util.osgi.manifest.DynamicImportPackage;
import org.eclipse.virgo.util.osgi.manifest.DynamicallyImportedPackage;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
/**
* {@link PackageImportWildcardExpander} expands the wildcards in a string containing the body of an import package
@@ -90,7 +88,7 @@ final class PackageImportWildcardExpander {
Dictionary<String, String> headers = new Hashtable<String, String>();
headers.put("DynamicImport-Package", userRegionImportsProperty);
- BundleManifest manifest = BundleManifestFactory.createBundleManifest(headers, new RegionManagerParserLogger(eventLogger));
+ BundleManifest manifest = BundleManifestFactory.createBundleManifest(headers, new UserRegionFactoryParserLogger(eventLogger));
return manifest.getDynamicImportPackage();
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerParserLogger.java b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionFactoryParserLogger.java
index bb25f6a6..a69be1ca 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManagerParserLogger.java
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionFactoryParserLogger.java
@@ -9,14 +9,14 @@
* VMware Inc. - initial contribution
*******************************************************************************/
-package org.eclipse.virgo.kernel.osgi.region;
+package org.eclipse.virgo.kernel.userregionfactory;
import org.eclipse.virgo.kernel.osgi.framework.OsgiFrameworkLogEvents;
import org.eclipse.virgo.medic.eventlog.EventLogger;
import org.eclipse.virgo.util.osgi.manifest.parse.ParserLogger;
/**
- * {@link RegionManagerParserLogger} maps OSGi bundle manifest parsing errors to a log message.
+ * {@link UserRegionFactoryParserLogger} maps OSGi bundle manifest parsing errors to a log message.
* <p />
*
* <strong>Concurrent Semantics</strong><br />
@@ -24,11 +24,11 @@ import org.eclipse.virgo.util.osgi.manifest.parse.ParserLogger;
* This class is thread safe.
*
*/
-final class RegionManagerParserLogger implements ParserLogger {
+final class UserRegionFactoryParserLogger implements ParserLogger {
private final EventLogger eventLogger;
- public RegionManagerParserLogger(EventLogger eventLogger) {
+ public UserRegionFactoryParserLogger(EventLogger eventLogger) {
this.eventLogger = eventLogger;
}
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java
new file mode 100644
index 00000000..06a85b13
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.userregionfactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.osgi.service.resolver.VersionRange;
+import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy;
+import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
+import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
+import org.eclipse.virgo.util.osgi.manifest.ImportedPackage;
+import org.osgi.framework.Version;
+
+/**
+ * {@link UserRegionPackageImportPolicy} is a {@link RegionPackageImportPolicy} for a user region.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread safe.
+ *
+ */
+class UserRegionPackageImportPolicy implements RegionPackageImportPolicy {
+
+ private static final String MANDATORY_ATTRIBUTE_NAME_SEPARATOR = ",";
+
+ private static final String MANDATORY_DIRECTIVE_NAME = "mandatory";
+
+ private static final String VERSION_ATTRIBUTE_NAME = "version";
+
+ private static final String WILDCARD = "*";
+
+ private final Map<String, ImportedPackage> importedPackages = new HashMap<String, ImportedPackage>();
+
+ /**
+ * Construct a {@link UserRegionPackageImportPolicy} for the specified import package list which must not contain
+ * wildcards.
+ *
+ * @param regionImports a string representing a list of imported packages
+ */
+ UserRegionPackageImportPolicy(String regionImports) {
+ if (regionImports != null && !regionImports.isEmpty()) {
+ if (regionImports.contains(WILDCARD)) {
+ throw new IllegalArgumentException("Wildcards not supported in region imports: '" + regionImports + "'");
+ }
+ BundleManifest manifest = BundleManifestFactory.createBundleManifest();
+ manifest.setHeader("Import-Package", regionImports);
+ List<ImportedPackage> list = manifest.getImportPackage().getImportedPackages();
+ for (ImportedPackage importedPackage : list) {
+ String packageName = importedPackage.getPackageName();
+ this.importedPackages.put(packageName, importedPackage);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isImported(String packageName, Map<String, Object> exportAttributes, Map<String, String> exportDirectives) {
+ ImportedPackage importedPackage = this.importedPackages.get(packageName);
+ if (importedPackage != null) {
+ Map<String, String> importAttributes = importedPackage.getAttributes();
+ Set<String> importAttributeNames = importAttributes.keySet();
+
+ // Check any attribute values match.
+ for (String importAttributeName : importAttributeNames) {
+ if (exportAttributes == null) {
+ return false;
+ }
+ Object exportAttributeValue = exportAttributes.get(importAttributeName);
+ if (importAttributeName.equals(VERSION_ATTRIBUTE_NAME)) {
+ if (exportAttributeValue != null && exportAttributeValue instanceof Version) {
+ Version exportVersion = (Version) exportAttributeValue;
+ String importAttributeValue = importAttributes.get(importAttributeName);
+ VersionRange importVersion = new VersionRange(importAttributeValue);
+ if (!importVersion.isIncluded(exportVersion)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ if (exportAttributeValue != null && exportAttributeValue instanceof String) {
+ String exportAttributeValueString = (String) exportAttributeValue;
+ String importAttributeValue = importAttributes.get(importAttributeName);
+ if (!exportAttributeValueString.equals(importAttributeValue)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ }
+
+ // Check mandatory attributes are present.
+ if (exportDirectives != null) {
+ String mandatoryDirectiveValue = exportDirectives.get(MANDATORY_DIRECTIVE_NAME);
+ if (mandatoryDirectiveValue != null) {
+ for (String mandatoryAttribute : mandatoryDirectiveValue.split(MANDATORY_ATTRIBUTE_NAME_SEPARATOR)) {
+ if (!importAttributeNames.contains(mandatoryAttribute)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/main/resources/.gitignore b/org.eclipse.virgo.kernel.userregionfactory/src/main/resources/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/test/java/.gitignore b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/.gitignore
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/PackageImportWildcardExpanderTests.java b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/PackageImportWildcardExpanderTests.java
index e8b54865..62050d61 100644
--- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/PackageImportWildcardExpanderTests.java
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/PackageImportWildcardExpanderTests.java
@@ -9,7 +9,7 @@
* VMware Inc. - initial contribution
*******************************************************************************/
-package org.eclipse.virgo.kernel.osgi.region;
+package org.eclipse.virgo.kernel.userregionfactory;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@@ -22,7 +22,6 @@ import org.osgi.framework.Bundle;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
-import org.eclipse.virgo.kernel.osgi.region.PackageImportWildcardExpander;
import org.eclipse.virgo.medic.eventlog.EventLogger;
import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java
new file mode 100644
index 00000000..3975dcb4
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.userregionfactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy;
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.Capability;
+
+public class UserRegionPackageImportPolicyTests {
+
+ @Test
+ public void testNullPackageString() {
+ new UserRegionPackageImportPolicy(null);
+ }
+
+ @Test
+ public void testEmptyPackageString() {
+ new UserRegionPackageImportPolicy("");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testWildcard() {
+ new UserRegionPackageImportPolicy("*");
+ }
+
+ @Test
+ public void testPackageStringWithArbitraryAttribute() {
+ UserRegionPackageImportPolicy userRegionPackageImportPolicy = createUserRegionPackageImportPolicy("p;pa=pv,q");
+ Assert.assertFalse(userRegionPackageImportPolicy.isImported("p", null, null));
+ Map<String, Object> attributes = createAttributes("p");
+ attributes.put("pa", "pv");
+ Assert.assertTrue(userRegionPackageImportPolicy.isImported("p", attributes, null));
+
+ }
+
+ private UserRegionPackageImportPolicy createUserRegionPackageImportPolicy(String regionImports) {
+ UserRegionPackageImportPolicy userRegionPackageImportPolicy = new UserRegionPackageImportPolicy(regionImports);
+ return userRegionPackageImportPolicy;
+ }
+
+ @Test
+ public void testPackageStringWithoutArbitraryAttribute() {
+ RegionPackageImportPolicy userRegionPackageImportPolicy = createUserRegionPackageImportPolicy("p,q");
+ Map<String, Object> attributes = createAttributes("p");
+ attributes.put("pa", "pv");
+ Assert.assertTrue(userRegionPackageImportPolicy.isImported("p", attributes, null));
+
+ }
+
+ private Map<String, Object> createAttributes(String packageName) {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Capability.PACKAGE_CAPABILITY, packageName);
+ return attributes;
+ }
+
+ @Test
+ public void testPackageStringWithMandatoryAttribute() {
+ RegionPackageImportPolicy userRegionPackageImportPolicy = createUserRegionPackageImportPolicy("p;pa=pv");
+ Assert.assertFalse(userRegionPackageImportPolicy.isImported("p", null, null));
+ Map<String, Object> attributes = createAttributes("p");
+ attributes.put("pa", "pv");
+ Map<String, String> directives = createMandatoryDirective("pa");
+ Assert.assertTrue(userRegionPackageImportPolicy.isImported("p", attributes, directives));
+ }
+
+ @Test
+ public void testPackageStringWithoutMandatoryAttribute() {
+ RegionPackageImportPolicy userRegionPackageImportPolicy = createUserRegionPackageImportPolicy("p");
+ Map<String, Object> attributes = createAttributes("p");
+ attributes.put("pa", "pv");
+ Map<String, String> directives = createMandatoryDirective("pa");
+ Assert.assertFalse(userRegionPackageImportPolicy.isImported("p", attributes, directives));
+ }
+
+ private Map<String, String> createMandatoryDirective(String attributes) {
+ Map<String, String> directives = new HashMap<String, String>();
+ directives.put("mandatory", attributes);
+ return directives;
+ }
+
+ @Test
+ public void testPackageStringWithVersion() {
+ RegionPackageImportPolicy userRegionPackageImportPolicy = createUserRegionPackageImportPolicy("p;version=2,q");
+ Assert.assertFalse(userRegionPackageImportPolicy.isImported("p", null, null));
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("version", new Version("2.0.0"));
+ Assert.assertTrue(userRegionPackageImportPolicy.isImported("p", attributes, null));
+
+ }
+
+ @Test
+ public void testPackages() {
+ RegionPackageImportPolicy userRegionPackageImportPolicy = createUserRegionPackageImportPolicy("p,q");
+ Assert.assertTrue(userRegionPackageImportPolicy.isImported("p", null, null));
+ Assert.assertTrue(userRegionPackageImportPolicy.isImported("q", null, null));
+ Assert.assertFalse(userRegionPackageImportPolicy.isImported("r", null, null));
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/test/resources/.gitignore b/org.eclipse.virgo.kernel.userregionfactory/src/test/resources/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.kernel.userregionfactory/template.mf b/org.eclipse.virgo.kernel.userregionfactory/template.mf
new file mode 100644
index 00000000..228ea8cd
--- /dev/null
+++ b/org.eclipse.virgo.kernel.userregionfactory/template.mf
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Virgo Kernel User Region Factory
+Bundle-SymbolicName: org.eclipse.virgo.kernel.userregionfactory
+Bundle-Version: 2.2.0
+Import-Template:
+ org.eclipse.virgo.kernel.*;version="${version:[=.=.=, =.+1)}",
+ org.eclipse.virgo.util.*;version="${org.eclipse.virgo.util:[=.=.=, =.+1)}",
+ org.eclipse.osgi.framework.*;version="0",
+ org.eclipse.osgi.service.resolver.*;version="0",
+ org.osgi.framework.*;version="0",
+ org.osgi.service.*;version="0",
+ org.eclipse.virgo.medic.*;version="${org.eclipse.virgo.medic:[=.=.=, =.+1)}"
+Import-Package: org.aspectj.lang;version="0"
+Bundle-Activator: org.eclipse.virgo.kernel.userregionfactory.Activator
+Excluded-Imports: org.easymock,
+ org.eclipse.virgo.osgi.launcher.*,
+ org.eclipse.virgo.teststubs.*
+Excluded-Exports: *

Back to the top