Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2012-09-06 14:29:18 +0000
committerThomas Watson2012-09-06 14:29:18 +0000
commit869e2ef794c4cabc62e3e931f3ef73493d2e21ab (patch)
tree87f1bc9e2f0b94398e4f32a8fb32abd21cf4ced0 /bundles/org.eclipse.osgi
parent1d5e88b1dcfca7ff764ce0e9741b1e432b320617 (diff)
parentda9bd82cc99714d9877c6f77e81b2b7358b880e6 (diff)
downloadrt.equinox.framework-869e2ef794c4cabc62e3e931f3ef73493d2e21ab.tar.gz
rt.equinox.framework-869e2ef794c4cabc62e3e931f3ef73493d2e21ab.tar.xz
rt.equinox.framework-869e2ef794c4cabc62e3e931f3ef73493d2e21ab.zip
Merge branch 'master' into twatson/containerMerge
Conflicts: bundles/org.eclipse.osgi.tests/.classpath bundles/org.eclipse.osgi.tests/build.properties bundles/org.eclipse.osgi/META-INF/MANIFEST.MF bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorage.java
Diffstat (limited to 'bundles/org.eclipse.osgi')
-rw-r--r--bundles/org.eclipse.osgi/.classpath11
-rw-r--r--bundles/org.eclipse.osgi/.settings/.api_filters429
-rw-r--r--bundles/org.eclipse.osgi/.settings/org.eclipse.core.resources.prefs5
-rw-r--r--bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--bundles/org.eclipse.osgi/META-INF/MANIFEST.MF95
-rw-r--r--bundles/org.eclipse.osgi/about.html17
-rw-r--r--bundles/org.eclipse.osgi/build.properties19
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleManager.java266
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMessages.properties143
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMsg.java159
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandInterpreter.java599
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java1997
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsole.java209
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsoleSession.java58
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java1051
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java122
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java1893
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ShadowList.java157
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/SimpleHostedCapability.java61
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Util.java99
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WireImpl.java116
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedCapability.java114
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedRequirement.java102
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedResource.java127
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java)601
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/package.html (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/ConsoleManager.java87
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/DefaultStartupMonitor.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/DefaultStartupMonitor.java)14
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java)21
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/BasicReadWriteLock.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/BasicReadWriteLock.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/EventAdminAdapter.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/EventAdminAdapter.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/EventAdminLogListener.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/EventAdminLogListener.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceImpl.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceImpl.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogServiceFactory.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogServiceFactory.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogServiceImpl.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogServiceImpl.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/LogServiceManager.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/LogServiceManager.java)4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/LoggerImpl.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/LoggerImpl.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/SerializedTaskQueue.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/SerializedTaskQueue.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/Module.java626
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java62
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCollisionHook.java59
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java1417
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java205
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java1564
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleLoader.java46
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java143
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java853
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevision.java211
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java240
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisions.java125
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWire.java80
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java393
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/SystemModule.java212
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java837
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EclipsePlatformNamespace.java43
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxModuleDataNamespace.java145
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeCodeNamespace.java79
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/CommandInterpreter.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/CommandInterpreter.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/CommandProvider.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/CommandProvider.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/ConsoleSession.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/ConsoleSession.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/package.html (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/FilePath.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FilePath.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/Headers.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/Headers.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/KeyedElement.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/KeyedElement.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/KeyedHashSet.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/KeyedHashSet.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/ObjectPool.java)18
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/AdaptorMsg.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorMsg.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java)40
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/ArrayMap.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/ArrayMap.java)3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/ExternalMessages.properties (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/ExternalMessages.properties)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Capabilities.java248
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/ComputeNodeOrder.java (renamed from bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ComputeNodeOrder.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Converters.java107
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/LockSet.java79
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AliasMapper.java)13
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java)295
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ContextFinder.java)8
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java746
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java800
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java340
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java243
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java331
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java)160
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java342
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java282
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/UniversalUniqueIdentifier.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/UniversalUniqueIdentifier.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java405
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/StartLevelImpl.java74
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/osname.aliases (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/osname.aliases)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/processor.aliases (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/processor.aliases)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ActivatorHookFactory.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ProtocolActivator.java)15
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileWrapperFactoryHook.java)18
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java243
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookConfigurator.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/HookConfigurator.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/HookRegistry.java)206
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/StorageHookFactory.java114
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassLoadingHook.java)83
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java168
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java)851
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoaderSources.java89
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/FragmentLoader.java24
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader.java)149
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/SystemBundleLoader.java116
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/DependentPolicy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/DependentPolicy.java)63
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/GlobalPolicy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/GlobalPolicy.java)3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/IBuddyPolicy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/IBuddyPolicy.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/PolicyHandler.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/PolicyHandler.java)16
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/RegisteredPolicy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/RegisteredPolicy.java)65
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/SystemPolicy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/SystemPolicy.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathEntry.java)61
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java)541
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/FragmentClasspath.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/FragmentClasspath.java)33
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/FilteredSourcePackage.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/FilteredSourcePackage.java)18
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/MultiSourcePackage.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/MultiSourcePackage.java)7
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/NullPackageSource.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/NullPackageSource.java)4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java175
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/SingleSourcePackage.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SingleSourcePackage.java)21
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/LocationManager.java)198
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogFactory.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogFactory.java)14
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogHook.java)105
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogWriter.java)43
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/BundlePermissions.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/BundlePermissions.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/EquinoxSecurityManager.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/EquinoxSecurityManager.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionAdminTable.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionAdminTable.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionInfoCollection.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionInfoCollection.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionsHash.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionsHash.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java)67
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityRow.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityRowSnapShot.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRowSnapShot.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityTable.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTableUpdate.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityTableUpdate.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/implied.permissions)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEngine.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEngine.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEvent.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEvent.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationListener.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationListener.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationStatus.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationStatus.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateChain.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateChain.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateTrustAuthority.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateTrustAuthority.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifier.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifier.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifierFactory.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifierFactory.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/service/security/KeyStoreTrustEngine.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/KeyStoreTrustEngine.java)7
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java)14
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/HookContext.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ModifiedServiceEvent.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ModifiedServiceEvent.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java)25
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java)75
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java)38
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableEntrySetValueCollection.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableEntrySetValueCollection.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableValueCollectionMap.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableValueCollectionMap.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/Base64.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/Base64.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/DigestedInputStream.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/DigestedInputStream.java)10
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/PKCS7DateParser.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/PKCS7DateParser.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/PKCS7Processor.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/PKCS7Processor.java)4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java)14
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java)56
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java)298
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentConstants.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentConstants.java)4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentFile.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentFile.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java)11
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java187
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignerInfoImpl.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignerInfoImpl.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java96
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/ContentHandlerFactoryImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ContentHandlerFactory.java)21
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/ContentHandlerProxy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java)6
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java238
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingContentHandler.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingContentHandler.java)6
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingFactory.java)42
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingURLStreamHandler.java)35
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/NullURLStreamHandlerService.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/NullURLStreamHandlerService.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerFactoryImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/StreamHandlerFactory.java)118
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerProxy.java)23
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerSetter.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerSetter.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/DynamicImportList.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/DynamicImportList.java)16
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WeavingHookConfigurator.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java)84
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java)10
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java176
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFactory.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/package.html (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/pluginconversion/PluginConversionException.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/osgi/service/pluginconversion/PluginConversionException.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/pluginconversion/PluginConverter.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/osgi/service/pluginconversion/PluginConverter.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BaseDescription.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleDelta.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDelta.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleDescription.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleSpecification.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleSpecification.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/DisabledInfo.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/DisabledInfo.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ExportPackageDescription.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ExportPackageDescription.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/GenericDescription.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/GenericDescription.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/GenericSpecification.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/GenericSpecification.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/HostSpecification.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/HostSpecification.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ImportPackageSpecification.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ImportPackageSpecification.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/NativeCodeDescription.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/NativeCodeDescription.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/NativeCodeSpecification.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/NativeCodeSpecification.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/PlatformAdmin.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/PlatformAdmin.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/Resolver.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/Resolver.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ResolverError.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ResolverError.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ResolverHookException.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ResolverHookException.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/State.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateDelta.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateDelta.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateHelper.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateHelper.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateObjectFactory.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateObjectFactory.java)219
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateWire.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateWire.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/VersionConstraint.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/VersionRange.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionRange.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/package.html (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/security/TrustEngine.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/service/security/TrustEngine.java)8
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/security/package.html (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/service/security/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/InvalidContentException.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/InvalidContentException.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContent.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContent.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContentEntry.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContentEntry.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContentFactory.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContentFactory.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignerInfo.java (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignerInfo.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/package.html (renamed from bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java461
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleLocalizationImpl.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/BundleLocalizationImpl.java)11
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java146
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/ManifestLocalization.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ManifestLocalization.java)92
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/NativeCodeFinder.java206
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/PermissionData.java198
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java1540
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java106
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java)7
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleFile.java)85
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleFileWrapperChain.java)11
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/DirBundleFile.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/DirZipBundleEntry.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/FileBundleEntry.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java)20
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/NestedDirBundleFile.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/ZipBundleEntry.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/ZipBundleFile.java)61
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleResourceHandler.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/BundleResourceHandler.java)76
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleURLConnection.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/BundleURLConnection.java)4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleURLConverter.java (renamed from bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/URLConverterImpl.java)6
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleentry/Handler.java)31
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleresource/Handler.java49
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/Handler.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/reference/Handler.java)16
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ReferenceInputStream.java)2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java (renamed from bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/reference/ReferenceURLConnection.java)26
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/util/TextProcessor.java (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/TextProcessor.java)0
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/util/package.html (renamed from bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/package.html)0
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleClassLoader.java178
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleData.java255
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleOperation.java77
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleProtectionDomain.java71
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleWatcher.java90
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java134
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegateHook.java124
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/EventPublisher.java37
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java296
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/PermissionStorage.java100
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/StatusException.java45
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/DescriptionReference.java28
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/Sortable.java27
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/SpecificationReference.java28
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeBase.java108
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeClassLoader.java162
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeConfigurator.java246
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeHelper.java269
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeImpl.java292
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java178
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/SurrogateImpl.java102
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/service/internal/composite/CompositeModule.java38
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/event/BatchBundleListener.java63
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java1551
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java334
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java686
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleRepository.java196
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleSource.java45
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Constants.java254
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java216
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/EquinoxLauncher.java347
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ExportedPackageImpl.java99
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java2006
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java433
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/PackageAdminImpl.java766
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelEvent.java82
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java678
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/SystemBundleActivator.java110
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Util.java208
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerFactoryProxyFor15.java41
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoaderProxy.java248
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/PackageSource.java81
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SystemBundleLoader.java277
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurePermissionStorage.java109
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/default.permissions25
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/DefaultProfileLogger.java391
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/Profile.java268
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/ProfileLogger.java42
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/Equinox.java301
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFWClassLoader.java71
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java699
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseData.java530
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/AdaptorHook.java100
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileFactoryHook.java35
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingHook.java98
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingStatsHook.java80
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/StorageHook.java138
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/BaseClassLoader.java76
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ParallelClassLoader.java52
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleresource/Handler.java55
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseClassLoadingHook.java139
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseHookConfigurator.java30
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BasePermissionStorage.java97
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorage.java1455
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorageHook.java459
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleInstall.java132
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUninstall.java74
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUpdate.java151
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassPathHelper.java160
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/InvalidVersion.java44
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/StateManager.java320
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/SystemBundleData.java219
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/CachedManifest.java156
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ClasspathManifest.java87
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorHook.java235
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseClassLoadingHook.java243
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseCommandProvider.java283
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseEnvironmentInfo.java243
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseErrorHandler.java113
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java281
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseStorageHook.java522
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IModel.java92
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IPluginInfo.java52
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/MessageHelper.java66
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginConverterImpl.java761
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginParser.java710
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/BundleStats.java132
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassStats.java121
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassloaderStats.java242
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ResourceBundleStats.java123
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/StatsManager.java237
-rw-r--r--bundles/org.eclipse.osgi/hookconfigurators.properties24
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundle.java164
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundleFactory.java153
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/SurrogateBundle.java78
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/HostedCapability.java53
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolutionException.java103
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolveContext.java184
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java72
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/package-info.java39
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java8
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java7
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java3
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java3
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java3
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java2
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java8
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java7
-rw-r--r--bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/DefaultAuthorizationEngine.java186
-rw-r--r--bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BundleInstallListener.java40
-rw-r--r--bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/LegacyVerifierFactory.java137
-rw-r--r--bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java243
-rw-r--r--bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java167
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/ExternalMessages.properties10
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/FrameworkProperties.java233
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Msg.java11
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/reliablefile/ReliableFile.java9
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/util/SecureAction.java60
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/Debug.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/Debug.java)194
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/EclipseDebugTrace.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/EclipseDebugTrace.java)8
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/FrameworkDebugOptions.java)56
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/FrameworkDebugTraceEntry.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/FrameworkDebugTraceEntry.java)2
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/BasicLocation.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/BasicLocation.java)54
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/EclipseAdaptorMessages.properties (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorMessages.properties)0
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/EclipseAdaptorMsg.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorMsg.java)4
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/LocationHelper.java)2
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker.java)2
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker_JavaIo.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaIo.java)2
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker_JavaNio.java (renamed from bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaNio.java)10
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/storagemanager/StorageManager.java8
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java10
-rw-r--r--bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java11
382 files changed, 22885 insertions, 31131 deletions
diff --git a/bundles/org.eclipse.osgi/.classpath b/bundles/org.eclipse.osgi/.classpath
index 5e737b490..c0ae52c7f 100644
--- a/bundles/org.eclipse.osgi/.classpath
+++ b/bundles/org.eclipse.osgi/.classpath
@@ -1,16 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="osgi/src"/>
<classpathentry kind="src" path="supplement/src"/>
- <classpathentry kind="src" path="core/adaptor"/>
- <classpathentry kind="src" path="core/framework"/>
- <classpathentry kind="src" path="core/composite"/>
- <classpathentry kind="src" path="resolver/src"/>
- <classpathentry kind="src" path="defaultAdaptor/src"/>
- <classpathentry kind="src" path="eclipseAdaptor/src"/>
- <classpathentry kind="src" path="security/src"/>
- <classpathentry kind="src" path="console/src"/>
+ <classpathentry kind="src" path="container/src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.osgi/.settings/.api_filters b/bundles/org.eclipse.osgi/.settings/.api_filters
index 2edc26f86..dd18db8ce 100644
--- a/bundles/org.eclipse.osgi/.settings/.api_filters
+++ b/bundles/org.eclipse.osgi/.settings/.api_filters
@@ -1,406 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.osgi" version="2">
- <resource path="core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerFactoryProxyFor15.java" type="org.eclipse.osgi.framework.internal.protocol.URLStreamHandlerFactoryProxyFor15">
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.osgi.framework.internal.protocol.URLStreamHandlerFactoryProxyFor15.openConnection(URL, Proxy)"/>
- <message_argument value="Proxy"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- </resource>
- <resource path="eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorHook.java" type="org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorHook$ParsingService">
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorHook.ParsingService.createService()"/>
- <message_argument value="DocumentBuilderFactory"/>
- <message_argument value="newInstance()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorHook.ParsingService.createService()"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="newInstance()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- </resource>
- <resource path="eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginParser.java" type="org.eclipse.core.runtime.internal.adaptor.PluginParser">
- <filter comment="Code is protected when running on a limited environment" id="579862564">
- <message_arguments>
- <message_argument value="PluginParser"/>
- <message_argument value="DefaultHandler"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="630194212">
- <message_arguments>
- <message_argument value="PluginParser.locator"/>
- <message_argument value="Locator"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="630194212">
- <message_arguments>
- <message_argument value="PluginParser.xmlTracker"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.acquireXMLParsing(BundleContext)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.error(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.fatalError(SAXParseException)"/>
- <message_argument value="SAXException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.fatalError(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleExtensionPointState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleExtensionState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleInitialState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleLibraryExportState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleLibraryState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handlePluginState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleRequiresImportState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleRequiresState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleRuntimeState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.logStatus(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseFragmentAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseLibraryAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePluginAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePluginRequiresImport(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseRequiresAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.processingInstruction(String, String)"/>
- <message_argument value="SAXException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.setDocumentLocator(Locator)"/>
- <message_argument value="Locator"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.startElement(String, String, String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="646971428">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.warning(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647000098">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.PluginParser(FrameworkAdaptor, BundleContext, Version)"/>
- <message_argument value="DefaultHandler()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.acquireXMLParsing(BundleContext)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="newInstance()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.handleLibraryState(String, Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getValue(String, String)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.logStatus(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="getColumnNumber()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.logStatus(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="getLineNumber()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.logStatus(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="getMessage()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.logStatus(SAXParseException)"/>
- <message_argument value="SAXParseException"/>
- <message_argument value="getSystemId()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseFragmentAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getLength()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseFragmentAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getLocalName(int)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseFragmentAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getValue(int)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parseLibraryAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getValue(String, String)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXParser"/>
- <message_argument value="parse(InputStream, DefaultHandler)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="newSAXParser()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="setFeature(String, boolean)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="setNamespaceAware(boolean)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePlugin(InputStream)"/>
- <message_argument value="SAXParserFactory"/>
- <message_argument value="setValidating(boolean)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePluginAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getLength()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePluginAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getLocalName(int)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePluginAttributes(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getValue(int)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- <filter comment="Code is protected when running on a limited environment" id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.core.runtime.internal.adaptor.PluginParser.parsePluginRequiresImport(Attributes)"/>
- <message_argument value="Attributes"/>
- <message_argument value="getValue(String, String)"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- </resource>
- <resource path="eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java" type="org.eclipse.equinox.log.internal.ExtendedLogEntryImpl">
- <filter comment="Ingore this and extend anyway" id="574660632">
- <message_arguments>
- <message_argument value="ExtendedLogEntry"/>
- <message_argument value="LogEntry"/>
- <message_argument value="ExtendedLogEntryImpl"/>
- </message_arguments>
- </filter>
- <filter comment="protected by reflection method check." id="647004193">
- <message_arguments>
- <message_argument value="org.eclipse.equinox.log.internal.ExtendedLogEntryImpl.getId(Thread)"/>
- <message_argument value="Thread"/>
- <message_argument value="getId()"/>
- <message_argument value="OSGi/Minimum-1.2"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="osgi/src/org/osgi/framework/AdaptPermission.java" type="org.osgi.framework.AdaptPermission">
<filter comment="Ignore OSGi API" id="337768515">
<message_arguments>
@@ -576,6 +175,34 @@
</message_arguments>
</filter>
</resource>
+ <resource path="osgi/src/org/osgi/service/resolver/HostedCapability.java" type="org.osgi.service.resolver.HostedCapability">
+ <filter comment="Ignore OSGi API" id="1110441988">
+ <message_arguments>
+ <message_argument value="org.osgi.service.resolver.HostedCapability"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="osgi/src/org/osgi/service/resolver/ResolutionException.java" type="org.osgi.service.resolver.ResolutionException">
+ <filter comment="Ignore OSGi API" id="1110441988">
+ <message_arguments>
+ <message_argument value="org.osgi.service.resolver.ResolutionException"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="osgi/src/org/osgi/service/resolver/ResolveContext.java" type="org.osgi.service.resolver.ResolveContext">
+ <filter comment="Ignore OSGi API" id="1110441988">
+ <message_arguments>
+ <message_argument value="org.osgi.service.resolver.ResolveContext"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="osgi/src/org/osgi/service/resolver/Resolver.java" type="org.osgi.service.resolver.Resolver">
+ <filter comment="Ignore OSGi API" id="1110441988">
+ <message_arguments>
+ <message_argument value="org.osgi.service.resolver.Resolver"/>
+ </message_arguments>
+ </filter>
+ </resource>
<resource path="supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaNio.java" type="org.eclipse.core.runtime.internal.adaptor.Locker_JavaNio">
<filter comment="Code is protected when running on a limited environment" id="630194212">
<message_arguments>
diff --git a/bundles/org.eclipse.osgi/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.osgi/.settings/org.eclipse.core.resources.prefs
index 5991b6bdf..6d3bfd6f9 100644
--- a/bundles/org.eclipse.osgi/.settings/org.eclipse.core.resources.prefs
+++ b/bundles/org.eclipse.osgi/.settings/org.eclipse.core.resources.prefs
@@ -1,6 +1,5 @@
-#Thu Aug 06 15:31:01 CDT 2009
eclipse.preferences.version=1
-encoding//core/framework/org/eclipse/osgi/framework/internal/core/osname.aliases=UTF-8
-encoding//core/framework/org/eclipse/osgi/framework/internal/core/processor.aliases=UTF-8
+encoding//container/src/org/eclipse/osgi/internal/framework/osname.aliases=UTF-8
+encoding//container/src/org/eclipse/osgi/internal/framework/processor.aliases=UTF-8
encoding//osgi/src=UTF-8
encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs
index 4f32b45f6..df8c0b940 100644
--- a/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,3 @@
-#Thu Feb 17 07:54:09 CST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
@@ -8,9 +7,9 @@ org.eclipse.jdt.core.circularClasspath=error
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=jsr14
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -100,7 +99,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enab
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
index e812bd226..b51cd0627 100644
--- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
@@ -1,89 +1,80 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Export-Package: org.eclipse.osgi.event;version="1.0",
+Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.runtime",
+ org.eclipse.core.runtime.internal.adaptor;x-internal:=true,
+ org.eclipse.equinox.log;version="1.0",
+ org.eclipse.equinox.log.internal;x-internal:=true,
+ org.eclipse.osgi.container;version="1.0",
+ org.eclipse.osgi.container.builders;version="1.0",
+ org.eclipse.osgi.container.namespaces;version="1.0",
org.eclipse.osgi.framework.console;version="1.1",
org.eclipse.osgi.framework.eventmgr;version="1.2",
+ org.eclipse.osgi.framework.internal.core;x-internal:=true,
+ org.eclipse.osgi.framework.internal.reliablefile;x-internal:=true,
org.eclipse.osgi.framework.log;version="1.1",
- org.eclipse.osgi.launch; version="1.0",
+ org.eclipse.osgi.framework.util;x-internal:=true,
+ org.eclipse.osgi.internal.baseadaptor;x-internal:=true,
+ org.eclipse.osgi.internal.debug;x-internal:=true,
+ org.eclipse.osgi.internal.framework;x-internal:=true,
+ org.eclipse.osgi.internal.loader;x-internal:=true,
+ org.eclipse.osgi.internal.loader.buddy;x-internal:=true,
+ org.eclipse.osgi.internal.loader.classpath;x-internal:=true,
+ org.eclipse.osgi.internal.loader.sources;x-internal:=true,
+ org.eclipse.osgi.internal.location;x-internal:=true,
+ org.eclipse.osgi.internal.provisional.service.security;version="1.0.0";x-friends:="org.eclipse.equinox.security.ui",
+ org.eclipse.osgi.internal.provisional.verifier;x-friends:="org.eclipse.update.core,org.eclipse.ui.workbench,org.eclipse.equinox.p2.artifact.repository",
+ org.eclipse.osgi.internal.service.security;x-friends:="org.eclipse.equinox.security.ui",
+ org.eclipse.osgi.internal.serviceregistry;x-internal:=true,
+ org.eclipse.osgi.internal.signedcontent;x-internal:=true,
+ org.eclipse.osgi.internal.url;x-internal:=true,
+ org.eclipse.osgi.launch;version="1.0",
org.eclipse.osgi.service.datalocation;version="1.3",
org.eclipse.osgi.service.debug;version="1.2",
org.eclipse.osgi.service.environment;version="1.3",
org.eclipse.osgi.service.localization;version="1.1",
org.eclipse.osgi.service.pluginconversion;version="1.0",
org.eclipse.osgi.service.resolver;version="1.6",
- org.eclipse.osgi.service.resolver.extras;version="1.0"; x-friends:="org.eclipse.equinox.resolver",
org.eclipse.osgi.service.runnable;version="1.1",
- org.eclipse.osgi.service.security; version="1.0",
+ org.eclipse.osgi.service.security;version="1.0",
org.eclipse.osgi.service.urlconversion;version="1.0",
- org.eclipse.osgi.signedcontent; version="1.0",
+ org.eclipse.osgi.signedcontent;version="1.0",
+ org.eclipse.osgi.storage.bundlefile;x-internal:=true,
+ org.eclipse.osgi.storage.url.reference;x-internal:=true,
org.eclipse.osgi.storagemanager;version="1.0",
org.eclipse.osgi.util;version="1.1",
- org.eclipse.equinox.log; version="1.0",
org.osgi.framework;version="1.7",
- org.osgi.framework.launch; version="1.1",
- org.osgi.framework.hooks.bundle; version="1.1",
- org.osgi.framework.hooks.resolver; version="1.0",
- org.osgi.framework.hooks.service; version="1.1",
- org.osgi.framework.hooks.weaving; version="1.0",
+ org.osgi.framework.hooks.bundle;version="1.1",
+ org.osgi.framework.hooks.resolver;version="1.0",
+ org.osgi.framework.hooks.service;version="1.1",
+ org.osgi.framework.hooks.weaving;version="1.0",
+ org.osgi.framework.launch;version="1.1",
org.osgi.framework.namespace;version="1.0",
- org.osgi.framework.startlevel; version="1.0",
- org.osgi.framework.wiring; version="1.1",
- org.osgi.resource; version="1.0",
+ org.osgi.framework.startlevel;version="1.0",
+ org.osgi.framework.wiring;version="1.1",
+ org.osgi.resource;version="1.0",
org.osgi.service.condpermadmin;version="1.1.1",
- org.osgi.service.framework; version="1.0"; x-internal:=true,
- org.osgi.service.log; version="1.3",
+ org.osgi.service.log;version="1.3",
org.osgi.service.packageadmin;version="1.2",
org.osgi.service.permissionadmin;version="1.2",
+ org.osgi.service.resolver;version="1.0",
org.osgi.service.startlevel;version="1.1",
org.osgi.service.url;version="1.0",
- org.osgi.util.tracker;version="1.5.1",
- org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.runtime",
- org.eclipse.core.runtime.internal.adaptor;x-internal:=true,
- org.eclipse.core.runtime.internal.stats;x-friends:="org.eclipse.core.runtime",
- org.eclipse.osgi.baseadaptor;x-internal:=true,
- org.eclipse.osgi.baseadaptor.bundlefile;x-internal:=true,
- org.eclipse.osgi.baseadaptor.hooks;x-internal:=true,
- org.eclipse.osgi.baseadaptor.loader;x-internal:=true,
- org.eclipse.osgi.framework.adaptor;x-internal:=true,
- org.eclipse.osgi.framework.debug;x-internal:=true,
- org.eclipse.osgi.framework.internal.core;x-internal:=true,
- org.eclipse.osgi.framework.internal.protocol;x-internal:=true,
- org.eclipse.osgi.framework.internal.protocol.bundleentry;x-internal:=true,
- org.eclipse.osgi.framework.internal.protocol.bundleresource;x-internal:=true,
- org.eclipse.osgi.framework.internal.protocol.reference;x-internal:=true,
- org.eclipse.osgi.framework.internal.reliablefile;x-internal:=true,
- org.eclipse.osgi.framework.util;x-internal:=true,
- org.eclipse.osgi.internal.baseadaptor;x-internal:=true,
- org.eclipse.osgi.internal.composite; x-internal:=true,
- org.eclipse.osgi.internal.loader;x-internal:=true,
- org.eclipse.osgi.internal.loader.buddy; x-internal:=true,
- org.eclipse.osgi.internal.module;x-internal:=true,
- org.eclipse.osgi.internal.profile;x-internal:=true,
- org.eclipse.osgi.internal.resolver;x-internal:=true,
- org.eclipse.osgi.internal.serviceregistry; x-internal:=true,
- org.eclipse.osgi.internal.permadmin;x-internal:=true,
- org.eclipse.osgi.internal.provisional.service.security; x-friends:="org.eclipse.equinox.security.ui";version="1.0.0",
- org.eclipse.osgi.internal.provisional.verifier;x-friends:="org.eclipse.update.core,org.eclipse.ui.workbench,org.eclipse.equinox.p2.artifact.repository",
- org.eclipse.osgi.internal.service.security;x-friends:="org.eclipse.equinox.security.ui",
- org.eclipse.osgi.internal.signedcontent; x-internal:=true,
- org.eclipse.osgi.service.internal.composite; x-internal:=true,
- org.eclipse.equinox.log.internal; x-internal:=true
+ org.osgi.util.tracker;version="1.5.1"
Export-Service: org.osgi.service.packageadmin.PackageAdmin,
org.osgi.service.permissionadmin.PermissionAdmin,
org.osgi.service.startlevel.StartLevel,
org.eclipse.osgi.service.debug.DebugOptions
Bundle-Name: %systemBundle
Bundle-SymbolicName: org.eclipse.osgi; singleton:=true
-Bundle-Activator: org.eclipse.osgi.framework.internal.core.SystemBundleActivator
+Bundle-Activator: org.eclipse.osgi.internal.framework.SystemBundleActivator
Bundle-Description: %systemBundle
Bundle-Copyright: %copyright
Bundle-Vendor: %eclipse.org
-Bundle-Version: 3.8.100.qualifier
+Bundle-Version: 3.10.0.qualifier
Bundle-Localization: systembundle
Bundle-DocUrl: http://www.eclipse.org
Eclipse-ExtensibleAPI: true
Eclipse-SystemBundle: true
Main-Class: org.eclipse.core.runtime.adaptor.EclipseStarter
-Bundle-RequiredExecutionEnvironment: J2SE-1.5,
- OSGi/Minimum-1.2
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Eclipse-BundleShape: jar
diff --git a/bundles/org.eclipse.osgi/about.html b/bundles/org.eclipse.osgi/about.html
index 60a8dda5f..7aa669046 100644
--- a/bundles/org.eclipse.osgi/about.html
+++ b/bundles/org.eclipse.osgi/about.html
@@ -67,6 +67,23 @@ in the file <a href="about_files/LICENSE-2.0.txt" target="_blank">LICENSE-2.0.tx
or may not be a member of the OSGi Alliance). The OSGi Alliance and its members are not responsible and shall not be held responsible in any manner for identifying or failing to identify any or all such third party
intellectual property rights.</p>
+<h4>Apache Felix Resolver</h4>
+
+<p>This bundle includes software developed by The Apache Software Foundation as part of the Felix project.
+this includes all files in the following sub-directories (and their sub-directories):</p>
+<ul>
+ <li>org/apache/felix/resolver</li>
+</ul>
+
+<p>Your use of the Resolver code is subject to the terms and conditions of the Apache Software License 2.0. A copy of the license is contained
+ in the file <a href="about_files/LICENSE-2.0.txt">LICENSE-2.0.txt</a> and is also available at <a href="http://www.apache.org/licenses/LICENSE-2.0.html">http://www.apache.org/licenses/LICENSE-2.0.html</a>.
+
+<p>The names &quot;Felix Resolver&quot; and &quot;Apache Software Foundation&quot; must not be used to endorse or promote products derived from this
+ software without prior written permission. For written permission, please contact <a href="mailto:apache@apache.org">apache@apache.org</a>.</p>
+
+<p>
+ Original binaries and source are available from the <a href="http://felix.apache.org/">Apache Felix website</a>.</p>
+
<small>OSGi&trade; is a trademark, registered trademark, or service mark of The OSGi Alliance in the US and other countries. Java is a trademark,
registered trademark, or service mark of Sun Microsystems, Inc. in the US and other countries. All other trademarks, registered trademarks, or
service marks used in the Content are the property of their respective owners and are hereby recognized.</small>
diff --git a/bundles/org.eclipse.osgi/build.properties b/bundles/org.eclipse.osgi/build.properties
index deea927bc..396fc34b3 100644
--- a/bundles/org.eclipse.osgi/build.properties
+++ b/bundles/org.eclipse.osgi/build.properties
@@ -15,28 +15,13 @@ bin.includes = .options,\
systembundle.properties,\
*.profile,\
profile.list,\
- hookconfigurators.properties,\
about_files/
src.includes = about.html,\
about_files/
source.. = osgi/src,\
- core/adaptor/,\
- core/framework/,\
- core/composite/,\
- resolver/src/,\
- defaultAdaptor/src/,\
- eclipseAdaptor/src/,\
- console/src/,\
supplement/src/,\
- security/src/
+ container/src/
output.. = bin/
-jre.compilation.profile = J2SE-1.5
-
-# jre.compilation.profile = CDC-1.1/Foundation-1.1
-# bootClasspath=osgi/exceptions.jar;osgi/xmlParserAPIs.jar;${CDC-1.1/Foundation-1.1}
-
-javacSource=1.5
-javacTarget=jsr14
# To enable building the framework using projects from OSGi repo uncomment customBuildCallbacks
# and add the following to the beginning of source..
@@ -44,4 +29,4 @@ javacTarget=jsr14
# and use the .classpath.osgisource as the .classpath file.
# customBuildCallbacks=customBuildCallbacks.xml
-javacWarnings..=-deadCode,-raw,-unchecked \ No newline at end of file
+javacWarnings..=-deadCode,-raw,-unchecked
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleManager.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleManager.java
deleted file mode 100644
index ecb88c91d..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleManager.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.lang.reflect.Method;
-import java.net.*;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import org.eclipse.osgi.framework.console.CommandProvider;
-import org.eclipse.osgi.framework.console.ConsoleSession;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public class ConsoleManager implements ServiceTrackerCustomizer<ConsoleSession, FrameworkConsole> {
- /**
- * ConsoleSocketGetter - provides a Thread that listens on the port
- * for FrameworkConsole.
- */
- class ConsoleSocketGetter implements Runnable {
-
- /** The ServerSocket to accept connections from */
- private final ServerSocket server;
- private volatile boolean shutdown = false;
-
- /**
- * Constructor - sets the server and starts the thread to
- * listen for connections.
- *
- * @param server a ServerSocket to accept connections from
- */
- ConsoleSocketGetter(ServerSocket server) {
- this.server = server;
- try {
- Method reuseAddress = server.getClass().getMethod("setReuseAddress", new Class[] {boolean.class}); //$NON-NLS-1$
- reuseAddress.invoke(server, new Object[] {Boolean.TRUE});
- } catch (Exception ex) {
- // try to set the socket re-use property, it isn't a problem if it can't be set
- }
- Thread t = new Thread(this, "ConsoleSocketGetter"); //$NON-NLS-1$
- t.setDaemon(false);
- t.start();
- }
-
- public void run() {
- // Print message containing port console actually bound to..
- System.out.println(NLS.bind(ConsoleMsg.CONSOLE_LISTENING_ON_PORT, server.getInetAddress().toString() + ':' + Integer.toString(server.getLocalPort())));
- while (!shutdown) {
- try {
- Socket socket = server.accept();
- if (socket == null)
- throw new IOException("No socket available. Probably caused by a shutdown."); //$NON-NLS-1$
- FrameworkConsoleSession session = new FrameworkConsoleSession(socket.getInputStream(), socket.getOutputStream(), socket);
- framework.getSystemBundleContext().registerService(ConsoleSession.class.getName(), session, null);
- } catch (Exception e) {
- if (!shutdown)
- e.printStackTrace();
- }
-
- }
- }
-
- public void shutdown() {
- if (shutdown)
- return;
- shutdown = true;
- try {
- server.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- public static final String PROP_CONSOLE = "osgi.console"; //$NON-NLS-1$
- private static final String PROP_SYSTEM_IN_OUT = "console.systemInOut"; //$NON-NLS-1$
- private static final String CONSOLE_NAME = "OSGi Console"; //$NON-NLS-1$
- public static final String CONSOLE_BUNDLE = "org.eclipse.equinox.console"; //$NON-NLS-1$
- public static final String PROP_CONSOLE_ENABLED = "osgi.console.enable.builtin"; //$NON-NLS-1$
- final Framework framework;
- private final ServiceTracker<CommandProvider, CommandProvider> cpTracker;
- private final ServiceTracker<ConsoleSession, FrameworkConsole> sessions;
- private final String consolePort;
- // Allow for specifying the particular local host address on which the framework to listen for connections. Currently it listens on
- // all network interfaces of the host and restricting this is desirable from security point of view. See bug 322917.
- private final String consoleHost;
- private FrameworkCommandProvider fwkCommands;
- private ServiceRegistration<?> builtinSession;
- private ConsoleSocketGetter socketGetter;
- private final boolean isEnabled;
- private final String consoleBundle;
-
- public ConsoleManager(Framework framework, String consolePropValue) {
- String port = null;
- String host = null;
- if (consolePropValue != null) {
- int index = consolePropValue.lastIndexOf(":"); //$NON-NLS-1$
- if (index > -1) {
- host = consolePropValue.substring(0, index);
- }
- port = consolePropValue.substring(index + 1);
- }
- this.framework = framework;
- this.consoleHost = host != null ? host.trim() : host;
- this.consolePort = port != null ? port.trim() : port;
- String enabled = FrameworkProperties.getProperty(PROP_CONSOLE_ENABLED, CONSOLE_BUNDLE);
- if (!"true".equals(enabled) || "none".equals(port)) { //$NON-NLS-1$ //$NON-NLS-2$
- isEnabled = false;
- this.cpTracker = null;
- this.sessions = null;
- this.consoleBundle = "false".equals(enabled) ? CONSOLE_BUNDLE : enabled; //$NON-NLS-1$
- if (consolePort == null || consolePort.length() > 0) {
- // no -console was specified or it has specified none or a port for telnet;
- // need to make sure the gogo shell does not create an interactive console on standard in/out
- FrameworkProperties.setProperty("gosh.args", "--nointeractive"); //$NON-NLS-1$//$NON-NLS-2$
- } else {
- // Need to make sure we don't shutdown the framework if no console is around (bug 362412)
- FrameworkProperties.setProperty("gosh.args", "--noshutdown"); //$NON-NLS-1$//$NON-NLS-2$
- }
- return;
- }
- this.isEnabled = true;
- this.cpTracker = new ServiceTracker<CommandProvider, CommandProvider>(framework.getSystemBundleContext(), CommandProvider.class.getName(), null);
- this.sessions = new ServiceTracker<ConsoleSession, FrameworkConsole>(framework.getSystemBundleContext(), ConsoleSession.class.getName(), this);
- this.consoleBundle = "unknown"; //$NON-NLS-1$
- }
-
- public static ConsoleManager startConsole(Framework framework) {
- ConsoleManager consoleManager = new ConsoleManager(framework, FrameworkProperties.getProperty(PROP_CONSOLE));
- consoleManager.startConsole();
- return consoleManager;
- }
-
- private void startConsole() {
- if (!isEnabled) {
- return;
- }
-
- this.cpTracker.open();
- this.sessions.open();
- fwkCommands = new FrameworkCommandProvider(framework);
- fwkCommands.start();
- if (consolePort == null)
- return;
- int port = -1;
- try {
- if (consolePort.length() > 0)
- port = Integer.parseInt(consolePort);
- } catch (NumberFormatException e) {
- // do nothing;
- }
- if (port < 0) {
- InputStream in = new FilterInputStream(System.in) {
- /**
- * @throws IOException
- */
- public void close() throws IOException {
- // We don't want to close System.in
- }
- };
- OutputStream out = new FilterOutputStream(System.out) {
- /**
- * @throws IOException
- */
- public void close() throws IOException {
- // We don't want to close System.out
- }
-
- public void write(byte[] var0, int var1, int var2) throws IOException {
- this.out.write(var0, var1, var2);
- }
-
- };
- FrameworkConsoleSession session = new FrameworkConsoleSession(in, out, null);
- Dictionary<String, Object> props = null;
- props = new Hashtable<String, Object>(1);
- props.put(PROP_SYSTEM_IN_OUT, Boolean.TRUE);
- builtinSession = framework.getSystemBundleContext().registerService(ConsoleSession.class.getName(), session, props);
- } else {
- try {
- if (consoleHost != null) {
- socketGetter = new ConsoleSocketGetter(new ServerSocket(port, 0, InetAddress.getByName(consoleHost)));
- } else {
- socketGetter = new ConsoleManager.ConsoleSocketGetter(new ServerSocket(port));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- public void checkForConsoleBundle() throws BundleException {
- if (isEnabled)
- return;
- if ("none".equals(consolePort)) //$NON-NLS-1$
- return;
- // otherwise we need to check for the equinox console bundle and start it
- Bundle[] consoles = framework.getBundleBySymbolicName(consoleBundle);
- if (consoles == null || consoles.length == 0) {
- if (consolePort != null)
- throw new BundleException("Could not find bundle: " + consoleBundle, BundleException.UNSUPPORTED_OPERATION); //$NON-NLS-1$
- return;
- }
- try {
- consoles[0].start(Bundle.START_TRANSIENT);
- } catch (BundleException e) {
- throw new BundleException("Could not start bundle: " + consoleBundle, BundleException.UNSUPPORTED_OPERATION, e); //$NON-NLS-1$
- }
- }
-
- /**
- * Stops the OSGi Command console
- *
- */
- public void stopConsole() {
- if (!isEnabled) {
- return;
- }
- if (builtinSession != null)
- try {
- builtinSession.unregister();
- } catch (IllegalStateException e) {
- // ignore; this can happen if the session was closed manually (bug 314343)
- }
- sessions.close();
- cpTracker.close();
- if (socketGetter != null)
- socketGetter.shutdown();
- if (fwkCommands != null)
- fwkCommands.stop();
- }
-
- public FrameworkConsole addingService(ServiceReference<ConsoleSession> reference) {
- FrameworkConsole console = null;
-
- Boolean isSystemInOut = (Boolean) reference.getProperty(PROP_SYSTEM_IN_OUT);
- if (isSystemInOut == null)
- isSystemInOut = Boolean.FALSE;
-
- ConsoleSession session = framework.getSystemBundleContext().getService(reference);
- console = new FrameworkConsole(framework.getSystemBundleContext(), session, isSystemInOut.booleanValue(), cpTracker);
-
- Thread t = new Thread(console, CONSOLE_NAME);
- t.setDaemon(false);
- t.start();
- return console;
- }
-
- public void modifiedService(ServiceReference<ConsoleSession> reference, FrameworkConsole service) {
- // nothing
- }
-
- public void removedService(ServiceReference<ConsoleSession> reference, FrameworkConsole service) {
- service.shutdown();
- }
-}
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMessages.properties b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMessages.properties
deleted file mode 100644
index fc686ad45..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMessages.properties
+++ /dev/null
@@ -1,143 +0,0 @@
-###############################################################################
-# Copyright (c) 2003, 2011 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-
-#External Messages for EN locale
-CONSOLE_PROMPT=osgi>
-CONSOLE_ID=id
-CONSOLE_MORE=-- More...Press Enter to Continue...
-CONSOLE_HELP_CONTROLLING_CONSOLE_HEADING=---Controlling the Console---
-CONSOLE_HELP_MORE=More prompt for console output
-CONSOLE_HELP_DISCONNECT=Disconnects from telnet session
-CONSOLE_CONFIRM_MORE=Use 'more' prompt?
-CONSOLE_MORE_ENTER_LINES=Enter maximum number of lines to scroll:
-CONSOLE_CONFIRM_DISCONNECT=Disconnect from console?
-CONSOLE_CONFIRM=Confirm
-CONSOLE_CONFIRM_VALUES=y/n; default=
-CONSOLE_Y=y
-CONSOLE_N=n
-CONSOLE_ERROR_READING_RESOURCE=Error reading {0}
-CONSOLE_RESOURCE_NOT_IN_BUNDLE={0} not found in {1}
-CONSOLE_NESTED_EXCEPTION=Nested Exception:
-CONSOLE_PROMPT_DEFAULT=default
-CONSOLE_INVALID_INPUT=Invalid input.
-CONSOLE_TOO_MUCH_INVALID_INPUT=Too much invalid input.
-CONSOLE_LINES_TO_SCROLL_NEGATIVE_ERROR=Lines to scroll is set to a negative number
-CONSOLE_HELP_CONTROLLING_FRAMEWORK_HEADER=Controlling the OSGi framework
-CONSOLE_HELP_LAUNCH_COMMAND_DESCRIPTION=start the OSGi Framework
-CONSOLE_HELP_SHUTDOWN_COMMAND_DESCRIPTION=shutdown the OSGi Framework
-CONSOLE_HELP_CLOSE_COMMAND_DESCRIPTION=shutdown and exit
-CONSOLE_HELP_EXIT_COMMAND_DESCRIPTION=exit immediately (System.exit)
-CONSOLE_HELP_GC_COMMAND_DESCRIPTION=perform a garbage collection
-CONSOLE_HELP_INIT_COMMAND_DESCRIPTION=uninstall all bundles
-CONSOLE_HELP_SETPROP_COMMAND_DESCRIPTION=set the OSGi property
-CONSOLE_HELP_CONTROLLING_BUNDLES_HEADER=Controlling Bundles
-CONSOLE_HELP_INSTALL_COMMAND_DESCRIPTION=install and optionally start bundle from the given URL
-CONSOLE_HELP_UNINSTALL_COMMAND_DESCRIPTION=uninstall the specified bundle(s)
-CONSOLE_HELP_START_COMMAND_DESCRIPTION=start the specified bundle(s)
-CONSOLE_HELP_STOP_COMMAND_DESCRIPTION=stop the specified bundle(s)
-CONSOLE_HELP_REFRESH_COMMAND_DESCRIPTION=refresh the packages of the specified bundles
-CONSOLE_HELP_UPDATE_COMMAND_DESCRIPTION=update the specified bundle(s)
-CONSOLE_HELP_DISPLAYING_STATUS_HEADER=Displaying Status
-CONSOLE_HELP_STATUS_COMMAND_DESCRIPTION=display installed bundles and registered services
-CONSOLE_HELP_STATE_ARGUMENT_DESCRIPTION=[-s [<comma separated list of bundle states>] [<segment of bsn>]]
-CONSOLE_HELP_SS_COMMAND_DESCRIPTION=display installed bundles (short status)
-CONSOLE_HELP_SERVICES_COMMAND_DESCRIPTION=display registered service details. Examples for [filter]: (objectClass=com.xyz.Person); (&(objectClass=com.xyz.Person)(|(sn=Jensen)(cn=Babs J*))); passing only com.xyz.Person is a shortcut for (objectClass=com.xyz.Person). The filter syntax specification is available at http://www.ietf.org/rfc/rfc1960.txt
-CONSOLE_HELP_PACKAGES_COMMAND_DESCRIPTION=display imported/exported package details
-CONSOLE_HELP_BUNDLES_COMMAND_DESCRIPTION=display details for all installed bundles
-CONSOLE_HELP_BUNDLE_COMMAND_DESCRIPTION=display details for the specified bundle(s)
-CONSOLE_HELP_HEADERS_COMMAND_DESCRIPTION=print bundle headers
-CONSOLE_HELP_EXTRAS_HEADER=Extras
-CONSOLE_HELP_EXEC_COMMAND_DESCRIPTION=execute a command in a separate process and wait
-CONSOLE_HELP_FORK_COMMAND_DESCRIPTION=execute a command in a separate process
-CONSOLE_HELP_KEYVALUE_ARGUMENT_DESCRIPTION=<key>=<value>
-CONSOLE_HELP_FILTER_ARGUMENT_DESCRIPTION=[filter]
-CONSOLE_HELP_PACKAGES_ARGUMENT_DESCRIPTION=[<pkgname>|<id>|<location>]
-CONSOLE_HELP_IDLOCATION_ARGUMENT_DESCRIPTION=(<id>|<location>)
-CONSOLE_HELP_OPTIONAL_IDLOCATION_ARGUMENT_DESCRIPTION=[<id>|<location>]
-CONSOLE_HELP_COMMAND_ARGUMENT_DESCRIPTION=<command>
-CONSOLE_HELP_GETPROP_COMMAND_DESCRIPTION=displays the system properties with the given name, or all of them.
-CONSOLE_HELP_GETPROP_ARGUMENT_DESCRIPTION=[ name ]
-CONSOLE_NO_BUNDLE_SPECIFIED_ERROR=No bundle(s) specified!
-CONSOLE_NOTHING_TO_INSTALL_ERROR=Nothing to install!
-CONSOLE_NO_INSTALLED_BUNDLES_ERROR=No installed bundles.
-CONSOLE_BUNDLE_ID_MESSAGE=Bundle id is
-CONSOLE_FRAMEWORK_IS_LAUNCHED_MESSAGE=Framework is launched.
-CONSOLE_FRAMEWORK_IS_SHUTDOWN_MESSAGE=Framework is shutdown.
-CONSOLE_ID_MESSAGE=Id={0}
-CONSOLE_BUNDLE_LOCATION_MESSAGE=Bundle Location
-CONSOLE_STATE_BUNDLE_FILE_NAME_HEADER=State Bundle File Name
-CONSOLE_REGISTERED_SERVICES_MESSAGE=Registered Services
-CONSOLE_REGISTERED_BY_BUNDLE_MESSAGE=Registered by bundle:
-CONSOLE_BUNDLES_USING_SERVICE_MESSAGE=Bundles using service:
-CONSOLE_NO_BUNDLES_USING_SERVICE_MESSAGE=No bundles using service.
-CONSOLE_NO_REGISTERED_SERVICES_MESSAGE=No registered services.
-CONSOLE_NO_EXPORTED_PACKAGES_MESSAGE=No exported packages
-CONSOLE_NO_IMPORTED_PACKAGES_MESSAGE=No imported packages
-CONSOLE_REMOVAL_PENDING_MESSAGE=removal pending
-CONSOLE_IMPORTS_MESSAGE=imports
-CONSOLE_STALE_MESSAGE=stale
-CONSOLE_NO_EXPORTED_PACKAGES_NO_PACKAGE_ADMIN_MESSAGE=No exported packages [PackageAdmin service is not registered]
-CONSOLE_SERVICES_IN_USE_MESSAGE=Services in use:
-CONSOLE_NO_SERVICES_IN_USE_MESSAGE=No services in use.
-CONSOLE_STATUS_MESSAGE=Status={0}
-CONSOLE_DATA_ROOT_MESSAGE=Data Root={0}
-CONSOLE_EXPORTED_PACKAGES_MESSAGE=Exported packages
-CONSOLE_IMPORTED_PACKAGES_MESSAGE=Imported packages
-CONSOLE_EXPORTED_REMOVAL_PENDING_MESSAGE=[exported(removal pending)]
-CONSOLE_EXPORTED_MESSAGE=[exported]
-CONSOLE_TOTAL_MEMORY_MESSAGE=Total memory:
-CONSOLE_FREE_MEMORY_BEFORE_GARBAGE_COLLECTION_MESSAGE=Free memory before GC:
-CONSOLE_FREE_MEMORY_AFTER_GARBAGE_COLLECTION_MESSAGE=Free memory after GC:
-CONSOLE_MEMORY_GAINED_WITH_GARBAGE_COLLECTION_MESSAGE=Memory gained with GC:
-CONSOLE_FRAMEWORK_LAUNCHED_PLEASE_SHUTDOWN_MESSAGE=Framework is launched. Please shutdown framework first.
-CONSOLE_INVALID_BUNDLE_SPECIFICATION_ERROR=Invalid bundle specification.
-CONSOLE_CAN_NOT_REFRESH_NO_PACKAGE_ADMIN_ERROR=Cannot refresh [PackageAdmin service is not registered]
-CONSOLE_CAN_NOT_USE_STARTLEVEL_NO_STARTLEVEL_SVC_ERROR=Cannot use Startlevel commands [Startlevel service is not registered]
-CONSOLE_NO_COMMAND_SPECIFIED_ERROR=No command specified
-CONSOLE_EXECUTED_RESULT_CODE_MESSAGE=Executed ({0}); result code = {1}
-CONSOLE_STARTED_IN_MESSAGE=Started({0}) in {1}
-CONSOLE_BUNDLE_HEADERS_TITLE=Bundle headers:
-CONSOLE_SYSTEM_PROPERTIES_TITLE=System properties:
-CONSOLE_NO_PARAMETERS_SPECIFIED_TITLE=No parameters specified:
-CONSOLE_SETTING_PROPERTIES_TITLE=Setting Properties:
-CONSOLE_STATE_BUNDLE_TITLE=State Bundle
-CONSOLE_THREADGROUP_TITLE=ThreadGroupType: Name: ParentGroup: MaxP: Threads:
-CONSOLE_THREADTYPE_TITLE=ThreadType: Name: ThreadGroup: Prio:
-CONSOLE_CANNOT_FIND_BUNDLE_ERROR=Cannot find bundle {0}
-CONSOLE_LISTENING_ON_PORT=Listening on port {0} ...
-STARTLEVEL_HELP_HEADING=Controlling Start Level
-STARTLEVEL_HELP_SL=display the start level for the specified bundle, or for the framework if no bundle specified
-STARTLEVEL_HELP_SETFWSL=set the framework start level
-STARTLEVEL_HELP_SETBSL=set the start level for the bundle(s)
-STARTLEVEL_HELP_SETIBSL=set the initial bundle start level
-STARTLEVEL_FRAMEWORK_ACTIVE_STARTLEVEL=Framework Active Start Level = {0}
-STARTLEVEL_NO_STARTLEVEL_GIVEN=No Start Level given.
-STARTLEVEL_NO_STARTLEVEL_OR_BUNDLE_GIVEN=No Bundle or Start Level given.
-STARTLEVEL_INITIAL_BUNDLE_STARTLEVEL=Initial Bundle Start Level = {0}
-STARTLEVEL_BUNDLE_STARTLEVEL=Bundle {0} Start Level = {1}
-STARTLEVEL_ARGUMENT_DESCRIPTION = <start level>
-STARTLEVEL_IDLOCATION_ARGUMENT_DESCRIPTION = <start level> (<id>|<location>)
-STARTLEVEL_POSITIVE_INTEGER=Startlevel must be a positive integer.
-CONSOLE_NAMED_CLASS_SPACE_MESSAGE=Named class space
-CONSOLE_PROVIDED_MESSAGE=[provided]
-CONSOLE_HOST_MESSAGE=Host bundles
-CONSOLE_NO_HOST_MESSAGE=No host bundles
-CONSOLE_FRAGMENT_MESSAGE=Fragment bundles
-CONSOLE_NO_FRAGMENT_MESSAGE=No fragment bundles
-CONSOLE_NO_NAMED_CLASS_SPACES_MESSAGE=No named class spaces
-CONSOLE_REQUIRED_BUNDLES_MESSAGE=Required bundles
-CONSOLE_NO_REQUIRED_BUNDLES_MESSAGE=No required bundles
-CONSOLE_REQUIRES_MESSAGE=[requires]
-CONSOLE_HELP_PROFILE_HEADING=Controlling the Profiling
-CONSOLE_HELP_PROFILELOG_DESCRIPTION=Display & flush the profile log messages
-CONSOLE_HELP_HELP_COMMAND_DESCRIPTION=Display help for the specified command
-CONSOLE_PROPS_COMMAND_DESCRIPTION=Display system properties
-CONSOLE_THREADS_COMMAND_DESCRIPTION=Display threads and thread groups
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMsg.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMsg.java
deleted file mode 100644
index ac72bc22c..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/ConsoleMsg.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import org.eclipse.osgi.util.NLS;
-
-public class ConsoleMsg extends NLS {
- private static final String BUNDLE_NAME = "org.eclipse.osgi.framework.internal.core.ConsoleMessages"; //$NON-NLS-1$
-
- public static String CONSOLE_LINES_TO_SCROLL_NEGATIVE_ERROR;
- public static String CONSOLE_NESTED_EXCEPTION;
- public static String CONSOLE_ERROR_READING_RESOURCE;
- public static String CONSOLE_RESOURCE_NOT_IN_BUNDLE;
- public static String CONSOLE_MORE;
- public static String CONSOLE_HELP_CONTROLLING_CONSOLE_HEADING;
- public static String CONSOLE_HELP_MORE;
- public static String CONSOLE_HELP_DISCONNECT;
- public static String CONSOLE_CONFIRM_MORE;
- public static String CONSOLE_CONFIRM_DISCONNECT;
- public static String CONSOLE_CONFIRM;
- public static String CONSOLE_CONFIRM_VALUES;
- public static String CONSOLE_Y;
- public static String CONSOLE_N;
- public static String CONSOLE_PROMPT_DEFAULT;
- public static String CONSOLE_INVALID_INPUT;
- public static String CONSOLE_TOO_MUCH_INVALID_INPUT;
- public static String CONSOLE_MORE_ENTER_LINES;
-
- public static String CONSOLE_LISTENING_ON_PORT;
- public static String CONSOLE_PROMPT;
-
- public static String CONSOLE_HELP_CONTROLLING_FRAMEWORK_HEADER;
- public static String CONSOLE_HELP_LAUNCH_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_SHUTDOWN_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_CLOSE_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_EXIT_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_GC_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_INIT_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_KEYVALUE_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_SETPROP_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_CONTROLLING_BUNDLES_HEADER;
- public static String CONSOLE_HELP_INSTALL_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_UNINSTALL_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_START_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_STOP_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_REFRESH_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_DISPLAYING_STATUS_HEADER;
- public static String CONSOLE_HELP_STATUS_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_STATE_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_SS_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_FILTER_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_SERVICES_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_PACKAGES_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_PACKAGES_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_BUNDLES_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_IDLOCATION_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_BUNDLE_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_HEADERS_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_EXTRAS_HEADER;
- public static String CONSOLE_HELP_COMMAND_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_GETPROP_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_GETPROP_ARGUMENT_DESCRIPTION;
- public static String CONSOLE_HELP_EXEC_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_FORK_COMMAND_DESCRIPTION;
- public static String STARTLEVEL_HELP_HEADING;
- public static String CONSOLE_HELP_OPTIONAL_IDLOCATION_ARGUMENT_DESCRIPTION;
- public static String STARTLEVEL_HELP_SL;
- public static String STARTLEVEL_ARGUMENT_DESCRIPTION;
- public static String STARTLEVEL_HELP_SETFWSL;
- public static String STARTLEVEL_IDLOCATION_ARGUMENT_DESCRIPTION;
- public static String STARTLEVEL_HELP_SETBSL;
- public static String STARTLEVEL_HELP_SETIBSL;
- public static String CONSOLE_HELP_PROFILE_HEADING;
- public static String CONSOLE_HELP_PROFILELOG_DESCRIPTION;
- public static String CONSOLE_HELP_UPDATE_COMMAND_DESCRIPTION;
- public static String CONSOLE_HELP_HELP_COMMAND_DESCRIPTION;
-
- public static String CONSOLE_NO_BUNDLE_SPECIFIED_ERROR;
- public static String CONSOLE_NOTHING_TO_INSTALL_ERROR;
- public static String CONSOLE_BUNDLE_ID_MESSAGE;
- public static String CONSOLE_NO_INSTALLED_BUNDLES_ERROR;
- public static String CONSOLE_REGISTERED_SERVICES_MESSAGE;
- public static String CONSOLE_FRAMEWORK_IS_LAUNCHED_MESSAGE;
- public static String CONSOLE_FRAMEWORK_IS_SHUTDOWN_MESSAGE;
- public static String CONSOLE_ID;
- public static String CONSOLE_BUNDLE_LOCATION_MESSAGE;
- public static String CONSOLE_STATE_BUNDLE_FILE_NAME_HEADER;
- public static String CONSOLE_BUNDLES_USING_SERVICE_MESSAGE;
- public static String CONSOLE_NO_REGISTERED_SERVICES_MESSAGE;
- public static String CONSOLE_NO_BUNDLES_USING_SERVICE_MESSAGE;
- public static String CONSOLE_REGISTERED_BY_BUNDLE_MESSAGE;
- public static String CONSOLE_IMPORTS_MESSAGE;
- public static String CONSOLE_STALE_MESSAGE;
- public static String CONSOLE_NO_EXPORTED_PACKAGES_NO_PACKAGE_ADMIN_MESSAGE;
- public static String CONSOLE_NO_EXPORTED_PACKAGES_MESSAGE;
- public static String CONSOLE_REMOVAL_PENDING_MESSAGE;
- public static String CONSOLE_SERVICES_IN_USE_MESSAGE;
- public static String CONSOLE_NO_SERVICES_IN_USE_MESSAGE;
- public static String CONSOLE_ID_MESSAGE;
- public static String CONSOLE_STATUS_MESSAGE;
- public static String CONSOLE_DATA_ROOT_MESSAGE;
-
- public static String CONSOLE_IMPORTED_PACKAGES_MESSAGE;
- public static String CONSOLE_NO_IMPORTED_PACKAGES_MESSAGE;
- public static String CONSOLE_HOST_MESSAGE;
- public static String CONSOLE_EXPORTED_PACKAGES_MESSAGE;
- public static String CONSOLE_EXPORTED_REMOVAL_PENDING_MESSAGE;
- public static String CONSOLE_EXPORTED_MESSAGE;
- public static String CONSOLE_NO_HOST_MESSAGE;
- public static String CONSOLE_FRAGMENT_MESSAGE;
- public static String CONSOLE_NO_FRAGMENT_MESSAGE;
- public static String CONSOLE_NO_NAMED_CLASS_SPACES_MESSAGE;
- public static String CONSOLE_NAMED_CLASS_SPACE_MESSAGE;
- public static String CONSOLE_PROVIDED_MESSAGE;
- public static String CONSOLE_REQUIRED_BUNDLES_MESSAGE;
- public static String CONSOLE_NO_REQUIRED_BUNDLES_MESSAGE;
- public static String CONSOLE_TOTAL_MEMORY_MESSAGE;
- public static String CONSOLE_FREE_MEMORY_BEFORE_GARBAGE_COLLECTION_MESSAGE;
- public static String CONSOLE_FREE_MEMORY_AFTER_GARBAGE_COLLECTION_MESSAGE;
- public static String CONSOLE_MEMORY_GAINED_WITH_GARBAGE_COLLECTION_MESSAGE;
- public static String CONSOLE_FRAMEWORK_LAUNCHED_PLEASE_SHUTDOWN_MESSAGE;
- public static String CONSOLE_INVALID_BUNDLE_SPECIFICATION_ERROR;
- public static String CONSOLE_CAN_NOT_REFRESH_NO_PACKAGE_ADMIN_ERROR;
- public static String CONSOLE_NO_COMMAND_SPECIFIED_ERROR;
- public static String CONSOLE_STARTED_IN_MESSAGE;
- public static String CONSOLE_EXECUTED_RESULT_CODE_MESSAGE;
- public static String CONSOLE_BUNDLE_HEADERS_TITLE;
- public static String CONSOLE_SYSTEM_PROPERTIES_TITLE;
- public static String CONSOLE_NO_PARAMETERS_SPECIFIED_TITLE;
- public static String CONSOLE_SETTING_PROPERTIES_TITLE;
- public static String CONSOLE_STATE_BUNDLE_TITLE;
- public static String CONSOLE_THREADGROUP_TITLE;
- public static String CONSOLE_THREADTYPE_TITLE;
- public static String CONSOLE_REQUIRES_MESSAGE;
- public static String CONSOLE_CAN_NOT_USE_STARTLEVEL_NO_STARTLEVEL_SVC_ERROR;
- public static String CONSOLE_CANNOT_FIND_BUNDLE_ERROR;
- public static String CONSOLE_PROPS_COMMAND_DESCRIPTION;
- public static String CONSOLE_THREADS_COMMAND_DESCRIPTION;
-
- public static String STARTLEVEL_FRAMEWORK_ACTIVE_STARTLEVEL;
- public static String STARTLEVEL_BUNDLE_STARTLEVEL;
- public static String STARTLEVEL_NO_STARTLEVEL_GIVEN;
- public static String STARTLEVEL_NO_STARTLEVEL_OR_BUNDLE_GIVEN;
- public static String STARTLEVEL_INITIAL_BUNDLE_STARTLEVEL;
- public static String STARTLEVEL_POSITIVE_INTEGER;
-
- static {
- // initialize resource bundles
- NLS.initializeMessages(BUNDLE_NAME, ConsoleMsg.class);
- }
-} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandInterpreter.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandInterpreter.java
deleted file mode 100644
index c23e1feac..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandInterpreter.java
+++ /dev/null
@@ -1,599 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.URL;
-import java.util.*;
-import org.eclipse.osgi.framework.console.CommandInterpreter;
-import org.eclipse.osgi.framework.console.CommandProvider;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.Bundle;
-
-/**
- * This class knows how to parse and execute the command line arguments to the FrameworkConsole.
- * It attempts to pass the command to each registered CommandProvider until it finds one
- * that knows what to do with it.
- *
- * FrameworkCommandInterpreter provides support for the "More" command which allows the operator to configure
- * the number of lines to display before being prompted to continue.
- *
- * FrameworkCommandInterpreter provides several print methods which handle the "More" command.
- */
-public class FrameworkCommandInterpreter implements CommandInterpreter {
- private static final String WS_DELIM = " \t\n\r\f"; //$NON-NLS-1$
-
- /** The command line in StringTokenizer form */
- private StringTokenizer tok;
- /** The active CommandProviders */
- private CommandProvider[] commandProviders;
- /** The FrameworkConsole */
- private FrameworkConsole con;
- /** The stream to send output to */
- private PrintWriter out;
-
- /** Strings used to format other strings */
- private String tab = "\t"; //$NON-NLS-1$
- private String newline = "\r\n"; //$NON-NLS-1$
- private boolean firstCommand = true;
-
- /**
- * The maximum number of lines to print without user prompt.
- * 0 means no user prompt is required, the window is scrollable.
- */
- protected static int maxLineCount;
-
- /** The number of lines printed without user prompt.*/
- protected int currentLineCount;
-
- /**
- * The constructor. It turns the cmdline string into a StringTokenizer and remembers
- * the input parms.
- */
- public FrameworkCommandInterpreter(String cmdline, CommandProvider[] commandProviders, FrameworkConsole con) {
- tok = new StringTokenizer(cmdline);
- this.commandProviders = commandProviders;
- this.con = con;
- this.out = con.getWriter();
- }
-
- /**
- Get the next argument in the input.
-
- E.g. if the commandline is hello world, the _hello method
- will get "world" as the first argument.
-
- @return A string containing the next argument on the command line
- */
- public String nextArgument() {
- if (tok == null || !tok.hasMoreElements())
- return null;
- return consumeQuotes(tok.nextToken());
- }
-
- private String consumeQuotes(String arg) {
- if (!(arg.startsWith("\"") || arg.startsWith("'"))) //$NON-NLS-1$//$NON-NLS-2$
- return arg;
- String quote = arg.substring(0, 1);
- if (arg.endsWith(quote)) {
- if (arg.length() >= 2)
- // strip the beginning and ending quotes
- return arg.substring(1, arg.length() - 1);
- // single quote case; return empty string
- return ""; //$NON-NLS-1$
- }
-
- try {
- arg = arg.substring(1) + tok.nextToken(quote);
- } catch (NoSuchElementException e) {
- // should not happen
- printStackTrace(e);
- return ""; //$NON-NLS-1$
- }
- try {
- // skip to next whitespace separated token
- tok.nextToken(WS_DELIM);
- } catch (NoSuchElementException e) {
- // this is ok we are at the end
- }
- return arg;
- }
-
- /**
- Execute a command line as if it came from the end user.
-
- Searches the list of command providers using introspection until
- it finds one that contains a matching method. It searches for a method
- with the name "_cmd" where cmd is the command to execute. For example,
- for a command of "launch" execute searches for a method called "_launch".
-
- @param cmd The name of the command to execute.
- @return The object returned by the method executed.
- */
- public Object execute(String cmd) {
- if (!firstCommand)
- return innerExecute(cmd);
- firstCommand = false;
- resetLineCount();
- Object retval = null;
- // handle "more" command here
- if (cmd.equalsIgnoreCase("more")) { //$NON-NLS-1$
- try {
- _more();
- } catch (Exception e) {
- printStackTrace(e);
- }
- return retval;
- }
- // handle "disconnect" command here
- if (cmd.equalsIgnoreCase("disconnect")) { //$NON-NLS-1$
- try {
- _disconnect();
- } catch (Exception e) {
- printStackTrace(e);
- }
- return retval;
- }
-
- // handle "help" command here
- if (cmd.equalsIgnoreCase("help") && !tok.hasMoreElements()) { //$NON-NLS-1$
- displayAllHelp();
- return retval;
- }
-
- Class<?>[] parameterTypes = new Class[] {CommandInterpreter.class};
- Object[] parameters = new Object[] {this};
- boolean executed = false;
- int size = commandProviders.length;
-
- if (cmd.equalsIgnoreCase("help") && tok.hasMoreElements()) { //$NON-NLS-1$
- String commandName = nextArgument();
-
- String builtinHelp = getHelp(commandName);
- if (builtinHelp != null) {
- print(builtinHelp);
- return builtinHelp;
- }
- for (int i = 0; i < size; i++) {
- // re-create the StringTokenizer for the call of each CommandProvider - there may be help commands in more than one CommandProvider
- tok = new StringTokenizer(commandName);
- boolean isException = false;
- Object target = commandProviders[i];
- Method method = null;
- try {
- method = target.getClass().getMethod("_" + cmd, parameterTypes); //$NON-NLS-1$
- retval = method.invoke(target, parameters);
- } catch (NoSuchMethodException e) {
- // keep going - maybe another command provider will provide help <command> method
- isException = true;
- } catch (InvocationTargetException e) {
- // keep going - maybe another command provider will provide help <command> method
- printStackTrace(e.getTargetException());
- isException = true;
- } catch (Exception ee) {
- printStackTrace(ee);
- }
-
- if (retval != null) {
- if (retval instanceof Boolean) {
- executed = executed || ((Boolean) retval).booleanValue();
- } else if (retval instanceof String) {
- print(retval);
- return retval;
- } else {
- // this could happen if a CommandProvider provides an arbitrary help command;
- // since there is no way to determine if this CommandProvider provides the search command,
- // we should continue with the other CommandProvider
- executed = true;
- }
- } else {
- // if the return value is null, but there was no exception assume that a help method was called
- executed = executed || !isException;
- }
- }
- } else {
- for (int i = 0; !executed && (i < size); i++) {
- try {
- Object target = commandProviders[i];
- Method method = target.getClass().getMethod("_" + cmd, parameterTypes); //$NON-NLS-1$
- retval = method.invoke(target, parameters);
- executed = true; // stop after the command has been found
- } catch (NoSuchMethodException ite) {
- // keep going - maybe another command provider will be able to execute this command
- } catch (InvocationTargetException ite) {
- executed = true; // don't want to keep trying - we found the method but got an error
- printStackTrace(ite.getTargetException());
- } catch (Exception ee) {
- executed = true; // don't want to keep trying - we got an error we don't understand
- printStackTrace(ee);
- }
- }
- }
-
- // if no command was found to execute, display help for all registered command providers
- if (!executed) {
- displayAllHelp();
- }
- return retval;
- }
-
- private void displayAllHelp() {
- int size = commandProviders.length;
- for (int i = 0; i < size; i++) {
- try {
- CommandProvider commandProvider = commandProviders[i];
- out.print(commandProvider.getHelp());
- out.flush();
- } catch (Exception ee) {
- printStackTrace(ee);
- }
- }
- // call help for the more command provided by this class
- out.print(getHelp(null));
- out.flush();
- }
-
- private Object innerExecute(String cmd) {
- if (cmd != null && cmd.length() > 0) {
- CommandInterpreter intcp = new FrameworkCommandInterpreter(cmd, commandProviders, con);
- String command = intcp.nextArgument();
- if (command != null)
- return intcp.execute(command);
- }
- return null;
- }
-
- /**
- * Answers the number of lines output to the console
- * window should scroll without user interaction.
- *
- * @return The number of lines to scroll.
- */
- private int getMaximumLinesToScroll() {
- return maxLineCount;
- }
-
- /**
- * Sets the number of lines output to the console
- * window will scroll without user interaction.
- * <p>
- * Note that this number does not include the line
- * for the 'more' prompt itself.
- * <p>
- * If the number of lines is 0 then no 'more' prompt
- * is disabled.
- *
- * @param lines the number of lines to scroll
- */
- private void setMaximumLinesToScroll(int lines) {
- if (lines < 0) {
- throw new IllegalArgumentException(ConsoleMsg.CONSOLE_LINES_TO_SCROLL_NEGATIVE_ERROR);
- }
-
- maxLineCount = lines;
- }
-
- /**
- * Resets the line counter for the 'more' prompt.
- */
- private void resetLineCount() {
- currentLineCount = 0;
- }
-
- /**
- * Prints a string to the output medium (appended with newline character).
- * <p>
- * This method does not increment the line counter for the 'more' prompt.
- *
- * @param o the string to be printed
- */
- private void printline(Object o) {
- print(o + newline);
- }
-
- /**
- * Prints an object to the outputstream
- *
- * @param o the object to be printed
- */
- public void print(Object o) {
- synchronized (out) {
- check4More();
- out.print(o);
- out.flush();
- }
- }
-
- /**
- * Prints a empty line to the outputstream
- */
- public void println() {
- println(""); //$NON-NLS-1$
- }
-
- /**
- * Print a stack trace including nested exceptions.
- * @param t The offending exception
- */
- public void printStackTrace(Throwable t) {
- t.printStackTrace(out);
-
- Method[] methods = t.getClass().getMethods();
-
- int size = methods.length;
- Class<Throwable> throwable = Throwable.class;
-
- for (int i = 0; i < size; i++) {
- Method method = methods[i];
-
- if (Modifier.isPublic(method.getModifiers()) && method.getName().startsWith("get") && throwable.isAssignableFrom(method.getReturnType()) && (method.getParameterTypes().length == 0)) { //$NON-NLS-1$
- try {
- Throwable nested = (Throwable) method.invoke(t, (Object[]) null);
-
- if ((nested != null) && (nested != t)) {
- out.println(ConsoleMsg.CONSOLE_NESTED_EXCEPTION);
- printStackTrace(nested);
- }
- } catch (IllegalAccessException e) {
- // nothing
- } catch (InvocationTargetException e) {
- // nothing
- }
- }
- }
- }
-
- /**
- * Prints an object to the output medium (appended with newline character).
- * <p>
- * If running on the target environment, the user is prompted with '--more'
- * if more than the configured number of lines have been printed without user prompt.
- * This enables the user of the program to have control over scrolling.
- * <p>
- * For this to work properly you should not embed "\n" etc. into the string.
- *
- * @param o the object to be printed
- */
- public void println(Object o) {
- if (o == null) {
- return;
- }
- synchronized (out) {
- check4More();
- printline(o);
- currentLineCount++;
- currentLineCount += o.toString().length() / 80;
- }
- }
-
- /**
- * Prints the given dictionary sorted by keys.
- *
- * @param dic the dictionary to print
- * @param title the header to print above the key/value pairs
- */
- public void printDictionary(Dictionary<?, ?> dic, String title) {
- if (dic == null)
- return;
-
- int count = dic.size();
- String[] keys = new String[count];
- Enumeration<?> keysEnum = dic.keys();
- int i = 0;
- while (keysEnum.hasMoreElements()) {
- keys[i++] = (String) keysEnum.nextElement();
- }
- Util.sortByString(keys);
-
- if (title != null) {
- println(title);
- }
- for (i = 0; i < count; i++) {
- println(" " + keys[i] + " = " + dic.get(keys[i])); //$NON-NLS-1$//$NON-NLS-2$
- }
- println();
- }
-
- /**
- * Prints the given bundle resource if it exists
- *
- * @param bundle the bundle containing the resource
- * @param resource the resource to print
- */
- public void printBundleResource(Bundle bundle, String resource) {
- URL entry = null;
- entry = bundle.getEntry(resource);
- if (entry != null) {
- try {
- println(resource);
- InputStream in = entry.openStream();
- byte[] buffer = new byte[1024];
- int read = 0;
- try {
- while ((read = in.read(buffer)) != -1)
- print(new String(buffer, 0, read));
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- // nothing
- }
- }
- }
- } catch (Exception e) {
- System.err.println(NLS.bind(ConsoleMsg.CONSOLE_ERROR_READING_RESOURCE, resource));
- }
- } else {
- println(NLS.bind(ConsoleMsg.CONSOLE_RESOURCE_NOT_IN_BUNDLE, resource, bundle.toString()));
- }
- }
-
- /**
- * Displays the more... prompt if the max line count has been reached
- * and waits for the operator to hit enter.
- *
- */
- private void check4More() {
- int max = getMaximumLinesToScroll();
- if (max > 0) {
- if (currentLineCount >= max) {
- out.print(ConsoleMsg.CONSOLE_MORE);
- out.flush();
- con.getInput(); // wait for user entry
- resetLineCount(); //Reset the line counter for the 'more' prompt
- }
- }
- }
-
- /**
- Answer a string (may be as many lines as you like) with help
- texts that explain the command.
- */
- public String getHelp(String commandName) {
- boolean all = commandName == null;
- StringBuffer help = new StringBuffer(256);
- if (all) {
- help.append(ConsoleMsg.CONSOLE_HELP_CONTROLLING_CONSOLE_HEADING);
- help.append(newline);
- }
- if (all || "more".equals(commandName)) { //$NON-NLS-1$
- help.append(tab);
- help.append("more - "); //$NON-NLS-1$
- help.append(ConsoleMsg.CONSOLE_HELP_MORE);
- help.append(newline);
- }
- if (all || "disconnect".equals(commandName)) { //$NON-NLS-1$
- help.append(tab);
- help.append("disconnect - "); //$NON-NLS-1$
- help.append(ConsoleMsg.CONSOLE_HELP_DISCONNECT);
- help.append(newline);
- }
- if (all || "help".equals(commandName)) { //$NON-NLS-1$
- help.append(tab);
- help.append("help <commmand> - "); //$NON-NLS-1$
- help.append(ConsoleMsg.CONSOLE_HELP_HELP_COMMAND_DESCRIPTION);
- help.append(newline);
- }
- return help.length() == 0 ? null : help.toString();
- }
-
- /**
- * Toggles the use of the more prompt for displayed output.
- *
- */
- public void _more() throws Exception {
- if (confirm(ConsoleMsg.CONSOLE_CONFIRM_MORE, true)) {
- int lines = prompt(newline + ConsoleMsg.CONSOLE_MORE_ENTER_LINES, 24);
- setMaximumLinesToScroll(lines);
- } else {
- setMaximumLinesToScroll(0);
- }
- }
-
- private void _disconnect() throws Exception {
- if (confirm(ConsoleMsg.CONSOLE_CONFIRM_DISCONNECT, true)) {
- con.shutdown();
- }
- }
-
- /**
- * Prompts the user for confirmation.
- *
- * @param string the message to present to the user to confirm
- * @param defaultAnswer the default result
- *
- * @return <code>true</code> if the user confirms; <code>false</code> otherwise.
- */
- protected boolean confirm(String string, boolean defaultAnswer) {
- synchronized (out) {
- if (string.length() > 0) {
- print(string);
- } else {
- print(ConsoleMsg.CONSOLE_CONFIRM);
- }
- print(" (" + ConsoleMsg.CONSOLE_CONFIRM_VALUES); //$NON-NLS-1$
- if (defaultAnswer) {
- print(ConsoleMsg.CONSOLE_Y + ") "); //$NON-NLS-1$
- } else {
- print(ConsoleMsg.CONSOLE_N + ") "); //$NON-NLS-1$
- }
- }
- String input = con.getInput();
- resetLineCount();
- if (input.length() == 0) {
- return defaultAnswer;
- }
- return input.toLowerCase().charAt(0) == ConsoleMsg.CONSOLE_Y.charAt(0);
- }
-
- /**
- * Prompts the user for input from the input medium providing a default value.
- *
- * @param string the message to present to the user
- * @param defaultAnswer the string to use as a default return value
- *
- * @return The user provided string or the defaultAnswer,
- * if user provided string was empty.
- */
- protected String prompt(String string, String defaultAnswer) {
- if (string.length() > 0) {
- if (defaultAnswer.length() > 0) {
- StringBuffer buf = new StringBuffer(256);
- buf.append(string);
- buf.append(" "); //$NON-NLS-1$
- buf.append(ConsoleMsg.CONSOLE_PROMPT_DEFAULT);
- buf.append("="); //$NON-NLS-1$
- buf.append(defaultAnswer);
- buf.append(") "); //$NON-NLS-1$
- print(buf.toString());
- } else {
- print(string);
- }
- }
- String input = con.getInput();
- resetLineCount();
- if (input.length() > 0) {
- return input;
- }
- return defaultAnswer;
- }
-
- /**
- * Prompts the user for input of a positive integer.
- *
- * @param string the message to present to the user
- * @param defaultAnswer the integer to use as a default return value
- *
- * @return The user provided integer or the defaultAnswer,
- * if user provided an empty input.
- */
- protected int prompt(String string, int defaultAnswer) {
- Integer i = new Integer(defaultAnswer);
- int answer;
- for (int j = 0; j < 3; j++) {
- String s = prompt(string, i.toString());
- try {
- answer = Integer.parseInt(s);
- if (answer >= 0) {
- return answer;
- }
- } catch (NumberFormatException e) {
- // nothing
- }
- println(ConsoleMsg.CONSOLE_INVALID_INPUT);
- }
- println(ConsoleMsg.CONSOLE_TOO_MUCH_INVALID_INPUT);
- return defaultAnswer;
- }
-}
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java
deleted file mode 100644
index 20036db97..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java
+++ /dev/null
@@ -1,1997 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.lang.reflect.Field;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.*;
-import java.util.Map.Entry;
-import org.eclipse.osgi.framework.console.CommandInterpreter;
-import org.eclipse.osgi.framework.console.CommandProvider;
-import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
-import org.eclipse.osgi.internal.profile.Profile;
-import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
-import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.service.packageadmin.RequiredBundle;
-import org.osgi.service.startlevel.StartLevel;
-
-/**
- * This class provides methods to execute commands from the command line. It registers
- * itself as a CommandProvider so it can be invoked by a CommandInterpreter. The
- * FrameworkCommandProvider registers itself with the highest ranking (Integer.MAXVALUE) so it will always be
- * called first. Other CommandProviders should register with lower rankings.
- *
- * The commands provided by this class are:
- ---Controlling the OSGi framework---
- close - shutdown and exit
- exit - exit immediately (System.exit)
- gc - perform a garbage collection
- init - uninstall all bundles
- launch - start the Service Management Framework
- setprop <key>=<value> - set the OSGI property
- shutdown - shutdown the Service Management Framework
- ---Controlliing Bundles---
- install <url> {s[tart]} - install and optionally start bundle from the given URL
- refresh (<id>|<location>) - refresh the packages of the specified bundles
- start (<id>|<location>) - start the specified bundle(s)
- stop (<id>|<location>) - stop the specified bundle(s)
- uninstall (<id>|<location>) - uninstall the specified bundle(s)
- update (<id>|<location>|<*>) - update the specified bundle(s)
- ---Displaying Status---
- bundle (<id>|<location>) - display details for the specified bundle(s)
- bundles - display details for all installed bundles
- headers (<id>|<location>) - print bundle headers
- packages {<pkgname>|<id>|<location>} - display imported/exported package details
- props - display System properties
- services {filter} - display registered service details. Examples for [filter]: (objectClass=com.xyz.Person); (&(objectClass=com.xyz.Person)(sn=Jensen)); passing only com.xyz.Person is a shortcut for (objectClass=com.xyz.Person). The filter syntax specification is available at http://www.ietf.org/rfc/rfc1960.txt
- ss - display installed bundles (short status)
- status - display installed bundles and registered services
- threads - display threads and thread groups
- ---Extras---
- exec <command> - execute a command in a separate process and wait
- fork <command> - execute a command in a separate process
- getprop <name> - Displays the system properties with the given name, or all of them.
- ---Controlling StartLevel---
- sl {(<id>|<location>)} - display the start level for the specified bundle, or for the framework if no bundle specified
- setfwsl <start level> - set the framework start level
- setbsl <start level> (<id>|<location>) - set the start level for the bundle(s)
- setibsl <start level> - set the initial bundle start level
- ---Getting Help---
- help <command> - Display help for the specified command
-
- *
- * There is a method for each command which is named '_'+method. The methods are
- * invoked by a CommandInterpreter's execute method.
- */
-public class FrameworkCommandProvider implements CommandProvider, SynchronousBundleListener {
-
- /** An instance of the OSGi framework */
- private final Framework framework;
- /** The system bundle context */
- private final BundleContext context;
- /** The start level implementation */
- private final StartLevelManager slImpl;
- private final SecurityAdmin securityAdmin;
- private ServiceRegistration<?> providerReg;
-
- /** Strings used to format other strings */
- private final static String tab = "\t"; //$NON-NLS-1$
- private final static String newline = "\r\n"; //$NON-NLS-1$
-
- /** this list contains the bundles known to be lazily awaiting activation */
- private final List<Bundle> lazyActivation = new ArrayList<Bundle>();
-
- /** this map contains the mapping between the command name and its description and eventually arguments.*/
- private Map<String, String[]> commandsHelp = null;
- /** this map contains the mapping between the command groups and the names of the commands in each group*/
- private Map<String, String[]> commandGroups = null;
-
- /**
- * Constructor.
- *
- * initialize must be called after creating this object.
- *
- * @param framework The current instance of the framework
- */
- public FrameworkCommandProvider(Framework framework) {
- this.framework = framework;
- context = framework.systemBundle.getContext();
- slImpl = framework.startLevelManager;
- securityAdmin = framework.securityAdmin;
- }
-
- /**
- * Starts this CommandProvider.
- *
- * Registers this object as a CommandProvider with the highest ranking possible.
- * Adds this object as a SynchronousBundleListener.
- */
- void start() {
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE));
- providerReg = context.registerService(CommandProvider.class.getName(), this, props);
- context.addBundleListener(this);
- }
-
- void stop() {
- context.removeBundleListener(this);
- if (providerReg != null)
- providerReg.unregister();
- }
-
- /**
- Answer a string (may be as many lines as you like) with help
- texts that explain the command. This getHelp() method uses the
- ConsoleMsg class to obtain the correct NLS data to display to the user.
-
- @return The help string
- */
- public String getHelp() {
- return getHelp(null);
- }
-
- /* This method either returns the help message for a particular command,
- * or returns the help messages for all commands (if commandName is not specified)*/
- private String getHelp(String commandName) {
- StringBuffer help = new StringBuffer(1024);
-
- if (commandsHelp == null) {
- initializeCommandsHelp();
- }
-
- if (commandGroups == null) {
- initializeCommandGroups();
- }
-
- if (commandName != null) {
- if (commandsHelp.containsKey(commandName)) {
- addCommand(commandName, commandsHelp.get(commandName), help);
- }
- return help.toString();
- }
-
- for (Entry<String, String[]> groupEntry : commandGroups.entrySet()) {
- addHeader(groupEntry.getKey(), help);
- for (String command : groupEntry.getValue()) {
- addCommand(command, commandsHelp.get(command), help);
- }
- }
-
- return help.toString();
- }
-
- private void initializeCommandsHelp() {
- commandsHelp = new HashMap<String, String[]>();
- // add help for commands for controlling the framework
- commandsHelp.put("launch", new String[] {ConsoleMsg.CONSOLE_HELP_LAUNCH_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("shutdown", new String[] {ConsoleMsg.CONSOLE_HELP_SHUTDOWN_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("close", new String[] {ConsoleMsg.CONSOLE_HELP_CLOSE_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("exit", new String[] {ConsoleMsg.CONSOLE_HELP_EXIT_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("init", new String[] {ConsoleMsg.CONSOLE_HELP_INIT_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("setprop", new String[] {ConsoleMsg.CONSOLE_HELP_KEYVALUE_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_SETPROP_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("setp", new String[] {ConsoleMsg.CONSOLE_HELP_KEYVALUE_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_SETPROP_COMMAND_DESCRIPTION}); //$NON-NLS-1$
-
- // add help for commands for controlling bundles
- commandsHelp.put("install", new String[] {ConsoleMsg.CONSOLE_HELP_INSTALL_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("i", new String[] {ConsoleMsg.CONSOLE_HELP_INSTALL_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("uninstall", new String[] {ConsoleMsg.CONSOLE_HELP_UNINSTALL_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("un", new String[] {ConsoleMsg.CONSOLE_HELP_UNINSTALL_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("start", new String[] {ConsoleMsg.CONSOLE_HELP_START_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("sta", new String[] {ConsoleMsg.CONSOLE_HELP_START_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("stop", new String[] {ConsoleMsg.CONSOLE_HELP_STOP_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("sto", new String[] {ConsoleMsg.CONSOLE_HELP_STOP_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("refresh", new String[] {ConsoleMsg.CONSOLE_HELP_REFRESH_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("r", new String[] {ConsoleMsg.CONSOLE_HELP_REFRESH_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("update", new String[] {ConsoleMsg.CONSOLE_HELP_UPDATE_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("up", new String[] {ConsoleMsg.CONSOLE_HELP_UPDATE_COMMAND_DESCRIPTION}); //$NON-NLS-1$
-
- // add help for commands for displaying status
- commandsHelp.put("status", new String[] {ConsoleMsg.CONSOLE_HELP_STATE_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_STATUS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("s", new String[] {ConsoleMsg.CONSOLE_HELP_STATE_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_STATUS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("ss", new String[] {ConsoleMsg.CONSOLE_HELP_STATE_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_SS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("services", new String[] {ConsoleMsg.CONSOLE_HELP_FILTER_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_SERVICES_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("packages", new String[] {ConsoleMsg.CONSOLE_HELP_PACKAGES_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_PACKAGES_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("p", new String[] {ConsoleMsg.CONSOLE_HELP_PACKAGES_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_PACKAGES_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("bundles", new String[] {ConsoleMsg.CONSOLE_HELP_STATE_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_BUNDLES_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("bundle", new String[] {ConsoleMsg.CONSOLE_HELP_IDLOCATION_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_BUNDLE_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("b", new String[] {ConsoleMsg.CONSOLE_HELP_IDLOCATION_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_BUNDLE_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("headers", new String[] {ConsoleMsg.CONSOLE_HELP_IDLOCATION_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_HEADERS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("h", new String[] {ConsoleMsg.CONSOLE_HELP_IDLOCATION_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_HEADERS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
-
- // add help for extra commands
- commandsHelp.put("exec", new String[] {ConsoleMsg.CONSOLE_HELP_COMMAND_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_EXEC_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("fork", new String[] {ConsoleMsg.CONSOLE_HELP_COMMAND_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_FORK_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("gc", new String[] {ConsoleMsg.CONSOLE_HELP_GC_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("getprop", new String[] {ConsoleMsg.CONSOLE_HELP_GETPROP_ARGUMENT_DESCRIPTION, ConsoleMsg.CONSOLE_HELP_GETPROP_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("props", new String[] {ConsoleMsg.CONSOLE_PROPS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("pr", new String[] {ConsoleMsg.CONSOLE_PROPS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("threads", new String[] {ConsoleMsg.CONSOLE_THREADS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
- commandsHelp.put("t", new String[] {ConsoleMsg.CONSOLE_THREADS_COMMAND_DESCRIPTION}); //$NON-NLS-1$
-
- // add help for startlevel commands
- commandsHelp.put("sl", new String[] {ConsoleMsg.CONSOLE_HELP_OPTIONAL_IDLOCATION_ARGUMENT_DESCRIPTION, ConsoleMsg.STARTLEVEL_HELP_SL}); //$NON-NLS-1$
- commandsHelp.put("setfwsl", new String[] {ConsoleMsg.STARTLEVEL_ARGUMENT_DESCRIPTION, ConsoleMsg.STARTLEVEL_HELP_SETFWSL}); //$NON-NLS-1$
- commandsHelp.put("setbsl", new String[] {ConsoleMsg.STARTLEVEL_IDLOCATION_ARGUMENT_DESCRIPTION, ConsoleMsg.STARTLEVEL_HELP_SETBSL}); //$NON-NLS-1$
- commandsHelp.put("setibsl", new String[] {ConsoleMsg.STARTLEVEL_ARGUMENT_DESCRIPTION, ConsoleMsg.STARTLEVEL_HELP_SETIBSL}); //$NON-NLS-1$
-
- // add help for profilelog command
- commandsHelp.put("profilelog", new String[] {ConsoleMsg.CONSOLE_HELP_PROFILELOG_DESCRIPTION}); //$NON-NLS-1$
- }
-
- private void initializeCommandGroups() {
- commandGroups = new LinkedHashMap<String, String[]>();
- commandGroups.put(ConsoleMsg.CONSOLE_HELP_CONTROLLING_FRAMEWORK_HEADER, new String[] {"launch", "shutdown", "close", "exit", "init", "setprop"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
- commandGroups.put(ConsoleMsg.CONSOLE_HELP_CONTROLLING_BUNDLES_HEADER, new String[] {"install", "uninstall", "start", "stop", "refresh", "update"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
- commandGroups.put(ConsoleMsg.CONSOLE_HELP_DISPLAYING_STATUS_HEADER, new String[] {"status", "ss", "services", "packages", "bundles", "bundle", "headers"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
- commandGroups.put(ConsoleMsg.CONSOLE_HELP_EXTRAS_HEADER, new String[] {"exec", "fork", "gc", "getprop", "props", "threads"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
- commandGroups.put(ConsoleMsg.STARTLEVEL_HELP_HEADING, new String[] {"sl", "setfwsl", "setbsl", "setibsl"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- commandGroups.put(ConsoleMsg.CONSOLE_HELP_PROFILE_HEADING, new String[] {"profilelog"}); //$NON-NLS-1$
- }
-
- /** Private helper method for getHelp. Formats the help headers. */
- private void addHeader(String header, StringBuffer help) {
- help.append("---"); //$NON-NLS-1$
- help.append(header);
- help.append("---"); //$NON-NLS-1$
- help.append(newline);
- }
-
- /** Private helper method for getHelp. Formats the command descriptions. */
- private void addCommand(String command, String description, StringBuffer help) {
- help.append(tab);
- help.append(command);
- help.append(" - "); //$NON-NLS-1$
- help.append(description);
- help.append(newline);
- }
-
- /** Private helper method for getHelp. Formats the command descriptions with command arguments. */
- private void addCommand(String command, String parameters, String description, StringBuffer help) {
- help.append(tab);
- help.append(command);
- help.append(" "); //$NON-NLS-1$
- help.append(parameters);
- help.append(" - "); //$NON-NLS-1$
- help.append(description);
- help.append(newline);
- }
-
- /** Private helper method for getHelp. According to its arguments chooses which one of the above addCommand methods to use. */
- private void addCommand(String command, String[] attributes, StringBuffer help) {
- if (attributes.length == 1) {
- addCommand(command, attributes[0], help);
- } else if (attributes.length == 2) {
- addCommand(command, attributes[0], attributes[1], help);
- }
- }
-
- /**
- * Handle the exit command. Exit immediately (System.exit)
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _exit(CommandInterpreter intp) throws Exception {
- intp.println();
- System.exit(0);
- }
-
- /**
- * Handle the launch command. Start the OSGi framework.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _launch(CommandInterpreter intp) throws Exception {
- framework.launch();
- }
-
- /**
- * Handle the shutdown command. Shutdown the OSGi framework.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _shutdown(CommandInterpreter intp) throws Exception {
- framework.shutdown(FrameworkEvent.STOPPED);
- }
-
- /**
- * Handle the start command's abbreviation. Invoke _start()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _sta(CommandInterpreter intp) throws Exception {
- _start(intp);
- }
-
- /**
- * Handle the start command. Start the specified bundle(s).
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _start(CommandInterpreter intp) throws Exception {
- String nextArg = intp.nextArgument();
- if (nextArg == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- }
- while (nextArg != null) {
- AbstractBundle bundle = getBundleFromToken(intp, nextArg, true);
- if (bundle != null) {
- bundle.start();
- }
- nextArg = intp.nextArgument();
- }
- }
-
- /**
- * Handle the stop command's abbreviation. Invoke _stop()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _sto(CommandInterpreter intp) throws Exception {
- _stop(intp);
- }
-
- /**
- * Handle the stop command. Stop the specified bundle(s).
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _stop(CommandInterpreter intp) throws Exception {
- String nextArg = intp.nextArgument();
- if (nextArg == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- }
- while (nextArg != null) {
- AbstractBundle bundle = getBundleFromToken(intp, nextArg, true);
- if (bundle != null) {
- bundle.stop();
- }
- nextArg = intp.nextArgument();
- }
- }
-
- /**
- * Handle the install command's abbreviation. Invoke _install()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _i(CommandInterpreter intp) throws Exception {
- _install(intp);
- }
-
- /**
- * Handle the install command. Install and optionally start bundle from the given URL\r\n"
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _install(CommandInterpreter intp) throws Exception {
- String url = intp.nextArgument();
- if (url == null) {
- intp.println(ConsoleMsg.CONSOLE_NOTHING_TO_INSTALL_ERROR);
- } else {
- AbstractBundle bundle = (AbstractBundle) context.installBundle(url);
- intp.print(ConsoleMsg.CONSOLE_BUNDLE_ID_MESSAGE);
- intp.println(new Long(bundle.getBundleId()));
-
- String nextArg = intp.nextArgument();
- if (nextArg != null) {
- String start = nextArg.toLowerCase();
-
- if (matchCommand("start", start, 1)) { //$NON-NLS-1$
- bundle.start();
- }
- }
- }
-
- }
-
- private static boolean matchCommand(String command, String input, int minLength) {
- if (minLength <= 0)
- minLength = command.length();
- int length = input.length();
- if (minLength > length)
- length = minLength;
- return (command.regionMatches(0, input, 0, length));
- }
-
- /**
- * Handle the update command's abbreviation. Invoke _update()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _up(CommandInterpreter intp) throws Exception {
- _update(intp);
- }
-
- /**
- * Handle the update command. Update the specified bundle(s).
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _update(CommandInterpreter intp) throws Exception {
- String token = intp.nextArgument();
- if (token == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- }
- while (token != null) {
-
- if ("*".equals(token)) { //$NON-NLS-1$
- AbstractBundle[] bundles = (AbstractBundle[]) context.getBundles();
-
- int size = bundles.length;
-
- if (size > 0) {
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = bundles[i];
-
- if (bundle.getBundleId() != 0) {
- try {
- bundle.update();
- } catch (BundleException e) {
- intp.printStackTrace(e);
- }
- }
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_NO_INSTALLED_BUNDLES_ERROR);
- }
- } else {
- AbstractBundle bundle = getBundleFromToken(intp, token, true);
- if (bundle != null) {
- String source = intp.nextArgument();
- try {
- if (source != null) {
- bundle.update(new URL(source).openStream());
- } else {
- bundle.update();
- }
- } catch (BundleException e) {
- intp.printStackTrace(e);
- }
- }
- }
- token = intp.nextArgument();
- }
- }
-
- /**
- * Handle the uninstall command's abbreviation. Invoke _uninstall()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _un(CommandInterpreter intp) throws Exception {
- _uninstall(intp);
- }
-
- /**
- * Handle the uninstall command. Uninstall the specified bundle(s).
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _uninstall(CommandInterpreter intp) throws Exception {
- String nextArg = intp.nextArgument();
- if (nextArg == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- }
- while (nextArg != null) {
- AbstractBundle bundle = getBundleFromToken(intp, nextArg, true);
- if (bundle != null) {
- bundle.uninstall();
- }
- nextArg = intp.nextArgument();
- }
- }
-
- /**
- * Handle the status command's abbreviation. Invoke _status()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _s(CommandInterpreter intp) throws Exception {
- _status(intp);
- }
-
- private Object[] processOption(CommandInterpreter intp) {
- String option = intp.nextArgument();
- String filteredName = null;
- int stateFilter = -1;
- if (option != null && option.equals("-s")) { //$NON-NLS-1$
- String searchedState = intp.nextArgument();
- if (searchedState == null)
- searchedState = ""; //$NON-NLS-1$
- StringTokenizer tokens = new StringTokenizer(searchedState, ","); //$NON-NLS-1$
- while (tokens.hasMoreElements()) {
- String desiredState = (String) tokens.nextElement();
- Field match = null;
- try {
- match = Bundle.class.getField(desiredState.toUpperCase());
- if (stateFilter == -1)
- stateFilter = 0;
- stateFilter |= match.getInt(match);
- } catch (NoSuchFieldException e) {
- intp.println(ConsoleMsg.CONSOLE_INVALID_INPUT + ": " + desiredState); //$NON-NLS-1$
- return null;
- } catch (IllegalAccessException e) {
- intp.println(ConsoleMsg.CONSOLE_INVALID_INPUT + ": " + desiredState); //$NON-NLS-1$
- return null;
- }
- }
- } else {
- filteredName = option;
- }
- String tmp = intp.nextArgument();
- if (tmp != null)
- filteredName = tmp;
- return new Object[] {filteredName, new Integer(stateFilter)};
- }
-
- /**
- * Handle the status command. Display installed bundles and registered services.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _status(CommandInterpreter intp) throws Exception {
- if (framework.isActive()) {
- intp.println(ConsoleMsg.CONSOLE_FRAMEWORK_IS_LAUNCHED_MESSAGE);
- } else {
- intp.println(ConsoleMsg.CONSOLE_FRAMEWORK_IS_SHUTDOWN_MESSAGE);
- }
- intp.println();
-
- Object[] options = processOption(intp);
- if (options == null)
- return;
-
- AbstractBundle[] bundles = (AbstractBundle[]) context.getBundles();
- int size = bundles.length;
-
- if (size == 0) {
- intp.println(ConsoleMsg.CONSOLE_NO_INSTALLED_BUNDLES_ERROR);
- return;
- }
- intp.print(ConsoleMsg.CONSOLE_ID);
- intp.print(tab);
- intp.println(ConsoleMsg.CONSOLE_BUNDLE_LOCATION_MESSAGE);
- intp.println(ConsoleMsg.CONSOLE_STATE_BUNDLE_FILE_NAME_HEADER);
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = bundles[i];
- if (!match(bundle, (String) options[0], ((Integer) options[1]).intValue()))
- continue;
- intp.print(new Long(bundle.getBundleId()));
- intp.print(tab);
- intp.println(bundle.getLocation());
- intp.print(" "); //$NON-NLS-1$
- intp.print(getStateName(bundle));
- intp.println(bundle.bundledata);
- }
-
- ServiceReference<?>[] services = context.getServiceReferences((String) null, (String) null);
- if (services != null) {
- intp.println(ConsoleMsg.CONSOLE_REGISTERED_SERVICES_MESSAGE);
- size = services.length;
- for (int i = 0; i < size; i++) {
- intp.println(services[i]);
- }
- }
- }
-
- /**
- * Handle the services command's abbreviation. Invoke _services()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _se(CommandInterpreter intp) throws Exception {
- _services(intp);
- }
-
- /**
- * Handle the services command. Display registered service details.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _services(CommandInterpreter intp) throws Exception {
- String filter = null;
-
- String nextArg = intp.nextArgument();
- if (nextArg != null) {
- StringBuffer buf = new StringBuffer();
- while (nextArg != null) {
- buf.append(' ');
- buf.append(nextArg);
- nextArg = intp.nextArgument();
- }
- filter = buf.toString();
- }
-
- InvalidSyntaxException originalException = null;
- ServiceReference<?>[] services = null;
-
- try {
- services = context.getServiceReferences((String) null, filter);
- } catch (InvalidSyntaxException e) {
- originalException = e;
- }
-
- if (filter != null) {
- filter = filter.trim();
- }
- // If the filter is invalid and does not start with a bracket, probably the argument was the name of an interface.
- // Try to construct an object class filter with this argument, and if still invalid - throw the original InvalidSyntaxException
- if (originalException != null && !filter.startsWith("(") && filter.indexOf(' ') < 0) { //$NON-NLS-1$
- try {
- filter = "(" + Constants.OBJECTCLASS + "=" + filter + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- services = context.getServiceReferences((String) null, filter);
- } catch (InvalidSyntaxException e) {
- throw originalException;
- }
- } else if (originalException != null) {
- throw originalException;
- }
-
- if (services != null) {
- int size = services.length;
- if (size > 0) {
- for (int j = 0; j < size; j++) {
- ServiceReference<?> service = services[j];
- intp.println(service);
- intp.print(" "); //$NON-NLS-1$
- intp.print(ConsoleMsg.CONSOLE_REGISTERED_BY_BUNDLE_MESSAGE);
- intp.print(" "); //$NON-NLS-1$
- intp.println(service.getBundle());
- Bundle[] users = service.getUsingBundles();
- if (users != null) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_BUNDLES_USING_SERVICE_MESSAGE);
- for (int k = 0; k < users.length; k++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(users[k]);
- }
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLES_USING_SERVICE_MESSAGE);
- }
- }
- return;
- }
- }
- intp.println(ConsoleMsg.CONSOLE_NO_REGISTERED_SERVICES_MESSAGE);
- }
-
- /**
- * Handle the packages command's abbreviation. Invoke _packages()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _p(CommandInterpreter intp) throws Exception {
- _packages(intp);
- }
-
- /**
- * Handle the packages command. Display imported/exported package details.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _packages(CommandInterpreter intp) throws Exception {
- org.osgi.framework.Bundle bundle = null;
-
- String token = intp.nextArgument();
- if (token != null) {
- bundle = getBundleFromToken(intp, token, false);
- }
-
- ServiceReference<?> packageAdminRef = context.getServiceReference("org.osgi.service.packageadmin.PackageAdmin"); //$NON-NLS-1$
- if (packageAdminRef != null) {
- PackageAdmin packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
- if (packageAdmin != null) {
- try {
- org.osgi.service.packageadmin.ExportedPackage[] packages = null;
-
- if (token != null)
- packages = packageAdmin.getExportedPackages(token);
- if (packages == null)
- packages = packageAdmin.getExportedPackages(bundle);
-
- if (packages == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_EXPORTED_PACKAGES_MESSAGE);
- } else {
- for (int i = 0; i < packages.length; i++) {
- org.osgi.service.packageadmin.ExportedPackage pkg = packages[i];
- intp.print(pkg);
-
- boolean removalPending = pkg.isRemovalPending();
- if (removalPending) {
- intp.print("("); //$NON-NLS-1$
- intp.print(ConsoleMsg.CONSOLE_REMOVAL_PENDING_MESSAGE);
- intp.println(")"); //$NON-NLS-1$
- }
-
- org.osgi.framework.Bundle exporter = pkg.getExportingBundle();
- if (exporter != null) {
- intp.print("<"); //$NON-NLS-1$
- intp.print(exporter);
- intp.println(">"); //$NON-NLS-1$
-
- org.osgi.framework.Bundle[] importers = pkg.getImportingBundles();
- for (int j = 0; j < importers.length; j++) {
- intp.print(" "); //$NON-NLS-1$
- intp.print(importers[j]);
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_IMPORTS_MESSAGE);
- }
- } else {
- intp.print("<"); //$NON-NLS-1$
- intp.print(ConsoleMsg.CONSOLE_STALE_MESSAGE);
- intp.println(">"); //$NON-NLS-1$
- }
-
- }
- }
- } finally {
- context.ungetService(packageAdminRef);
- }
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_NO_EXPORTED_PACKAGES_NO_PACKAGE_ADMIN_MESSAGE);
- }
- }
-
- /**
- * Handle the bundles command. Display details for all installed bundles.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _bundles(CommandInterpreter intp) throws Exception {
- Object[] options = processOption(intp);
- if (options == null)
- return;
-
- AbstractBundle[] bundles = (AbstractBundle[]) context.getBundles();
- int size = bundles.length;
-
- if (size == 0) {
- intp.println(ConsoleMsg.CONSOLE_NO_INSTALLED_BUNDLES_ERROR);
- return;
- }
-
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = bundles[i];
- if (!match(bundle, (String) options[0], ((Integer) options[1]).intValue()))
- continue;
- long id = bundle.getBundleId();
- intp.println(bundle);
- intp.print(" "); //$NON-NLS-1$
- intp.print(NLS.bind(ConsoleMsg.CONSOLE_ID_MESSAGE, String.valueOf(id)));
- intp.print(", "); //$NON-NLS-1$
- intp.print(NLS.bind(ConsoleMsg.CONSOLE_STATUS_MESSAGE, getStateName(bundle)));
- if (id != 0) {
- File dataRoot = framework.getDataFile(bundle, ""); //$NON-NLS-1$
-
- String root = (dataRoot == null) ? null : dataRoot.getAbsolutePath();
-
- intp.print(NLS.bind(ConsoleMsg.CONSOLE_DATA_ROOT_MESSAGE, root));
- } else {
- intp.println();
- }
-
- ServiceReference<?>[] services = bundle.getRegisteredServices();
- if (services != null) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_REGISTERED_SERVICES_MESSAGE);
- for (int j = 0; j < services.length; j++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(services[j]);
- }
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_REGISTERED_SERVICES_MESSAGE);
- }
-
- services = bundle.getServicesInUse();
- if (services != null) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_SERVICES_IN_USE_MESSAGE);
- for (int j = 0; j < services.length; j++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(services[j]);
- }
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_SERVICES_IN_USE_MESSAGE);
- }
- }
- }
-
- /**
- * Handle the bundle command's abbreviation. Invoke _bundle()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _b(CommandInterpreter intp) throws Exception {
- _bundle(intp);
- }
-
- /**
- * Handle the bundle command. Display details for the specified bundle(s).
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _bundle(CommandInterpreter intp) throws Exception {
- String nextArg = intp.nextArgument();
- if (nextArg == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- }
- while (nextArg != null) {
- AbstractBundle bundle = getBundleFromToken(intp, nextArg, true);
- if (bundle != null) {
- long id = bundle.getBundleId();
- intp.println(bundle);
- intp.print(" "); //$NON-NLS-1$
- intp.print(NLS.bind(ConsoleMsg.CONSOLE_ID_MESSAGE, String.valueOf(id)));
- intp.print(", "); //$NON-NLS-1$
- intp.print(NLS.bind(ConsoleMsg.CONSOLE_STATUS_MESSAGE, getStateName(bundle)));
- if (id != 0) {
- File dataRoot = framework.getDataFile(bundle, ""); //$NON-NLS-1$
-
- String root = (dataRoot == null) ? null : dataRoot.getAbsolutePath();
-
- intp.print(NLS.bind(ConsoleMsg.CONSOLE_DATA_ROOT_MESSAGE, root));
- intp.println();
- } else {
- intp.println();
- }
-
- ServiceReference<?>[] services = bundle.getRegisteredServices();
- if (services != null) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_REGISTERED_SERVICES_MESSAGE);
- for (int j = 0; j < services.length; j++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(services[j]);
- }
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_REGISTERED_SERVICES_MESSAGE);
- }
-
- services = bundle.getServicesInUse();
- if (services != null) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_SERVICES_IN_USE_MESSAGE);
- for (int j = 0; j < services.length; j++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(services[j]);
- }
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_SERVICES_IN_USE_MESSAGE);
- }
-
- ServiceReference<?> packageAdminRef = context.getServiceReference("org.osgi.service.packageadmin.PackageAdmin"); //$NON-NLS-1$
- if (packageAdminRef != null) {
- BundleDescription desc = bundle.getBundleDescription();
- if (desc != null) {
- boolean title = true;
- try {
- ExportPackageDescription[] exports = desc.getSelectedExports();
- if (exports == null || exports.length == 0) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_EXPORTED_PACKAGES_MESSAGE);
- } else {
- title = true;
-
- for (int i = 0; i < exports.length; i++) {
- if (title) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_EXPORTED_PACKAGES_MESSAGE);
- title = false;
- }
- intp.print(" "); //$NON-NLS-1$
- intp.print(exports[i].getName());
- intp.print("; version=\""); //$NON-NLS-1$
- intp.print(exports[i].getVersion());
- intp.print("\""); //$NON-NLS-1$
- if (desc.isRemovalPending()) {
- intp.println(ConsoleMsg.CONSOLE_EXPORTED_REMOVAL_PENDING_MESSAGE);
- } else {
- intp.println(ConsoleMsg.CONSOLE_EXPORTED_MESSAGE);
- }
- }
-
- if (title) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_EXPORTED_PACKAGES_MESSAGE);
- }
- }
- title = true;
- if (desc != null) {
- List<ImportPackageSpecification> fragmentsImportPackages = new ArrayList<ImportPackageSpecification>();
-
- // Get bundle' fragments imports
- BundleDescription[] fragments = desc.getFragments();
- for (int i = 0; i < fragments.length; i++) {
- ImportPackageSpecification[] fragmentImports = fragments[i].getImportPackages();
- for (int j = 0; j < fragmentImports.length; j++) {
- fragmentsImportPackages.add(fragmentImports[j]);
- }
- }
-
- // Get all bundle imports
- ImportPackageSpecification[] importPackages;
- if (fragmentsImportPackages.size() > 0) {
- ImportPackageSpecification[] directImportPackages = desc.getImportPackages();
- importPackages = new ImportPackageSpecification[directImportPackages.length + fragmentsImportPackages.size()];
-
- for (int i = 0; i < directImportPackages.length; i++) {
- importPackages[i] = directImportPackages[i];
- }
-
- int offset = directImportPackages.length;
- for (int i = 0; i < fragmentsImportPackages.size(); i++) {
- importPackages[offset + i] = fragmentsImportPackages.get(i);
- }
- } else {
- importPackages = desc.getImportPackages();
- }
-
- // Get all resolved imports
- ExportPackageDescription[] imports = null;
- imports = desc.getContainingState().getStateHelper().getVisiblePackages(desc, StateHelper.VISIBLE_INCLUDE_EE_PACKAGES | StateHelper.VISIBLE_INCLUDE_ALL_HOST_WIRES);
-
- // Get the unresolved optional and dynamic imports
- List<ImportPackageSpecification> unresolvedImports = new ArrayList<ImportPackageSpecification>();
-
- for (int i = 0; i < importPackages.length; i++) {
- if (importPackages[i].getDirective(Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_OPTIONAL)) {
- if (importPackages[i].getSupplier() == null) {
- unresolvedImports.add(importPackages[i]);
- }
- } else if (importPackages[i].getDirective(org.osgi.framework.Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_DYNAMIC)) {
- boolean isResolvable = false;
-
- // Check if the dynamic import can be resolved by any of the wired imports,
- // and if not - add it to the list of unresolved imports
- for (int j = 0; j < imports.length; j++) {
- if (importPackages[i].isSatisfiedBy(imports[j])) {
- isResolvable = true;
- }
- }
-
- if (isResolvable == false) {
- unresolvedImports.add(importPackages[i]);
- }
- }
- }
-
- title = printImportedPackages(imports, intp, title);
-
- if (desc.isResolved() && (unresolvedImports.isEmpty() == false)) {
- printUnwiredDynamicImports(unresolvedImports, intp);
- title = false;
- }
- }
-
- if (title) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_IMPORTED_PACKAGES_MESSAGE);
- }
-
- PackageAdmin packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
- if (packageAdmin != null) {
- intp.print(" "); //$NON-NLS-1$
- if ((packageAdmin.getBundleType(bundle) & PackageAdmin.BUNDLE_TYPE_FRAGMENT) > 0) {
- org.osgi.framework.Bundle[] hosts = packageAdmin.getHosts(bundle);
- if (hosts != null) {
- intp.println(ConsoleMsg.CONSOLE_HOST_MESSAGE);
- for (int i = 0; i < hosts.length; i++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(hosts[i]);
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_NO_HOST_MESSAGE);
- }
- } else {
- org.osgi.framework.Bundle[] fragments = packageAdmin.getFragments(bundle);
- if (fragments != null) {
- intp.println(ConsoleMsg.CONSOLE_FRAGMENT_MESSAGE);
- for (int i = 0; i < fragments.length; i++) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(fragments[i]);
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_NO_FRAGMENT_MESSAGE);
- }
- }
-
- RequiredBundle[] requiredBundles = packageAdmin.getRequiredBundles(null);
- RequiredBundle requiredBundle = null;
- if (requiredBundles != null) {
- for (int i = 0; i < requiredBundles.length; i++) {
- if (requiredBundles[i].getBundle() == bundle) {
- requiredBundle = requiredBundles[i];
- break;
- }
- }
- }
-
- if (requiredBundle == null) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_NAMED_CLASS_SPACES_MESSAGE);
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NAMED_CLASS_SPACE_MESSAGE);
- intp.print(" "); //$NON-NLS-1$
- intp.print(requiredBundle);
- if (requiredBundle.isRemovalPending()) {
- intp.println(ConsoleMsg.CONSOLE_REMOVAL_PENDING_MESSAGE);
- } else {
- intp.println(ConsoleMsg.CONSOLE_PROVIDED_MESSAGE);
- }
- }
- title = true;
- for (int i = 0; i < requiredBundles.length; i++) {
- if (requiredBundles[i] == requiredBundle)
- continue;
-
- org.osgi.framework.Bundle[] depBundles = requiredBundles[i].getRequiringBundles();
- if (depBundles == null)
- continue;
-
- for (int j = 0; j < depBundles.length; j++) {
- if (depBundles[j] == bundle) {
- if (title) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_REQUIRED_BUNDLES_MESSAGE);
- title = false;
- }
- intp.print(" "); //$NON-NLS-1$
- intp.print(requiredBundles[i]);
-
- org.osgi.framework.Bundle provider = requiredBundles[i].getBundle();
- intp.print("<"); //$NON-NLS-1$
- intp.print(provider);
- intp.println(">"); //$NON-NLS-1$
- }
- }
- }
- if (title) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_REQUIRED_BUNDLES_MESSAGE);
- }
-
- }
- } finally {
- context.ungetService(packageAdminRef);
- }
- }
- } else {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_NO_EXPORTED_PACKAGES_NO_PACKAGE_ADMIN_MESSAGE);
- }
-
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- ProtectionDomain domain = bundle.getProtectionDomain();
-
- intp.println(domain);
- }
- }
- nextArg = intp.nextArgument();
- }
- }
-
- private boolean printImportedPackages(ExportPackageDescription[] importedPkgs, CommandInterpreter intp, boolean title) {
- for (int i = 0; i < importedPkgs.length; i++) {
- if (title) {
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_IMPORTED_PACKAGES_MESSAGE);
- title = false;
- }
- intp.print(" "); //$NON-NLS-1$
- intp.print(importedPkgs[i].getName());
- intp.print("; version=\""); //$NON-NLS-1$
- intp.print(importedPkgs[i].getVersion());
- intp.print("\""); //$NON-NLS-1$
- Bundle exporter = context.getBundle(importedPkgs[i].getSupplier().getBundleId());
- if (exporter != null) {
- intp.print("<"); //$NON-NLS-1$
- intp.print(exporter);
- intp.println(">"); //$NON-NLS-1$
- } else {
- intp.print("<"); //$NON-NLS-1$
- intp.print(ConsoleMsg.CONSOLE_STALE_MESSAGE);
- intp.println(">"); //$NON-NLS-1$
- }
- }
- return title;
- }
-
- private void printUnwiredDynamicImports(List<ImportPackageSpecification> dynamicImports, CommandInterpreter intp) {
- for (int i = 0; i < dynamicImports.size(); i++) {
- ImportPackageSpecification importPackage = dynamicImports.get(i);
- intp.print(" "); //$NON-NLS-1$
- intp.print(importPackage.getName());
- intp.print("; version=\""); //$NON-NLS-1$
- intp.print(importPackage.getVersionRange());
- intp.print("\""); //$NON-NLS-1$
- intp.print("<"); //$NON-NLS-1$
- intp.print("unwired"); //$NON-NLS-1$
- intp.print(">"); //$NON-NLS-1$
- intp.print("<"); //$NON-NLS-1$
- intp.print(importPackage.getDirective(org.osgi.framework.Constants.RESOLUTION_DIRECTIVE));
- intp.println(">"); //$NON-NLS-1$
- }
- }
-
- /**
- * Handle the gc command. Perform a garbage collection.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _gc(CommandInterpreter intp) throws Exception {
- long before = Runtime.getRuntime().freeMemory();
-
- /* Let the finilizer finish its work and remove objects from its queue */
- System.gc(); /* asyncronous garbage collector might already run */
- System.gc(); /* to make sure it does a full gc call it twice */
- System.runFinalization();
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // do nothing
- }
-
- long after = Runtime.getRuntime().freeMemory();
- intp.print(ConsoleMsg.CONSOLE_TOTAL_MEMORY_MESSAGE);
- intp.println(String.valueOf(Runtime.getRuntime().totalMemory()));
- intp.print(ConsoleMsg.CONSOLE_FREE_MEMORY_BEFORE_GARBAGE_COLLECTION_MESSAGE);
- intp.println(String.valueOf(before));
- intp.print(ConsoleMsg.CONSOLE_FREE_MEMORY_AFTER_GARBAGE_COLLECTION_MESSAGE);
- intp.println(String.valueOf(after));
- intp.print(ConsoleMsg.CONSOLE_MEMORY_GAINED_WITH_GARBAGE_COLLECTION_MESSAGE);
- intp.println(String.valueOf(after - before));
- }
-
- /**
- * Handle the init command. Uninstall all bundles.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- @SuppressWarnings("deprecation")
- public void _init(CommandInterpreter intp) throws Exception {
- if (framework.isActive()) {
- intp.print(newline);
- intp.println(ConsoleMsg.CONSOLE_FRAMEWORK_LAUNCHED_PLEASE_SHUTDOWN_MESSAGE);
- return;
- }
-
- AbstractBundle[] bundles = (AbstractBundle[]) context.getBundles();
-
- int size = bundles.length;
-
- if (size > 0) {
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = bundles[i];
-
- if (bundle.getBundleId() != 0) {
- try {
- bundle.uninstall();
- } catch (BundleException e) {
- intp.printStackTrace(e);
- }
- }
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_NO_INSTALLED_BUNDLES_ERROR);
- }
- if (securityAdmin != null) {
- // clear the permissions from permission admin
- securityAdmin.setDefaultPermissions(null);
- String[] permLocations = securityAdmin.getLocations();
- if (permLocations != null)
- for (int i = 0; i < permLocations.length; i++)
- securityAdmin.setPermissions(permLocations[i], null);
- ConditionalPermissionUpdate update = securityAdmin.newConditionalPermissionUpdate();
- update.getConditionalPermissionInfos().clear();
- update.commit();
- }
- // clear the permissions from conditional permission admin
- if (securityAdmin != null)
- for (Enumeration<ConditionalPermissionInfo> infos = securityAdmin.getConditionalPermissionInfos(); infos.hasMoreElements();)
- infos.nextElement().delete();
- }
-
- /**
- * Handle the close command. Shutdown and exit.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _close(CommandInterpreter intp) throws Exception {
- intp.println();
- framework.close();
- System.exit(0);
- }
-
- /**
- * Handle the refresh command's abbreviation. Invoke _refresh()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _r(CommandInterpreter intp) throws Exception {
- _refresh(intp);
- }
-
- /**
- * Handle the refresh command. Refresh the packages of the specified bundles.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _refresh(CommandInterpreter intp) throws Exception {
- ServiceReference<?> packageAdminRef = context.getServiceReference("org.osgi.service.packageadmin.PackageAdmin"); //$NON-NLS-1$
- if (packageAdminRef != null) {
- org.osgi.service.packageadmin.PackageAdmin packageAdmin = (org.osgi.service.packageadmin.PackageAdmin) context.getService(packageAdminRef);
- if (packageAdmin != null) {
- try {
- Bundle[] refresh = null;
-
- String token = intp.nextArgument();
- if (token != null) {
- List<Bundle> bundles = new ArrayList<Bundle>();
-
- while (token != null) {
- AbstractBundle bundle = getBundleFromToken(intp, token, true);
-
- if (bundle != null) {
- bundles.add(bundle);
- }
- token = intp.nextArgument();
- }
-
- int size = bundles.size();
-
- if (size == 0) {
- intp.println(ConsoleMsg.CONSOLE_INVALID_BUNDLE_SPECIFICATION_ERROR);
- return;
- }
-
- refresh = new Bundle[size];
- bundles.toArray(refresh);
- }
-
- packageAdmin.refreshPackages(refresh);
- } finally {
- context.ungetService(packageAdminRef);
- }
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_CAN_NOT_REFRESH_NO_PACKAGE_ADMIN_ERROR);
- }
- }
-
- /**
- * Executes the given system command in a separate system process
- * and waits for it to finish.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _exec(CommandInterpreter intp) throws Exception {
- String command = intp.nextArgument();
- if (command == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_COMMAND_SPECIFIED_ERROR);
- return;
- }
-
- Process p = Runtime.getRuntime().exec(command);
-
- intp.println(NLS.bind(ConsoleMsg.CONSOLE_STARTED_IN_MESSAGE, command, String.valueOf(p)));
- int result = p.waitFor();
- intp.println(NLS.bind(ConsoleMsg.CONSOLE_EXECUTED_RESULT_CODE_MESSAGE, command, String.valueOf(result)));
- }
-
- /**
- * Executes the given system command in a separate system process. It does
- * not wait for a result.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _fork(CommandInterpreter intp) throws Exception {
- String command = intp.nextArgument();
- if (command == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_COMMAND_SPECIFIED_ERROR);
- return;
- }
-
- Process p = Runtime.getRuntime().exec(command);
- intp.println(NLS.bind(ConsoleMsg.CONSOLE_STARTED_IN_MESSAGE, command, String.valueOf(p)));
- }
-
- /**
- * Handle the headers command's abbreviation. Invoke _headers()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _h(CommandInterpreter intp) throws Exception {
- _headers(intp);
- }
-
- /**
- * Handle the headers command. Display headers for the specified bundle(s).
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _headers(CommandInterpreter intp) throws Exception {
-
- String nextArg = intp.nextArgument();
- if (nextArg == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- }
- while (nextArg != null) {
- AbstractBundle bundle = getBundleFromToken(intp, nextArg, true);
- if (bundle != null) {
- intp.printDictionary(bundle.getHeaders(), ConsoleMsg.CONSOLE_BUNDLE_HEADERS_TITLE);
- }
- nextArg = intp.nextArgument();
- }
- }
-
- /**
- * Handles the props command's abbreviation. Invokes _props()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _pr(CommandInterpreter intp) throws Exception {
- _props(intp);
- }
-
- /**
- * Handles the _props command. Prints the system properties sorted.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _props(CommandInterpreter intp) throws Exception {
- intp.printDictionary(FrameworkProperties.getProperties(), ConsoleMsg.CONSOLE_SYSTEM_PROPERTIES_TITLE);
- }
-
- /**
- * Handles the setprop command's abbreviation. Invokes _setprop()
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _setp(CommandInterpreter intp) throws Exception {
- _setprop(intp);
- }
-
- /**
- * Handles the setprop command. Sets the CDS property in the given argument.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _setprop(CommandInterpreter intp) throws Exception {
- String argument = intp.nextArgument();
- if (argument == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_PARAMETERS_SPECIFIED_TITLE);
- _props(intp);
- } else {
- InputStream in = new ByteArrayInputStream(argument.getBytes());
- try {
- Properties sysprops = FrameworkProperties.getProperties();
- Properties newprops = new Properties();
- newprops.load(in);
- intp.println(ConsoleMsg.CONSOLE_SETTING_PROPERTIES_TITLE);
- Enumeration<?> keys = newprops.propertyNames();
- while (keys.hasMoreElements()) {
- String key = (String) keys.nextElement();
- String value = (String) newprops.get(key);
- sysprops.put(key, value);
- intp.println(tab + key + " = " + value); //$NON-NLS-1$
- }
- } catch (IOException e) {
- // ignore
- } finally {
- try {
- in.close();
- } catch (IOException e) {
- // ignore
- }
- }
- }
- }
-
- /**
- * Prints the short version of the status.
- * For the long version use "status".
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _ss(CommandInterpreter intp) throws Exception {
- if (framework.isActive()) {
- intp.println();
- intp.println(ConsoleMsg.CONSOLE_FRAMEWORK_IS_LAUNCHED_MESSAGE);
- } else {
- intp.println();
- intp.println(ConsoleMsg.CONSOLE_FRAMEWORK_IS_SHUTDOWN_MESSAGE);
- }
-
- Object[] options = processOption(intp);
- if (options == null)
- return;
-
- AbstractBundle[] bundles = (AbstractBundle[]) context.getBundles();
- if (bundles.length == 0) {
- intp.println(ConsoleMsg.CONSOLE_NO_INSTALLED_BUNDLES_ERROR);
- } else {
- intp.print(newline);
- intp.print(ConsoleMsg.CONSOLE_ID);
- intp.print(tab);
- intp.println(ConsoleMsg.CONSOLE_STATE_BUNDLE_TITLE);
- for (int i = 0; i < bundles.length; i++) {
- AbstractBundle b = bundles[i];
- if (!match(b, (String) options[0], ((Integer) options[1]).intValue()))
- continue;
- String label = b.getSymbolicName();
- if (label == null || label.length() == 0)
- label = b.toString();
- else
- label = label + "_" + b.getVersion(); //$NON-NLS-1$
- intp.println(b.getBundleId() + "\t" + getStateName(b) + label); //$NON-NLS-1$
- if (b.isFragment()) {
- Bundle[] hosts = b.getHosts();
- if (hosts != null)
- for (int j = 0; j < hosts.length; j++)
- intp.println("\t Master=" + hosts[j].getBundleId()); //$NON-NLS-1$
- } else {
- Bundle[] fragments = b.getFragments();
- if (fragments != null) {
- intp.print("\t Fragments="); //$NON-NLS-1$
- for (int f = 0; f < fragments.length; f++) {
- AbstractBundle fragment = (AbstractBundle) fragments[f];
- intp.print((f > 0 ? ", " : "") + fragment.getBundleId()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- intp.println();
- }
- }
- }
- }
- }
-
- private boolean match(Bundle toFilter, String searchedName, int searchedState) {
- if ((toFilter.getState() & searchedState) == 0) {
- return false;
- }
- if (searchedName != null && toFilter.getSymbolicName() != null && toFilter.getSymbolicName().indexOf(searchedName) == -1) {
- return false;
- }
- return true;
- }
-
- /**
- * Handles the threads command abbreviation. Invokes _threads().
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _t(CommandInterpreter intp) throws Exception {
- _threads(intp);
- }
-
- /**
- * Prints the information about the currently running threads
- * in the embedded system.
- *
- * @param intp A CommandInterpreter object containing the command
- * and it's arguments.
- */
- public void _threads(CommandInterpreter intp) throws Exception {
-
- ThreadGroup[] threadGroups = getThreadGroups();
- Util.sortByString(threadGroups);
-
- ThreadGroup tg = getTopThreadGroup();
- Thread[] threads = new Thread[tg.activeCount()];
- int count = tg.enumerate(threads, true);
- Util.sortByString(threads);
-
- StringBuffer sb = new StringBuffer(120);
- intp.println();
- intp.println(ConsoleMsg.CONSOLE_THREADGROUP_TITLE);
- for (int i = 0; i < threadGroups.length; i++) {
- tg = threadGroups[i];
- int all = tg.activeCount(); //tg.allThreadsCount();
- int local = tg.enumerate(new Thread[all], false); //tg.threadsCount();
- ThreadGroup p = tg.getParent();
- String parent = (p == null) ? "-none-" : p.getName(); //$NON-NLS-1$
- sb.setLength(0);
- sb.append(Util.toString(simpleClassName(tg), 18)).append(" ").append(Util.toString(tg.getName(), 21)).append(" ").append(Util.toString(parent, 16)).append(Util.toString(new Integer(tg.getMaxPriority()), 3)).append(Util.toString(new Integer(local), 4)).append("/").append(Util.toString(String.valueOf(all), 6)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- intp.println(sb.toString());
- }
- intp.print(newline);
- intp.println(ConsoleMsg.CONSOLE_THREADTYPE_TITLE);
- for (int j = 0; j < count; j++) {
- Thread t = threads[j];
- if (t != null) {
- sb.setLength(0);
- sb.append(Util.toString(simpleClassName(t), 18)).append(" ").append(Util.toString(t.getName(), 21)).append(" ").append(Util.toString(t.getThreadGroup().getName(), 16)).append(Util.toString(new Integer(t.getPriority()), 3)); //$NON-NLS-1$ //$NON-NLS-2$
- if (t.isDaemon())
- sb.append(" [daemon]"); //$NON-NLS-1$
- intp.println(sb.toString());
- }
- }
- }
-
- /**
- * Handles the sl (startlevel) command.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _sl(CommandInterpreter intp) throws Exception {
- if (isStartLevelSvcPresent(intp)) {
- org.osgi.framework.Bundle bundle = null;
- String token = intp.nextArgument();
- int value = 0;
- if (token != null) {
- bundle = getBundleFromToken(intp, token, true);
- if (bundle == null) {
- return;
- }
- }
- if (bundle == null) { // must want framework startlevel
- value = slImpl.getStartLevel();
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_FRAMEWORK_ACTIVE_STARTLEVEL, String.valueOf(value)));
- } else { // must want bundle startlevel
- value = slImpl.getBundleStartLevel(bundle);
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_BUNDLE_STARTLEVEL, new Long(bundle.getBundleId()), new Integer(value)));
- }
- }
- }
-
- /**
- * Handles the setfwsl (set framework startlevel) command.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _setfwsl(CommandInterpreter intp) throws Exception {
- if (isStartLevelSvcPresent(intp)) {
- int value = 0;
- String token = intp.nextArgument();
- if (token == null) {
- intp.println(ConsoleMsg.STARTLEVEL_NO_STARTLEVEL_GIVEN);
- value = slImpl.getStartLevel();
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_FRAMEWORK_ACTIVE_STARTLEVEL, String.valueOf(value)));
- } else {
- value = this.getStartLevelFromToken(intp, token);
- if (value > 0) {
- try {
- slImpl.setStartLevel(value);
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_FRAMEWORK_ACTIVE_STARTLEVEL, String.valueOf(value)));
- } catch (IllegalArgumentException e) {
- intp.println(e.getMessage());
- }
- }
- }
- }
- }
-
- /**
- * Handles the setbsl (set bundle startlevel) command.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _setbsl(CommandInterpreter intp) throws Exception {
- if (isStartLevelSvcPresent(intp)) {
- String token;
- AbstractBundle bundle = null;
- token = intp.nextArgument();
- if (token == null) {
- intp.println(ConsoleMsg.STARTLEVEL_NO_STARTLEVEL_OR_BUNDLE_GIVEN);
- return;
- }
-
- int newSL = this.getStartLevelFromToken(intp, token);
-
- token = intp.nextArgument();
- if (token == null) {
- intp.println(ConsoleMsg.STARTLEVEL_NO_STARTLEVEL_OR_BUNDLE_GIVEN);
- return;
- }
- while (token != null) {
- bundle = getBundleFromToken(intp, token, true);
- if (bundle != null) {
- try {
- slImpl.setBundleStartLevel(bundle, newSL);
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_BUNDLE_STARTLEVEL, new Long(bundle.getBundleId()), new Integer(newSL)));
- } catch (IllegalArgumentException e) {
- intp.println(e.getMessage());
- }
- }
- token = intp.nextArgument();
- }
- }
- }
-
- /**
- * Handles the setibsl (set initial bundle startlevel) command.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _setibsl(CommandInterpreter intp) throws Exception {
- if (isStartLevelSvcPresent(intp)) {
- int value = 0;
- String token = intp.nextArgument();
- if (token == null) {
- intp.println(ConsoleMsg.STARTLEVEL_NO_STARTLEVEL_GIVEN);
- value = slImpl.getInitialBundleStartLevel();
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_INITIAL_BUNDLE_STARTLEVEL, String.valueOf(value)));
- } else {
- value = this.getStartLevelFromToken(intp, token);
- if (value > 0) {
- try {
- slImpl.setInitialBundleStartLevel(value);
- intp.println(NLS.bind(ConsoleMsg.STARTLEVEL_INITIAL_BUNDLE_STARTLEVEL, String.valueOf(value)));
- } catch (IllegalArgumentException e) {
- intp.println(e.getMessage());
- }
- }
- }
- }
- }
-
- public void _requiredBundles(CommandInterpreter intp) {
- _classSpaces(intp);
- }
-
- public void _classSpaces(CommandInterpreter intp) {
-
- String token = intp.nextArgument();
-
- ServiceReference<?> packageAdminRef = context.getServiceReference("org.osgi.service.packageadmin.PackageAdmin"); //$NON-NLS-1$
- if (packageAdminRef != null) {
- PackageAdmin packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
- if (packageAdmin != null) {
- try {
- org.osgi.service.packageadmin.RequiredBundle[] symBundles = null;
-
- symBundles = packageAdmin.getRequiredBundles(token);
-
- if (symBundles == null) {
- intp.println(ConsoleMsg.CONSOLE_NO_NAMED_CLASS_SPACES_MESSAGE);
- } else {
- for (int i = 0; i < symBundles.length; i++) {
- org.osgi.service.packageadmin.RequiredBundle symBundle = symBundles[i];
- intp.print(symBundle);
-
- boolean removalPending = symBundle.isRemovalPending();
- if (removalPending) {
- intp.print("("); //$NON-NLS-1$
- intp.print(ConsoleMsg.CONSOLE_REMOVAL_PENDING_MESSAGE);
- intp.println(")"); //$NON-NLS-1$
- }
-
- org.osgi.framework.Bundle provider = symBundle.getBundle();
- if (provider != null) {
- intp.print("<"); //$NON-NLS-1$
- intp.print(provider);
- intp.println(">"); //$NON-NLS-1$
-
- org.osgi.framework.Bundle[] requiring = symBundle.getRequiringBundles();
- if (requiring != null)
- for (int j = 0; j < requiring.length; j++) {
- intp.print(" "); //$NON-NLS-1$
- intp.print(requiring[j]);
- intp.print(" "); //$NON-NLS-1$
- intp.println(ConsoleMsg.CONSOLE_REQUIRES_MESSAGE);
- }
- } else {
- intp.print("<"); //$NON-NLS-1$
- intp.print(ConsoleMsg.CONSOLE_STALE_MESSAGE);
- intp.println(">"); //$NON-NLS-1$
- }
-
- }
- }
- } finally {
- context.ungetService(packageAdminRef);
- }
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_NO_EXPORTED_PACKAGES_NO_PACKAGE_ADMIN_MESSAGE);
- }
- }
-
- /**
- * Handles the profilelog command.
- *
- * @param intp A CommandInterpreter object containing the command and it's arguments.
- */
- public void _profilelog(CommandInterpreter intp) throws Exception {
- intp.println(Profile.getProfileLog());
- }
-
- public void _getPackages(CommandInterpreter intp) {
-
- String nextArg = intp.nextArgument();
- if (nextArg == null)
- return;
- AbstractBundle bundle = getBundleFromToken(intp, nextArg, true);
- ServiceReference<?> ref = context.getServiceReference("org.eclipse.osgi.service.resolver.PlatformAdmin"); //$NON-NLS-1$
- if (ref == null)
- return;
- PlatformAdmin platformAdmin = (PlatformAdmin) context.getService(ref);
- try {
- ExportPackageDescription[] exports = platformAdmin.getStateHelper().getVisiblePackages(bundle.getBundleDescription(), StateHelper.VISIBLE_INCLUDE_EE_PACKAGES | StateHelper.VISIBLE_INCLUDE_ALL_HOST_WIRES);
- for (int i = 0; i < exports.length; i++) {
- intp.println(exports[i] + ": " + platformAdmin.getStateHelper().getAccessCode(bundle.getBundleDescription(), exports[i])); //$NON-NLS-1$
- }
- } finally {
- context.ungetService(ref);
- }
- }
-
- /**
- * Handles the help command
- *
- * @param intp
- * @return description for a particular command or false if there is no command with the specified name
- */
- public Object _help(CommandInterpreter intp) {
- String commandName = intp.nextArgument();
- if (commandName == null) {
- return false;
- }
- String help = getHelp(commandName);
- return help.length() > 0 ? help : false;
- }
-
- /**
- * Checks for the presence of the StartLevel Service. Outputs a message if it is not present.
- * @param intp The CommandInterpreter object to be used to write to the console
- * @return true or false if service is present or not
- */
- protected boolean isStartLevelSvcPresent(CommandInterpreter intp) {
- boolean retval = false;
- ServiceReference<?> slSvcRef = context.getServiceReference("org.osgi.service.startlevel.StartLevel"); //$NON-NLS-1$
- if (slSvcRef != null) {
- StartLevel slSvc = (StartLevel) context.getService(slSvcRef);
- if (slSvc != null) {
- retval = true;
- }
- } else {
- intp.println(ConsoleMsg.CONSOLE_CAN_NOT_USE_STARTLEVEL_NO_STARTLEVEL_SVC_ERROR);
- }
- return retval;
- }
-
- /**
- * Given a number or a token representing a bundle symbolic name or bundle location,
- * retrieve the Bundle object with that id. The bundle symbolic name token is parsed as
- * symbolicname[@version]
- *
- * @param intp The CommandInterpreter
- * @param token A string containing a potential bundle it
- * @param error A boolean indicating whether or not to output a message
- * @return The requested Bundle object
- */
- protected AbstractBundle getBundleFromToken(CommandInterpreter intp, String token, boolean error) {
- AbstractBundle bundle = null;
- try {
- long id = Long.parseLong(token);
- bundle = (AbstractBundle) context.getBundle(id);
- } catch (NumberFormatException nfe) {
-
- // if not found, assume token is either symbolic name@version, or location
- String symbolicName = token;
- Version version = null;
-
- // check for @ -- this may separate either the version string, or be part of the
- // location
- int ix = token.indexOf("@"); //$NON-NLS-1$
- if (ix != -1) {
- if ((ix + 1) != token.length()) {
- try {
- // if the version parses, then use the token prior to @ as a symbolic name
- version = Version.parseVersion(token.substring(ix + 1, token.length()));
- symbolicName = token.substring(0, ix);
- } catch (IllegalArgumentException e) {
- // version doesn't parse, assume token is symbolic name without version, or location
- }
- }
- }
-
- Bundle[] bundles = context.getBundles();
- for (int i = 0, n = bundles.length; i < n; i++) {
- AbstractBundle b = (AbstractBundle) bundles[i];
- // if symbolicName matches, then matches if there is no version specific on command, or the version matches
- // if there is no version specified on command, pick first matching bundle
- if ((symbolicName.equals(b.getSymbolicName()) && (version == null || version.equals(b.getVersion()))) || token.equals(b.getLocation())) {
- bundle = b;
- break;
- }
- }
- }
-
- if ((bundle == null) && error) {
- intp.println(NLS.bind(ConsoleMsg.CONSOLE_CANNOT_FIND_BUNDLE_ERROR, token));
- }
-
- return (bundle);
- }
-
- /**
- * Given a string containing a startlevel value, validate it and convert it to an int
- *
- * @param intp A CommandInterpreter object used for printing out error messages
- * @param value A string containing a potential startlevel
- * @return The start level or an int <0 if it was invalid
- */
- protected int getStartLevelFromToken(CommandInterpreter intp, String value) {
- int retval = -1;
- try {
- retval = Integer.parseInt(value);
- if (Integer.parseInt(value) <= 0) {
- intp.println(ConsoleMsg.STARTLEVEL_POSITIVE_INTEGER);
- }
- } catch (NumberFormatException nfe) {
- intp.println(ConsoleMsg.STARTLEVEL_POSITIVE_INTEGER);
- }
- return retval;
- }
-
- /**
- * Given a bundle, return the string describing that bundle's state.
- *
- * @param bundle A bundle to return the state of
- * @return A String describing the state
- */
- protected String getStateName(Bundle bundle) {
- int state = bundle.getState();
- switch (state) {
- case Bundle.UNINSTALLED :
- return "UNINSTALLED "; //$NON-NLS-1$
-
- case Bundle.INSTALLED :
- if (isDisabled(bundle)) {
- return "<DISABLED> "; //$NON-NLS-1$
- }
- return "INSTALLED "; //$NON-NLS-1$
-
- case Bundle.RESOLVED :
- return "RESOLVED "; //$NON-NLS-1$
-
- case Bundle.STARTING :
- synchronized (lazyActivation) {
- if (lazyActivation.contains(bundle)) {
- return "<<LAZY>> "; //$NON-NLS-1$
- }
- return "STARTING "; //$NON-NLS-1$
- }
-
- case Bundle.STOPPING :
- return "STOPPING "; //$NON-NLS-1$
-
- case Bundle.ACTIVE :
- return "ACTIVE "; //$NON-NLS-1$
-
- default :
- return Integer.toHexString(state);
- }
- }
-
- private boolean isDisabled(Bundle bundle) {
- boolean disabled = false;
- ServiceReference<?> platformAdminRef = null;
- try {
- platformAdminRef = context.getServiceReference(PlatformAdmin.class.getName());
- if (platformAdminRef != null) {
- PlatformAdmin platAdmin = (PlatformAdmin) context.getService(platformAdminRef);
- if (platAdmin != null) {
- State state = platAdmin.getState(false);
- BundleDescription bundleDesc = state.getBundle(bundle.getBundleId());
- DisabledInfo[] disabledInfos = state.getDisabledInfos(bundleDesc);
- if ((disabledInfos != null) && (disabledInfos.length != 0)) {
- disabled = true;
- }
- }
- }
- } finally {
- if (platformAdminRef != null)
- context.ungetService(platformAdminRef);
- }
- return disabled;
- }
-
- /**
- * Answers all thread groups in the system.
- *
- * @return An array of all thread groups.
- */
- protected ThreadGroup[] getThreadGroups() {
- ThreadGroup tg = getTopThreadGroup();
- ThreadGroup[] groups = new ThreadGroup[tg.activeGroupCount()];
- int count = tg.enumerate(groups, true);
- if (count == groups.length) {
- return groups;
- }
- // get rid of null entries
- ThreadGroup[] ngroups = new ThreadGroup[count];
- System.arraycopy(groups, 0, ngroups, 0, count);
- return ngroups;
- }
-
- /**
- * Answers the top level group of the current thread.
- * <p>
- * It is the 'system' or 'main' thread group under
- * which all 'user' thread groups are allocated.
- *
- * @return The parent of all user thread groups.
- */
- protected ThreadGroup getTopThreadGroup() {
- ThreadGroup topGroup = Thread.currentThread().getThreadGroup();
- if (topGroup != null) {
- while (topGroup.getParent() != null) {
- topGroup = topGroup.getParent();
- }
- }
- return topGroup;
- }
-
- /**
- * Returns the simple class name of an object.
- *
- * @param o The object for which a class name is requested
- * @return The simple class name.
- */
- public String simpleClassName(Object o) {
- java.util.StringTokenizer t = new java.util.StringTokenizer(o.getClass().getName(), "."); //$NON-NLS-1$
- int ct = t.countTokens();
- for (int i = 1; i < ct; i++) {
- t.nextToken();
- }
- return t.nextToken();
- }
-
- public void _getprop(CommandInterpreter ci) throws Exception {
- Properties allProperties = FrameworkProperties.getProperties();
- String filter = ci.nextArgument();
- Iterator<?> propertyNames = new TreeSet<Object>(allProperties.keySet()).iterator();
- while (propertyNames.hasNext()) {
- String prop = (String) propertyNames.next();
- if (filter == null || prop.startsWith(filter)) {
- ci.println(prop + '=' + allProperties.getProperty(prop));
- }
- }
- }
-
- /**
- * This is used to track lazily activated bundles.
- */
- public void bundleChanged(BundleEvent event) {
- int type = event.getType();
- Bundle bundle = event.getBundle();
- synchronized (lazyActivation) {
- switch (type) {
- case BundleEvent.LAZY_ACTIVATION :
- if (!lazyActivation.contains(bundle)) {
- lazyActivation.add(bundle);
- }
- break;
-
- default :
- lazyActivation.remove(bundle);
- break;
- }
- }
-
- }
-}
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsole.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsole.java
deleted file mode 100644
index 8ecbcf968..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsole.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import org.eclipse.osgi.framework.console.*;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * This class starts OSGi with a console for development use.
- *
- * FrameworkConsole provides a printStackTrace method to print Exceptions and their
- * nested Exceptions.
- */
-public class FrameworkConsole implements Runnable {
- /** The stream to receive commands on */
- private final BufferedReader in;
- /** The stream to write command results to */
- private final PrintWriter out;
- /** The current bundle context */
- private final BundleContext context;
- /** A tracker containing the service object of all registered command providers */
- private final ServiceTracker<CommandProvider, CommandProvider> cptracker;
- private final ConsoleSession consoleSession;
- private final boolean isSystemInOut;
- /** Default code page which must be supported by all JVMs */
- static final String defaultEncoding = "iso8859-1"; //$NON-NLS-1$
- /** The current setting for code page */
- static final String encoding = FrameworkProperties.getProperty("osgi.console.encoding", FrameworkProperties.getProperty("file.encoding", defaultEncoding)); //$NON-NLS-1$ //$NON-NLS-2$
- private static final boolean blockOnready = FrameworkProperties.getProperty("osgi.dev") != null || FrameworkProperties.getProperty("osgi.console.blockOnReady") != null; //$NON-NLS-1$ //$NON-NLS-2$
- volatile boolean shutdown = false;
-
- public FrameworkConsole(BundleContext context, ConsoleSession consoleSession, boolean isSystemInOut, ServiceTracker<CommandProvider, CommandProvider> cptracker) {
- this.context = context;
- this.cptracker = cptracker;
- this.isSystemInOut = isSystemInOut;
- this.consoleSession = consoleSession;
- in = createBufferedReader(consoleSession.getInput());
- out = createPrintWriter(consoleSession.getOutput());
- }
-
- /**
- * Return a BufferedReader from an InputStream. Handle encoding.
- *
- * @param _in An InputStream to wrap with a BufferedReader
- * @return a BufferedReader
- */
- static BufferedReader createBufferedReader(InputStream _in) {
- BufferedReader reader;
- try {
- reader = new BufferedReader(new InputStreamReader(_in, encoding));
- } catch (UnsupportedEncodingException uee) {
- // if the encoding is not supported by the jvm, punt and use whatever encodiing there is
- reader = new BufferedReader(new InputStreamReader(_in));
- }
- return reader;
- }
-
- /**
- * Return a PrintWriter from an OutputStream. Handle encoding.
- *
- * @param _out An OutputStream to wrap with a PrintWriter
- * @return a PrintWriter
- */
- static PrintWriter createPrintWriter(OutputStream _out) {
- PrintWriter writer;
- try {
- writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(_out, encoding)), true);
- } catch (UnsupportedEncodingException uee) {
- // if the encoding is not supported by the jvm, punt and use whatever encoding there is
- writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(_out)), true);
- }
- return writer;
- }
-
- /**
- * Return the current output PrintWriter
- * @return The currently active PrintWriter
- */
- public PrintWriter getWriter() {
- return out;
- }
-
- /**
- * Command Line Interface for OSGi. The method processes the initial commands
- * and then reads and processes commands from the console InputStream.
- * Command output is written to the console PrintStream. The method will
- * loop reading commands from the console InputStream until end-of-file
- * is reached. This method will then return.
- */
- public void run() {
- try {
- runConsole();
- } finally {
- // ensure the console is shutdown before exiting the thread
- shutdown();
- }
- }
-
- private void runConsole() {
- // wait to receive commands from console and handle them
- //cache the console prompt String
- String consolePrompt = "\r\n" + ConsoleMsg.CONSOLE_PROMPT; //$NON-NLS-1$
- while (!shutdown) {
- out.print(consolePrompt);
- out.flush();
-
- String cmdline = null;
- try {
- if (blockOnready && isSystemInOut) {
- // bug 40066: avoid waiting on input stream - apparently generates contention with other native calls
- try {
- while (!in.ready())
- Thread.sleep(300);
- cmdline = in.readLine();
- } catch (InterruptedException e) {
- // do nothing; probably got disconnected
- }
- } else
- cmdline = in.readLine();
- } catch (IOException ioe) {
- if (!shutdown)
- ioe.printStackTrace(out);
- }
- if (cmdline == null)
- // we assume the session is done and break out of the loop.
- break;
- if (!shutdown)
- docommand(cmdline);
- }
- }
-
- /**
- * Process the args on the command line.
- * This method invokes a CommandInterpreter to do the actual work.
- *
- * @param cmdline a string containing the command line arguments
- */
- protected void docommand(String cmdline) {
- if (cmdline != null && cmdline.length() > 0) {
- CommandInterpreter intcp = new FrameworkCommandInterpreter(cmdline, getServices(), this);
- String command = intcp.nextArgument();
- if (command != null) {
- intcp.execute(command);
- }
- }
- }
-
- /**
- * Reads a string from standard input until user hits the Enter key.
- *
- * @return The string read from the standard input without the newline character.
- */
- public String getInput() {
- String input;
- try {
- /** The buffered input reader on standard in. */
- input = in.readLine();
- System.out.println("<" + input + ">"); //$NON-NLS-1$//$NON-NLS-2$
- } catch (IOException e) {
- input = ""; //$NON-NLS-1$
- }
- return input;
- }
-
- /**
- * Return an array of service objects for all services
- * being tracked by this <tt>ServiceTracker</tt> object.
- *
- * The array is sorted primarily by descending Service Ranking and
- * secondarily by ascending Service ID.
- *
- * @return Array of service objects; if no service
- * are being tracked then an empty array is returned
- */
- public CommandProvider[] getServices() {
- ServiceReference<CommandProvider>[] serviceRefs = cptracker.getServiceReferences();
- if (serviceRefs == null)
- return new CommandProvider[0];
- Util.dsort(serviceRefs, 0, serviceRefs.length);
-
- CommandProvider[] serviceObjects = new CommandProvider[serviceRefs.length];
- for (int i = 0; i < serviceRefs.length; i++)
- serviceObjects[i] = FrameworkConsole.this.context.getService(serviceRefs[i]);
- return serviceObjects;
- }
-
- /**
- * Stops the console so the thread can be GC'ed
- */
- public synchronized void shutdown() {
- if (shutdown)
- return;
- shutdown = true;
- consoleSession.close();
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsoleSession.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsoleSession.java
deleted file mode 100644
index 91b7c24d8..000000000
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkConsoleSession.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.net.Socket;
-import org.eclipse.osgi.framework.console.ConsoleSession;
-
-public class FrameworkConsoleSession extends ConsoleSession {
- private final Socket s;
- private final InputStream in;
- private final OutputStream out;
-
- public FrameworkConsoleSession(InputStream in, OutputStream out, Socket s) {
- this.in = in;
- this.out = out;
- this.s = s;
- }
-
- public synchronized InputStream getInput() {
- return in;
- }
-
- public synchronized OutputStream getOutput() {
- return out;
- }
-
- public void doClose() {
- if (s != null)
- try {
- s.close();
- } catch (IOException ioe) {
- // do nothing
- }
- if (out != null)
- try {
- out.close();
- } catch (IOException e) {
- // do nothing
- }
- if (in != null)
- try {
- in.close();
- } catch (IOException ioe) {
- // do nothing
- }
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java
new file mode 100644
index 000000000..3bffc1995
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java
@@ -0,0 +1,1051 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.resource.Wiring;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.resolver.ResolutionException;
+import org.osgi.service.resolver.ResolveContext;
+
+class Candidates
+{
+ public static final int MANDATORY = 0;
+ public static final int OPTIONAL = 1;
+ public static final int ON_DEMAND = 2;
+
+ private final Set<Resource> m_mandatoryResources;
+ // Maps a capability to requirements that match it.
+ private final Map<Capability, Set<Requirement>> m_dependentMap;
+ // Maps a requirement to the capability it matches.
+ private final Map<Requirement, List<Capability>> m_candidateMap;
+ // Maps a bundle revision to its associated wrapped revision; this only happens
+ // when a revision being resolved has fragments to attach to it.
+ private final Map<Resource, WrappedResource> m_allWrappedHosts;
+ // Map used when populating candidates to hold intermediate and final results.
+ private final Map<Resource, Object> m_populateResultCache;
+
+ // Flag to signal if fragments are present in the candidate map.
+ private boolean m_fragmentsPresent = false;
+
+ /**
+ * Private copy constructor used by the copy() method.
+ * @param dependentMap the capability dependency map.
+ * @param candidateMap the requirement candidate map.
+ * @param hostFragments the fragment map.
+ * @param wrappedHosts the wrapped hosts map.
+ **/
+ private Candidates(
+ Set<Resource> mandatoryResources,
+ Map<Capability, Set<Requirement>> dependentMap,
+ Map<Requirement, List<Capability>> candidateMap,
+ Map<Resource, WrappedResource> wrappedHosts, Map<Resource, Object> populateResultCache,
+ boolean fragmentsPresent)
+ {
+ m_mandatoryResources = mandatoryResources;
+ m_dependentMap = dependentMap;
+ m_candidateMap = candidateMap;
+ m_allWrappedHosts = wrappedHosts;
+ m_populateResultCache = populateResultCache;
+ m_fragmentsPresent = fragmentsPresent;
+ }
+
+ /**
+ * Constructs an empty Candidates object.
+ **/
+ public Candidates()
+ {
+ m_mandatoryResources = new HashSet<Resource>();
+ m_dependentMap = new HashMap<Capability, Set<Requirement>>();
+ m_candidateMap = new HashMap<Requirement, List<Capability>>();
+ m_allWrappedHosts = new HashMap<Resource, WrappedResource>();
+ m_populateResultCache = new HashMap<Resource, Object>();
+ }
+
+ /**
+ * Populates candidates for the specified revision. How a revision is
+ * resolved depends on its resolution type as follows:
+ * <ul>
+ * <li><tt>MANDATORY</tt> - must resolve and failure to do so throws
+ * an exception.</li>
+ * <li><tt>OPTIONAL</tt> - attempt to resolve, but no exception is thrown
+ * if the resolve fails.</li>
+ * <li><tt>ON_DEMAND</tt> - only resolve on demand; this only applies to
+ * fragments and will only resolve a fragment if its host is already
+ * selected as a candidate.</li>
+ * </ul>
+ * @param rc the resolve context used for populating the candidates.
+ * @param resource the resource whose candidates should be populated.
+ * @param resolution indicates the resolution type.
+ */
+ public final void populate(
+ ResolveContext rc, Resource resource, int resolution) throws ResolutionException
+ {
+ // Get the current result cache value, to make sure the revision
+ // hasn't already been populated.
+ Object cacheValue = m_populateResultCache.get(resource);
+ // Has been unsuccessfully populated.
+ if (cacheValue instanceof ResolutionException)
+ {
+ return;
+ }
+ // Has been successfully populated.
+ else if (cacheValue instanceof Boolean)
+ {
+ return;
+ }
+
+ // We will always attempt to populate fragments, since this is necessary
+ // for ondemand attaching of fragment. However, we'll only attempt to
+ // populate optional non-fragment revisions if they aren't already
+ // resolved.
+ boolean isFragment = Util.isFragment(resource);
+ if (!isFragment && rc.getWirings().containsKey(resource))
+ {
+ return;
+ }
+
+ // Always attempt to populate mandatory or optional revisions.
+ // However, for on-demand fragments only populate if their host
+ // is already populated.
+ if ((resolution != ON_DEMAND)
+ || (isFragment && populateFragmentOndemand(rc, resource)))
+ {
+ if (resolution == MANDATORY)
+ {
+ m_mandatoryResources.add(resource);
+ }
+ try
+ {
+ // Try to populate candidates for the optional revision.
+ populateResource(rc, resource);
+ }
+ catch (ResolutionException ex)
+ {
+ // Only throw an exception if resolution is mandatory.
+ if (resolution == MANDATORY)
+ {
+ throw ex;
+ }
+ }
+ }
+ }
+
+ /**
+ * Populates candidates for the specified revision.
+ * @param state the resolver state used for populating the candidates.
+ * @param revision the revision whose candidates should be populated.
+ */
+// TODO: FELIX3 - Modify to not be recursive.
+ private void populateResource(ResolveContext rc, Resource resource) throws ResolutionException
+ {
+ // Determine if we've already calculated this revision's candidates.
+ // The result cache will have one of three values:
+ // 1. A resolve exception if we've already attempted to populate the
+ // revision's candidates but were unsuccessful.
+ // 2. Boolean.TRUE indicating we've already attempted to populate the
+ // revision's candidates and were successful.
+ // 3. An array containing the cycle count, current map of candidates
+ // for already processed requirements, and a list of remaining
+ // requirements whose candidates still need to be calculated.
+ // For case 1, rethrow the exception. For case 2, simply return immediately.
+ // For case 3, this means we have a cycle so we should continue to populate
+ // the candidates where we left off and not record any results globally
+ // until we've popped completely out of the cycle.
+
+ // Keeps track of the number of times we've reentered this method
+ // for the current revision.
+ Integer cycleCount = null;
+
+ // Keeps track of the candidates we've already calculated for the
+ // current revision's requirements.
+ Map<Requirement, List<Capability>> localCandidateMap = null;
+
+ // Keeps track of the current revision's requirements for which we
+ // haven't yet found candidates.
+ List<Requirement> remainingReqs = null;
+
+ // Get the cache value for the current revision.
+ Object cacheValue = m_populateResultCache.get(resource);
+
+ // This is case 1.
+ if (cacheValue instanceof ResolutionException)
+ {
+ throw (ResolutionException) cacheValue;
+ }
+ // This is case 2.
+ else if (cacheValue instanceof Boolean)
+ {
+ return;
+ }
+ // This is case 3.
+ else if (cacheValue != null)
+ {
+ // Increment and get the cycle count.
+ cycleCount = (Integer)
+ (((Object[]) cacheValue)[0]
+ = new Integer(((Integer) ((Object[]) cacheValue)[0]).intValue() + 1));
+ // Get the already populated candidates.
+ localCandidateMap = (Map) ((Object[]) cacheValue)[1];
+ // Get the remaining requirements.
+ remainingReqs = (List) ((Object[]) cacheValue)[2];
+ }
+
+ // If there is no cache value for the current revision, then this is
+ // the first time we are attempting to populate its candidates, so
+ // do some one-time checks and initialization.
+ if ((remainingReqs == null) && (localCandidateMap == null))
+ {
+ // Record cycle count.
+ cycleCount = new Integer(0);
+
+ // Create a local map for populating candidates first, just in case
+ // the revision is not resolvable.
+ localCandidateMap = new HashMap();
+
+ // Create a modifiable list of the revision's requirements.
+ remainingReqs = new ArrayList(resource.getRequirements(null));
+
+ // Add these value to the result cache so we know we are
+ // in the middle of populating candidates for the current
+ // revision.
+ m_populateResultCache.put(resource,
+ cacheValue = new Object[] { cycleCount, localCandidateMap, remainingReqs });
+ }
+
+ // If we have requirements remaining, then find candidates for them.
+ while (!remainingReqs.isEmpty())
+ {
+ Requirement req = remainingReqs.remove(0);
+
+ // Ignore non-effective and dynamic requirements.
+ String resolution = req.getDirectives()
+ .get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ if (!rc.isEffective(req)
+ || ((resolution != null)
+ && resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC)))
+ {
+ continue;
+ }
+
+ // Process the candidates, removing any candidates that
+ // cannot resolve.
+ List<Capability> candidates = rc.findProviders(req);
+ ResolutionException rethrow = processCandidates(rc, resource, candidates);
+
+ // First, due to cycles, makes sure we haven't already failed in
+ // a deeper recursion.
+ Object result = m_populateResultCache.get(resource);
+ if (result instanceof ResolutionException)
+ {
+ throw (ResolutionException) result;
+ }
+ // Next, if are no candidates remaining and the requirement is not
+ // not optional, then record and throw a resolve exception.
+ else if (candidates.isEmpty() && !Util.isOptional(req))
+ {
+ String msg = "Unable to resolve " + resource
+ + ": missing requirement " + req;
+ if (rethrow != null)
+ {
+ msg = msg + " [caused by: " + rethrow.getMessage() + "]";
+ }
+ rethrow = new ResolutionException(msg, null, Collections.singleton(req));
+ m_populateResultCache.put(resource, rethrow);
+ throw rethrow;
+ }
+ // Otherwise, if we actually have candidates for the requirement, then
+ // add them to the local candidate map.
+ else if (candidates.size() > 0)
+ {
+ localCandidateMap.put(req, candidates);
+ }
+ }
+
+ // If we are exiting from a cycle then decrement
+ // cycle counter, otherwise record the result.
+ if (cycleCount.intValue() > 0)
+ {
+ ((Object[]) cacheValue)[0] = new Integer(cycleCount.intValue() - 1);
+ }
+ else if (cycleCount.intValue() == 0)
+ {
+ // Record that the revision was successfully populated.
+ m_populateResultCache.put(resource, Boolean.TRUE);
+
+ // Merge local candidate map into global candidate map.
+ if (localCandidateMap.size() > 0)
+ {
+ add(localCandidateMap);
+ }
+ }
+ }
+
+ private boolean populateFragmentOndemand(ResolveContext rc, Resource resource)
+ throws ResolutionException
+ {
+ // Create a modifiable list of the revision's requirements.
+ List<Requirement> remainingReqs =
+ new ArrayList(resource.getRequirements(null));
+ // Find the host requirement.
+ Requirement hostReq = null;
+ for (Iterator<Requirement> it = remainingReqs.iterator();
+ it.hasNext(); )
+ {
+ Requirement r = it.next();
+ if (r.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
+ {
+ hostReq = r;
+ it.remove();
+ break;
+ }
+ }
+ // Get candidates hosts and keep any that have been populated.
+ List<Capability> hosts = rc.findProviders(hostReq);
+ for (Iterator<Capability> it = hosts.iterator(); it.hasNext(); )
+ {
+ Capability host = it.next();
+ if (!isPopulated(host.getResource()))
+ {
+ it.remove();
+ }
+ }
+ // If there aren't any populated hosts, then we can just
+ // return since this fragment isn't needed.
+ if (hosts.isEmpty())
+ {
+ return false;
+ }
+
+ // If there are populated host candidates, then prepopulate
+ // the result cache with the work we've done so far.
+ // Record cycle count, but start at -1 since it will
+ // be incremented again in populate().
+ Integer cycleCount = new Integer(-1);
+ // Create a local map for populating candidates first, just in case
+ // the revision is not resolvable.
+ Map<Requirement, List<Capability>> localCandidateMap =
+ new HashMap<Requirement, List<Capability>>();
+ // Add the discovered host candidates to the local candidate map.
+ localCandidateMap.put(hostReq, hosts);
+ // Add these value to the result cache so we know we are
+ // in the middle of populating candidates for the current
+ // revision.
+ m_populateResultCache.put(resource,
+ new Object[] { cycleCount, localCandidateMap, remainingReqs });
+ return true;
+ }
+
+ public void populateDynamic(
+ ResolveContext rc, Resource resource,
+ Requirement req, List<Capability> candidates) throws ResolutionException
+ {
+ // Record the revision associated with the dynamic require
+ // as a mandatory revision.
+ m_mandatoryResources.add(resource);
+
+ // Add the dynamic imports candidates.
+ add(req, candidates);
+
+ // Process the candidates, removing any candidates that
+ // cannot resolve.
+ ResolutionException rethrow = processCandidates(rc, resource, candidates);
+
+ if (candidates.isEmpty())
+ {
+ if (rethrow == null)
+ {
+ rethrow = new ResolutionException(
+ "Dynamic import failed.", null, Collections.singleton(req));
+ }
+ throw rethrow;
+ }
+
+ m_populateResultCache.put(resource, Boolean.TRUE);
+ }
+
+ /**
+ * This method performs common processing on the given set of candidates.
+ * Specifically, it removes any candidates which cannot resolve and it
+ * synthesizes candidates for any candidates coming from any attached
+ * fragments, since fragment capabilities only appear once, but technically
+ * each host represents a unique capability.
+ * @param state the resolver state.
+ * @param revision the revision being resolved.
+ * @param candidates the candidates to process.
+ * @return a resolve exception to be re-thrown, if any, or null.
+ */
+ private ResolutionException processCandidates(
+ ResolveContext rc,
+ Resource resource,
+ List<Capability> candidates)
+ {
+ // Get satisfying candidates and populate their candidates if necessary.
+ ResolutionException rethrow = null;
+ Set<Capability> fragmentCands = null;
+ for (Iterator<Capability> itCandCap = candidates.iterator();
+ itCandCap.hasNext(); )
+ {
+ Capability candCap = itCandCap.next();
+
+ boolean isFragment = Util.isFragment(candCap.getResource());
+
+ // If the capability is from a fragment, then record it
+ // because we have to insert associated host capabilities
+ // if the fragment is already attached to any hosts.
+ if (isFragment)
+ {
+ if (fragmentCands == null)
+ {
+ fragmentCands = new HashSet<Capability>();
+ }
+ fragmentCands.add(candCap);
+ }
+
+ // If the candidate revision is a fragment, then always attempt
+ // to populate candidates for its dependency, since it must be
+ // attached to a host to be used. Otherwise, if the candidate
+ // revision is not already resolved and is not the current version
+ // we are trying to populate, then populate the candidates for
+ // its dependencies as well.
+ // NOTE: Technically, we don't have to check to see if the
+ // candidate revision is equal to the current revision, but this
+ // saves us from recursing and also simplifies exceptions messages
+ // since we effectively chain exception messages for each level
+ // of recursion; thus, any avoided recursion results in fewer
+ // exceptions to chain when an error does occur.
+ if ((isFragment || !rc.getWirings().containsKey(candCap.getResource()))
+ && !candCap.getResource().equals(resource))
+ {
+ try
+ {
+ populateResource(rc, candCap.getResource());
+ }
+ catch (ResolutionException ex)
+ {
+ if (rethrow == null)
+ {
+ rethrow = ex;
+ }
+ // Remove the candidate since we weren't able to
+ // populate its candidates.
+ itCandCap.remove();
+ }
+ }
+ }
+
+ // If any of the candidates for the requirement were from a fragment,
+ // then also insert synthesized hosted capabilities for any other host
+ // to which the fragment is attached since they are all effectively
+ // unique capabilities.
+ if (fragmentCands != null)
+ {
+ for (Capability fragCand : fragmentCands)
+ {
+ // Only necessary for resolved fragments.
+ Wiring wiring = rc.getWirings().get(fragCand.getResource());
+ if (wiring != null)
+ {
+ // Fragments only have host wire, so each wire represents
+ // an attached host.
+ for (Wire wire : wiring.getRequiredResourceWires(null))
+ {
+ // If the capability is a package, then make sure the
+ // host actually provides it in its resolved capabilities,
+ // since it may be a substitutable export.
+ if (!fragCand.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE)
+ || rc.getWirings().get(wire.getProvider())
+ .getResourceCapabilities(null).contains(fragCand))
+ {
+ // Note that we can just add this as a candidate
+ // directly, since we know it is already resolved.
+ // NOTE: We are synthesizing a hosted capability here,
+ // but we are not using a ShadowList like we do when
+ // we synthesizing capabilities for unresolved hosts.
+ // It is not necessary to use the ShadowList here since
+ // the host is resolved, because in that case we can
+ // calculate the proper package space by traversing
+ // the wiring. In the unresolved case, this isn't possible
+ // so we need to use the ShadowList so we can keep
+ // a reference to a synthesized resource with attached
+ // fragments so we can correctly calculate its package
+ // space.
+ rc.insertHostedCapability(
+ candidates,
+ new WrappedCapability(
+ wire.getCapability().getResource(),
+ fragCand));
+ }
+ }
+ }
+ }
+ }
+
+ return rethrow;
+ }
+
+ public boolean isPopulated(Resource resource)
+ {
+ Object value = m_populateResultCache.get(resource);
+ return ((value != null) && (value instanceof Boolean));
+ }
+
+ public ResolutionException getResolveException(Resource resource)
+ {
+ Object value = m_populateResultCache.get(resource);
+ return ((value != null) && (value instanceof ResolutionException))
+ ? (ResolutionException) value : null;
+ }
+
+ /**
+ * Adds a requirement and its matching candidates to the internal data
+ * structure. This method assumes it owns the data being passed in and
+ * does not make a copy. It takes the data and processes, such as calculating
+ * which requirements depend on which capabilities and recording any fragments
+ * it finds for future merging.
+ * @param req the requirement to add.
+ * @param candidates the candidates matching the requirement.
+ **/
+ private void add(Requirement req, List<Capability> candidates)
+ {
+ if (req.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
+ {
+ m_fragmentsPresent = true;
+ }
+
+ // Record the candidates.
+ m_candidateMap.put(req, candidates);
+ }
+
+ /**
+ * Adds requirements and candidates in bulk. The outer map is not retained
+ * by this method, but the inner data structures are, so they should not
+ * be further modified by the caller.
+ * @param candidates the bulk requirements and candidates to add.
+ **/
+ private void add(Map<Requirement, List<Capability>> candidates)
+ {
+ for (Entry<Requirement, List<Capability>> entry : candidates.entrySet())
+ {
+ add(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Returns the wrapped resource associated with the given resource. If the resource
+ * was not wrapped, then the resource itself is returned. This is really only
+ * needed to determine if the root resources of the resolve have been wrapped.
+ * @param r the resource whose wrapper is desired.
+ * @return the wrapper resource or the resource itself if it was not wrapped.
+ **/
+ public Resource getWrappedHost(Resource r)
+ {
+ Resource wrapped = m_allWrappedHosts.get(r);
+ return (wrapped == null) ? r : wrapped;
+ }
+
+ /**
+ * Gets the candidates associated with a given requirement.
+ * @param req the requirement whose candidates are desired.
+ * @return the matching candidates or null.
+ **/
+ public List<Capability> getCandidates(Requirement req)
+ {
+ return m_candidateMap.get(req);
+ }
+
+ /**
+ * Merges fragments into their hosts. It does this by wrapping all host
+ * modules and attaching their selected fragments, removing all unselected
+ * fragment modules, and replacing all occurrences of the original fragments
+ * in the internal data structures with the wrapped host modules instead.
+ * Thus, fragment capabilities and requirements are merged into the appropriate
+ * host and the candidates for the fragment now become candidates for the host.
+ * Likewise, any module depending on a fragment now depend on the host. Note
+ * that this process is sort of like multiplication, since one fragment that
+ * can attach to two hosts effectively gets multiplied across the two hosts.
+ * So, any modules being satisfied by the fragment will end up having the
+ * two hosts as potential candidates, rather than the single fragment.
+ * @throws ResolutionException if the removal of any unselected fragments result
+ * in the root module being unable to resolve.
+ **/
+ public void prepare(ResolveContext rc) throws ResolutionException
+ {
+ // Maps a host capability to a map containing its potential fragments;
+ // the fragment map maps a fragment symbolic name to a map that maps
+ // a version to a list of fragments requirements matching that symbolic
+ // name and version.
+ Map<Capability, Map<String, Map<Version, List<Requirement>>>>
+ hostFragments = Collections.EMPTY_MAP;
+ if (m_fragmentsPresent)
+ {
+ hostFragments = populateDependents();
+ }
+
+ // This method performs the following steps:
+ // 1. Select the fragments to attach to a given host.
+ // 2. Wrap hosts and attach fragments.
+ // 3. Remove any unselected fragments. This is necessary because
+ // other revisions may depend on the capabilities of unselected
+ // fragments, so we need to remove the unselected fragments and
+ // any revisions that depends on them, which could ultimately cause
+ // the entire resolve to fail.
+ // 4. Replace all fragments with any host it was merged into
+ // (effectively multiplying it).
+ // * This includes setting candidates for attached fragment
+ // requirements as well as replacing fragment capabilities
+ // with host's attached fragment capabilities.
+
+ // Steps 1 and 2
+ List<WrappedResource> hostResources = new ArrayList<WrappedResource>();
+ List<Resource> unselectedFragments = new ArrayList<Resource>();
+ for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>>
+ hostEntry : hostFragments.entrySet())
+ {
+ // Step 1
+ Capability hostCap = hostEntry.getKey();
+ Map<String, Map<Version, List<Requirement>>> fragments
+ = hostEntry.getValue();
+ List<Resource> selectedFragments = new ArrayList<Resource>();
+ for (Entry<String, Map<Version, List<Requirement>>> fragEntry
+ : fragments.entrySet())
+ {
+ boolean isFirst = true;
+ for (Entry<Version, List<Requirement>> versionEntry
+ : fragEntry.getValue().entrySet())
+ {
+ for (Requirement hostReq : versionEntry.getValue())
+ {
+ // Selecting the first fragment in each entry, which
+ // is equivalent to selecting the highest version of
+ // each fragment with a given symbolic name.
+ if (isFirst)
+ {
+ selectedFragments.add(hostReq.getResource());
+ isFirst = false;
+ }
+ // For any fragment that wasn't selected, remove the
+ // current host as a potential host for it and remove it
+ // as a dependent on the host. If there are no more
+ // potential hosts for the fragment, then mark it as
+ // unselected for later removal.
+ else
+ {
+ m_dependentMap.get(hostCap).remove(hostReq);
+ List<Capability> hosts = m_candidateMap.get(hostReq);
+ hosts.remove(hostCap);
+ if (hosts.isEmpty())
+ {
+ unselectedFragments.add(hostReq.getResource());
+ }
+ }
+ }
+ }
+ }
+
+ // Step 2
+ WrappedResource wrappedHost =
+ new WrappedResource(hostCap.getResource(), selectedFragments);
+ hostResources.add(wrappedHost);
+ m_allWrappedHosts.put(hostCap.getResource(), wrappedHost);
+ }
+
+ // Step 3
+ for (Resource fragment : unselectedFragments)
+ {
+ removeResource(fragment,
+ new ResolutionException(
+ "Fragment was not selected for attachment: " + fragment));
+ }
+
+ // Step 4
+ for (WrappedResource hostResource : hostResources)
+ {
+ // Replaces capabilities from fragments with the capabilities
+ // from the merged host.
+ for (Capability c : hostResource.getCapabilities(null))
+ {
+ // Don't replace the host capability, since the fragment will
+ // really be attached to the original host, not the wrapper.
+ if (!c.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
+ {
+ Capability origCap = ((HostedCapability) c).getDeclaredCapability();
+ // Note that you might think we could remove the original cap
+ // from the dependent map, but you can't since it may come from
+ // a fragment that is attached to multiple hosts, so each host
+ // will need to make their own copy.
+ Set<Requirement> dependents = m_dependentMap.get(origCap);
+ if (dependents != null)
+ {
+ dependents = new HashSet<Requirement>(dependents);
+ m_dependentMap.put(c, dependents);
+ for (Requirement r : dependents)
+ {
+ // We have synthesized hosted capabilities for all
+ // fragments that have been attached to hosts by
+ // wrapping the host bundle and their attached
+ // fragments. We need to use the ResolveContext to
+ // determine the proper priority order for hosted
+ // capabilities since the order may depend on the
+ // declaring host/fragment combination. However,
+ // internally we completely wrap the host revision
+ // and make all capabilities/requirements point back
+ // to the wrapped host not the declaring host. The
+ // ResolveContext expects HostedCapabilities to point
+ // to the declaring revision, so we need two separate
+ // candidate lists: one for the ResolveContext with
+ // HostedCapabilities pointing back to the declaring
+ // host and one for the resolver with HostedCapabilities
+ // pointing back to the wrapped host. We ask the
+ // ResolveContext to insert its appropriate HostedCapability
+ // into its list, then we mirror the insert into a
+ // shadow list with the resolver's HostedCapability.
+ // We only need to ask the ResolveContext to find
+ // the insert position for fragment caps since these
+ // were synthesized and we don't know their priority.
+ // However, in the resolver's candidate list we need
+ // to replace all caps with the wrapped caps, no
+ // matter if they come from the host or fragment,
+ // since we are completing replacing the declaring
+ // host and fragments with the wrapped host.
+ List<Capability> cands = m_candidateMap.get(r);
+ if (!(cands instanceof ShadowList))
+ {
+ ShadowList<Capability> shadow =
+ new ShadowList<Capability>(cands);
+ m_candidateMap.put(r, shadow);
+ cands = shadow;
+ }
+
+ // If the original capability is from a fragment, then
+ // ask the ResolveContext to insert it and update the
+ // shadow copy of the list accordingly.
+ if (!origCap.getResource().equals(hostResource.getDeclaredResource()))
+ {
+ List<Capability> original = ((ShadowList) cands).getOriginal();
+ int removeIdx = original.indexOf(origCap);
+ if (removeIdx != -1)
+ {
+ original.remove(removeIdx);
+ cands.remove(removeIdx);
+ }
+ int insertIdx = rc.insertHostedCapability(
+ original,
+ new SimpleHostedCapability(
+ hostResource.getDeclaredResource(),
+ origCap));
+ cands.add(insertIdx, c);
+ }
+ // If the original capability is from the host, then
+ // we just need to replace it in the shadow list.
+ else
+ {
+ int idx = cands.indexOf(origCap);
+ cands.set(idx, c);
+ }
+ }
+ }
+ }
+ }
+
+ // Copy candidates for fragment requirements to the host.
+ for (Requirement r : hostResource.getRequirements(null))
+ {
+ Requirement origReq = ((WrappedRequirement) r).getDeclaredRequirement();
+ List<Capability> cands = m_candidateMap.get(origReq);
+ if (cands != null)
+ {
+ m_candidateMap.put(r, new ArrayList<Capability>(cands));
+ for (Capability cand : cands)
+ {
+ Set<Requirement> dependents = m_dependentMap.get(cand);
+ dependents.remove(origReq);
+ dependents.add(r);
+ }
+ }
+ }
+ }
+
+ // Lastly, verify that all mandatory revisions are still
+ // populated, since some might have become unresolved after
+ // selecting fragments/singletons.
+ for (Resource resource : m_mandatoryResources)
+ {
+ if (!isPopulated(resource))
+ {
+ throw getResolveException(resource);
+ }
+ }
+ }
+
+ // Maps a host capability to a map containing its potential fragments;
+ // the fragment map maps a fragment symbolic name to a map that maps
+ // a version to a list of fragments requirements matching that symbolic
+ // name and version.
+ private Map<Capability,
+ Map<String, Map<Version, List<Requirement>>>> populateDependents()
+ {
+ Map<Capability, Map<String, Map<Version, List<Requirement>>>>
+ hostFragments = new HashMap<Capability,
+ Map<String, Map<Version, List<Requirement>>>>();
+ for (Entry<Requirement, List<Capability>> entry : m_candidateMap.entrySet())
+ {
+ Requirement req = entry.getKey();
+ List<Capability> caps = entry.getValue();
+ for (Capability cap : caps)
+ {
+ // Record the requirement as dependent on the capability.
+ Set<Requirement> dependents = m_dependentMap.get(cap);
+ if (dependents == null)
+ {
+ dependents = new HashSet<Requirement>();
+ m_dependentMap.put(cap, dependents);
+ }
+ dependents.add(req);
+
+ // Keep track of hosts and associated fragments.
+ if (req.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
+ {
+ String resSymName = Util.getSymbolicName(req.getResource());
+ Version resVersion = Util.getVersion(req.getResource());
+
+ Map<String, Map<Version, List<Requirement>>>
+ fragments = hostFragments.get(cap);
+ if (fragments == null)
+ {
+ fragments = new HashMap<String, Map<Version, List<Requirement>>>();
+ hostFragments.put(cap, fragments);
+ }
+ Map<Version, List<Requirement>> fragmentVersions = fragments.get(resSymName);
+ if (fragmentVersions == null)
+ {
+ fragmentVersions =
+ new TreeMap<Version, List<Requirement>>(Collections.reverseOrder());
+ fragments.put(resSymName, fragmentVersions);
+ }
+ List<Requirement> actual = fragmentVersions.get(resVersion);
+ if (actual == null)
+ {
+ actual = new ArrayList<Requirement>();
+ fragmentVersions.put(resVersion, actual);
+ }
+ actual.add(req);
+ }
+ }
+ }
+
+ return hostFragments;
+ }
+
+ /**
+ * Removes a module from the internal data structures if it wasn't selected
+ * as a fragment or a singleton. This process may cause other modules to
+ * become unresolved if they depended on the module's capabilities and there
+ * is no other candidate.
+ * @param revision the module to remove.
+ * @throws ResolveException if removing the module caused the resolve to fail.
+ **/
+ private void removeResource(Resource resource, ResolutionException ex)
+ throws ResolutionException
+ {
+ // Add removal reason to result cache.
+ m_populateResultCache.put(resource, ex);
+ // Remove from dependents.
+ Set<Resource> unresolvedResources = new HashSet<Resource>();
+ remove(resource, unresolvedResources);
+ // Remove dependents that failed as a result of removing revision.
+ while (!unresolvedResources.isEmpty())
+ {
+ Iterator<Resource> it = unresolvedResources.iterator();
+ resource = it.next();
+ it.remove();
+ remove(resource, unresolvedResources);
+ }
+ }
+
+ /**
+ * Removes the specified module from the internal data structures, which
+ * involves removing its requirements and its capabilities. This may cause
+ * other modules to become unresolved as a result.
+ * @param br the module to remove.
+ * @param unresolvedRevisions a list to containing any additional modules that
+ * that became unresolved as a result of removing this module and will
+ * also need to be removed.
+ * @throws ResolveException if removing the module caused the resolve to fail.
+ **/
+ private void remove(Resource resource, Set<Resource> unresolvedResources)
+ throws ResolutionException
+ {
+ for (Requirement r : resource.getRequirements(null))
+ {
+ remove(r);
+ }
+
+ for (Capability c : resource.getCapabilities(null))
+ {
+ remove(c, unresolvedResources);
+ }
+ }
+
+ /**
+ * Removes a requirement from the internal data structures.
+ * @param req the requirement to remove.
+ **/
+ private void remove(Requirement req)
+ {
+ boolean isFragment = req.getNamespace().equals(HostNamespace.HOST_NAMESPACE);
+
+ List<Capability> candidates = m_candidateMap.remove(req);
+ if (candidates != null)
+ {
+ for (Capability cap : candidates)
+ {
+ Set<Requirement> dependents = m_dependentMap.get(cap);
+ if (dependents != null)
+ {
+ dependents.remove(req);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes a capability from the internal data structures. This may cause
+ * other modules to become unresolved as a result.
+ * @param c the capability to remove.
+ * @param unresolvedRevisions a list to containing any additional modules that
+ * that became unresolved as a result of removing this module and will
+ * also need to be removed.
+ * @throws ResolveException if removing the module caused the resolve to fail.
+ **/
+ private void remove(Capability c, Set<Resource> unresolvedResources)
+ throws ResolutionException
+ {
+ Set<Requirement> dependents = m_dependentMap.remove(c);
+ if (dependents != null)
+ {
+ for (Requirement r : dependents)
+ {
+ List<Capability> candidates = m_candidateMap.get(r);
+ candidates.remove(c);
+ if (candidates.isEmpty())
+ {
+ m_candidateMap.remove(r);
+ if (!Util.isOptional(r))
+ {
+ String msg = "Unable to resolve " + r.getResource()
+ + ": missing requirement " + r;
+ m_populateResultCache.put(
+ r.getResource(),
+ new ResolutionException(msg, null, Collections.singleton(r)));
+ unresolvedResources.add(r.getResource());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates a copy of the Candidates object. This is used for creating
+ * permutations when package space conflicts are discovered.
+ * @return copy of this Candidates object.
+ **/
+ public Candidates copy()
+ {
+ Map<Capability, Set<Requirement>> dependentMap =
+ new HashMap<Capability, Set<Requirement>>();
+ for (Entry<Capability, Set<Requirement>> entry : m_dependentMap.entrySet())
+ {
+ Set<Requirement> dependents = new HashSet<Requirement>(entry.getValue());
+ dependentMap.put(entry.getKey(), dependents);
+ }
+
+ Map<Requirement, List<Capability>> candidateMap =
+ new HashMap<Requirement, List<Capability>>();
+ for (Entry<Requirement, List<Capability>> entry
+ : m_candidateMap.entrySet())
+ {
+ List<Capability> candidates =
+ new ArrayList<Capability>(entry.getValue());
+ candidateMap.put(entry.getKey(), candidates);
+ }
+
+ return new Candidates(
+ m_mandatoryResources, dependentMap, candidateMap,
+ m_allWrappedHosts, m_populateResultCache, m_fragmentsPresent);
+ }
+
+ public void dump(ResolveContext rc)
+ {
+ // Create set of all revisions from requirements.
+ Set<Resource> resources = new HashSet<Resource>();
+ for (Entry<Requirement, List<Capability>> entry
+ : m_candidateMap.entrySet())
+ {
+ resources.add(entry.getKey().getResource());
+ }
+ // Now dump the revisions.
+ System.out.println("=== BEGIN CANDIDATE MAP ===");
+ for (Resource resource : resources)
+ {
+ Wiring wiring = rc.getWirings().get(resource);
+ System.out.println(" " + resource
+ + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)"));
+ List<Requirement> reqs = (wiring != null)
+ ? wiring.getResourceRequirements(null)
+ : resource.getRequirements(null);
+ for (Requirement req : reqs)
+ {
+ List<Capability> candidates = m_candidateMap.get(req);
+ if ((candidates != null) && (candidates.size() > 0))
+ {
+ System.out.println(" " + req + ": " + candidates);
+ }
+ }
+ reqs = (wiring != null)
+ ? Util.getDynamicRequirements(wiring.getResourceRequirements(null))
+ : Util.getDynamicRequirements(resource.getRequirements(null));
+ for (Requirement req : reqs)
+ {
+ List<Capability> candidates = m_candidateMap.get(req);
+ if ((candidates != null) && (candidates.size() > 0))
+ {
+ System.out.println(" " + req + ": " + candidates);
+ }
+ }
+ }
+ System.out.println("=== END CANDIDATE MAP ===");
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java
new file mode 100644
index 000000000..9eaa21212
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+/**
+ * <p>
+ * This class mimics the standard OSGi <tt>LogService</tt> interface. An
+ * instance of this class is used by the framework for all logging. By default
+ * this class logs messages to standard out. The log level can be set to
+ * control the amount of logging performed, where a higher number results in
+ * more logging. A log level of zero turns off logging completely.
+ * </p>
+ * <p>
+ * The log levels match those specified in the OSGi Log Service (i.e., 1 = error,
+ * 2 = warning, 3 = information, and 4 = debug). The default value is 1.
+ * </p>
+ * <p>
+ * This class also uses the System Bundle's context to track log services
+ * and will use the highest ranking log service, if present, as a back end
+ * instead of printing to standard out. The class uses reflection to invoking
+ * the log service's method to avoid a dependency on the log interface.
+ * </p>
+**/
+public class Logger
+{
+ public static final int LOG_ERROR = 1;
+ public static final int LOG_WARNING = 2;
+ public static final int LOG_INFO = 3;
+ public static final int LOG_DEBUG = 4;
+
+ private int m_logLevel = 1;
+
+ private final static int LOGGER_OBJECT_IDX = 0;
+ private final static int LOGGER_METHOD_IDX = 1;
+ private Object[] m_logger = null;
+
+ public Logger(int i)
+ {
+ m_logLevel = i;
+ }
+
+ public final synchronized void setLogLevel(int i)
+ {
+ m_logLevel = i;
+ }
+
+ public final synchronized int getLogLevel()
+ {
+ return m_logLevel;
+ }
+
+ public final void log(int level, String msg)
+ {
+ _log(level, msg, null);
+ }
+
+ public final void log(int level, String msg, Throwable throwable)
+ {
+ _log(level, msg, throwable);
+ }
+
+ protected void doLog(int level, String msg, Throwable throwable)
+ {
+ String s = "";
+ s = s + msg;
+ if (throwable != null)
+ {
+ s = s + " (" + throwable + ")";
+ }
+ switch (level)
+ {
+ case LOG_DEBUG:
+ System.out.println("DEBUG: " + s);
+ break;
+ case LOG_ERROR:
+ System.out.println("ERROR: " + s);
+ if (throwable != null)
+ {
+ throwable.printStackTrace();
+ }
+ break;
+ case LOG_INFO:
+ System.out.println("INFO: " + s);
+ break;
+ case LOG_WARNING:
+ System.out.println("WARNING: " + s);
+ break;
+ default:
+ System.out.println("UNKNOWN[" + level + "]: " + s);
+ }
+ }
+
+ private void _log(
+ int level,
+ String msg, Throwable throwable)
+ {
+ // Save our own copy just in case it changes. We could try to do
+ // more conservative locking here, but let's be optimistic.
+ Object[] logger = m_logger;
+
+ if (m_logLevel >= level)
+ {
+ doLog(level, msg, throwable);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java
new file mode 100644
index 000000000..35ec2b8be
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java
@@ -0,0 +1,1893 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.StringTokenizer;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.resource.Wiring;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.resolver.ResolutionException;
+import org.osgi.service.resolver.ResolveContext;
+import org.osgi.service.resolver.Resolver;
+
+public class ResolverImpl implements Resolver
+{
+ private final Logger m_logger;
+
+ // Holds candidate permutations based on permutating "uses" chains.
+ // These permutations are given higher priority.
+ private final List<Candidates> m_usesPermutations = new ArrayList<Candidates>();
+ // Holds candidate permutations based on permutating requirement candidates.
+ // These permutations represent backtracking on previous decisions.
+ private final List<Candidates> m_importPermutations = new ArrayList<Candidates>();
+
+ public ResolverImpl(Logger logger)
+ {
+ m_logger = logger;
+ }
+
+ public Map<Resource, List<Wire>> resolve(ResolveContext rc) throws ResolutionException
+ {
+ Map<Resource, List<Wire>> wireMap =
+ new HashMap<Resource, List<Wire>>();
+ Map<Resource, Packages> resourcePkgMap =
+ new HashMap<Resource, Packages>();
+
+ // Make copies of arguments in case we want to modify them.
+ Collection<Resource> mandatoryResources = new ArrayList(rc.getMandatoryResources());
+ Collection<Resource> optionalResources = new ArrayList(rc.getOptionalResources());
+// TODO: RFC-112 - Need impl-specific type.
+// Collection<Resource> ondemandFragments = (rc instanceof ResolveContextImpl)
+// ? ((ResolveContextImpl) rc).getOndemandResources() : Collections.EMPTY_LIST;
+ Collection<Resource> ondemandFragments = Collections.EMPTY_LIST;
+
+ boolean retry;
+ do
+ {
+ retry = false;
+
+ try
+ {
+ // Create object to hold all candidates.
+ Candidates allCandidates = new Candidates();
+
+ // Populate mandatory resources; since these are mandatory
+ // resources, failure throws a resolve exception.
+ for (Iterator<Resource> it = mandatoryResources.iterator();
+ it.hasNext(); )
+ {
+ Resource resource = it.next();
+ if (Util.isFragment(resource) || (rc.getWirings().get(resource) == null))
+ {
+ allCandidates.populate(rc, resource, Candidates.MANDATORY);
+ }
+ else
+ {
+ it.remove();
+ }
+ }
+
+ // Populate optional resources; since these are optional
+ // resources, failure does not throw a resolve exception.
+ for (Resource resource : optionalResources)
+ {
+ boolean isFragment = Util.isFragment(resource);
+ if (isFragment || (rc.getWirings().get(resource) == null))
+ {
+ allCandidates.populate(rc, resource, Candidates.OPTIONAL);
+ }
+ }
+
+ // Populate ondemand fragments; since these are optional
+ // resources, failure does not throw a resolve exception.
+ for (Resource resource : ondemandFragments)
+ {
+ boolean isFragment = Util.isFragment(resource);
+ if (isFragment)
+ {
+ allCandidates.populate(rc, resource, Candidates.ON_DEMAND);
+ }
+ }
+
+ // Merge any fragments into hosts.
+ allCandidates.prepare(rc);
+
+ // Create a combined list of populated resources; for
+ // optional resources. We do not need to consider ondemand
+ // fragments, since they will only be pulled in if their
+ // host is already present.
+ Set<Resource> allResources =
+ new HashSet<Resource>(mandatoryResources);
+ for (Resource resource : optionalResources)
+ {
+ if (allCandidates.isPopulated(resource))
+ {
+ allResources.add(resource);
+ }
+ }
+
+ // Record the initial candidate permutation.
+ m_usesPermutations.add(allCandidates);
+
+ ResolutionException rethrow = null;
+
+ // If a populated resource is a fragment, then its host
+ // must ultimately be verified, so store its host requirement
+ // to use for package space calculation.
+ Map<Resource, List<Requirement>> hostReqs =
+ new HashMap<Resource, List<Requirement>>();
+ for (Resource resource : allResources)
+ {
+ if (Util.isFragment(resource))
+ {
+ hostReqs.put(
+ resource,
+ resource.getRequirements(HostNamespace.HOST_NAMESPACE));
+ }
+ }
+
+ do
+ {
+ rethrow = null;
+
+ resourcePkgMap.clear();
+ m_packageSourcesCache.clear();
+
+ allCandidates = (m_usesPermutations.size() > 0)
+ ? m_usesPermutations.remove(0)
+ : m_importPermutations.remove(0);
+//allCandidates.dump();
+
+ for (Resource resource : allResources)
+ {
+ Resource target = resource;
+
+ // If we are resolving a fragment, then get its
+ // host candidate and verify it instead.
+ List<Requirement> hostReq = hostReqs.get(resource);
+ if (hostReq != null)
+ {
+ target = allCandidates.getCandidates(hostReq.get(0))
+ .iterator().next().getResource();
+ }
+
+ calculatePackageSpaces(
+ rc, allCandidates.getWrappedHost(target), allCandidates,
+ resourcePkgMap, new HashMap(), new HashSet());
+//System.out.println("+++ PACKAGE SPACES START +++");
+//dumpResourcePkgMap(resourcePkgMap);
+//System.out.println("+++ PACKAGE SPACES END +++");
+
+ try
+ {
+ checkPackageSpaceConsistency(
+ rc, allCandidates.getWrappedHost(target),
+ allCandidates, resourcePkgMap, new HashMap());
+ }
+ catch (ResolutionException ex)
+ {
+ rethrow = ex;
+ }
+ }
+ }
+ while ((rethrow != null)
+ && ((m_usesPermutations.size() > 0) || (m_importPermutations.size() > 0)));
+
+ // If there is a resolve exception, then determine if an
+ // optionally resolved resource is to blame (typically a fragment).
+ // If so, then remove the optionally resolved resolved and try
+ // again; otherwise, rethrow the resolve exception.
+ if (rethrow != null)
+ {
+ Collection<Requirement> exReqs = rethrow.getUnresolvedRequirements();
+ Requirement faultyReq = ((exReqs == null) || (exReqs.isEmpty()))
+ ? null : exReqs.iterator().next();
+ Resource faultyResource = (faultyReq == null)
+ ? null : getDeclaredResource(faultyReq.getResource());
+ // If the faulty requirement is wrapped, then it may
+ // be from a fragment, so consider the fragment faulty
+ // instead of the host.
+ if (faultyReq instanceof WrappedRequirement)
+ {
+ faultyResource =
+ ((WrappedRequirement) faultyReq)
+ .getDeclaredRequirement().getResource();
+ }
+ // Try to ignore the faulty resource if it is not mandatory.
+ if (optionalResources.remove(faultyResource))
+ {
+ retry = true;
+ }
+ else if (ondemandFragments.remove(faultyResource))
+ {
+ retry = true;
+ }
+ else
+ {
+ throw rethrow;
+ }
+ }
+ // If there is no exception to rethrow, then this was a clean
+ // resolve, so populate the wire map.
+ else
+ {
+ for (Resource resource : allResources)
+ {
+ Resource target = resource;
+
+ // If we are resolving a fragment, then we
+ // actually want to populate its host's wires.
+ List<Requirement> hostReq = hostReqs.get(resource);
+ if (hostReq != null)
+ {
+ target = allCandidates.getCandidates(hostReq.get(0))
+ .iterator().next().getResource();
+ }
+
+ if (allCandidates.isPopulated(target))
+ {
+ wireMap =
+ populateWireMap(
+ rc, allCandidates.getWrappedHost(target),
+ resourcePkgMap, wireMap, allCandidates);
+ }
+ }
+ }
+ }
+ finally
+ {
+ // Always clear the state.
+ m_usesPermutations.clear();
+ m_importPermutations.clear();
+ }
+ }
+ while (retry);
+
+ return wireMap;
+ }
+
+ /**
+ * Resolves a dynamic requirement for the specified host resource using the specified
+ * {@link ResolveContext}. The dynamic requirement may contain wild cards in its filter
+ * for the package name. The matching candidates are used to resolve the requirement and
+ * the resolve context is not asked to find providers for the dynamic requirement.
+ * The host resource is expected to not be a fragment, to already be resolved and
+ * have an existing wiring provided by the resolve context.
+ * <p>
+ * This operation may resolve additional resources in order to resolve the dynamic
+ * requirement. The returned map will contain entries for each resource that got resolved
+ * in addition to the specified host resource. The wire list for the host resource
+ * will only contain a single wire which is for the dynamic requirement.
+ * @param rc the resolve context
+ * @param host the hosting resource
+ * @param dynamicReq the dynamic requirement
+ * @param matches a list of matching capabilities
+ * @param ondemandFragments collection of on demand fragments that will attach to any host that is a candidate
+ * @return The new resources and wires required to satisfy the specified
+ * dynamic requirement. The returned map is the property of the caller
+ * and can be modified by the caller.
+ * @throws ResolutionException
+ */
+ public Map<Resource, List<Wire>> resolve(
+ ResolveContext rc, Resource host, Requirement dynamicReq,
+ List<Capability> matches, Collection<Resource> ondemandFragments)
+ throws ResolutionException
+ {
+ Map<Resource, List<Wire>> wireMap = new HashMap<Resource, List<Wire>>();
+
+ // We can only create a dynamic import if the following
+ // conditions are met:
+ // 1. The specified resource is resolved.
+ // 2. The package in question is not already imported.
+ // 3. The package in question is not accessible via require-bundle.
+ // 4. The package in question is not exported by the resource.
+ // 5. The package in question matches a dynamic import of the resource.
+ if (!matches.isEmpty() && rc.getWirings().containsKey(host))
+ {
+ // Make sure all matching candidates are packages.
+ for (Capability cap : matches)
+ {
+ if (!cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ throw new IllegalArgumentException(
+ "Matching candidate does not provide a package name.");
+ }
+ }
+
+ // Make copy of args in case we want to modify them.
+ ondemandFragments = new ArrayList<Resource>(ondemandFragments);
+
+ // Create all candidates pre-populated with the single candidate set
+ // for the resolving dynamic import of the host.
+ Candidates allCandidates = new Candidates();
+ allCandidates.populateDynamic(rc, host, dynamicReq, matches);
+
+ Map<Resource, Packages> resourcePkgMap = new HashMap<Resource, Packages>();
+
+ boolean retry;
+ do
+ {
+ retry = false;
+
+ try
+ {
+ // Try to populate optional fragments.
+ for (Resource r : ondemandFragments)
+ {
+ if (Util.isFragment(r))
+ {
+ allCandidates.populate(rc, r, Candidates.ON_DEMAND);
+ }
+ }
+
+ // Merge any fragments into hosts.
+ allCandidates.prepare(rc);
+
+ // Record the initial candidate permutation.
+ m_usesPermutations.add(allCandidates);
+
+ ResolutionException rethrow = null;
+
+ do
+ {
+ rethrow = null;
+
+ resourcePkgMap.clear();
+ m_packageSourcesCache.clear();
+
+ allCandidates = (m_usesPermutations.size() > 0)
+ ? m_usesPermutations.remove(0)
+ : m_importPermutations.remove(0);
+//allCandidates.dump();
+
+ // For a dynamic import, the instigating resource
+ // will never be a fragment since fragments never
+ // execute code, so we don't need to check for
+ // this case like we do for a normal resolve.
+
+ calculatePackageSpaces(rc,
+ allCandidates.getWrappedHost(host), allCandidates,
+ resourcePkgMap, new HashMap(), new HashSet());
+//System.out.println("+++ PACKAGE SPACES START +++");
+//dumpResourcePkgMap(resourcePkgMap);
+//System.out.println("+++ PACKAGE SPACES END +++");
+
+ try
+ {
+ checkDynamicPackageSpaceConsistency(rc,
+ allCandidates.getWrappedHost(host),
+ allCandidates, resourcePkgMap, new HashMap());
+ }
+ catch (ResolutionException ex)
+ {
+ rethrow = ex;
+ }
+ }
+ while ((rethrow != null)
+ && ((m_usesPermutations.size() > 0) || (m_importPermutations.size() > 0)));
+
+ // If there is a resolve exception, then determine if an
+ // optionally resolved resource is to blame (typically a fragment).
+ // If so, then remove the optionally resolved resource and try
+ // again; otherwise, rethrow the resolve exception.
+ if (rethrow != null)
+ {
+ Collection<Requirement> exReqs = rethrow.getUnresolvedRequirements();
+ Requirement faultyReq = ((exReqs == null) || (exReqs.isEmpty()))
+ ? null : exReqs.iterator().next();
+ Resource faultyResource = (faultyReq == null)
+ ? null : getDeclaredResource(faultyReq.getResource());
+ // If the faulty requirement is wrapped, then it may
+ // be from a fragment, so consider the fragment faulty
+ // instead of the host.
+ if (faultyReq instanceof WrappedRequirement)
+ {
+ faultyResource =
+ ((WrappedRequirement) faultyReq)
+ .getDeclaredRequirement().getResource();
+ }
+ // Try to ignore the faulty resource if it is not mandatory.
+ if (ondemandFragments.remove(faultyResource))
+ {
+ retry = true;
+ }
+ else
+ {
+ throw rethrow;
+ }
+ }
+ // If there is no exception to rethrow, then this was a clean
+ // resolve, so populate the wire map.
+ else
+ {
+ wireMap = populateDynamicWireMap(rc,
+ host, dynamicReq, resourcePkgMap, wireMap, allCandidates);
+ }
+ }
+ finally
+ {
+ // Always clear the state.
+ m_usesPermutations.clear();
+ m_importPermutations.clear();
+ }
+ }
+ while (retry);
+ }
+
+ return wireMap;
+ }
+
+ private void calculatePackageSpaces(
+ ResolveContext rc,
+ Resource resource,
+ Candidates allCandidates,
+ Map<Resource, Packages> resourcePkgMap,
+ Map<Capability, List<Resource>> usesCycleMap,
+ Set<Resource> cycle)
+ {
+ if (cycle.contains(resource))
+ {
+ return;
+ }
+ cycle.add(resource);
+
+ // Make sure package space hasn't already been calculated.
+ Packages resourcePkgs = resourcePkgMap.get(resource);
+ if (resourcePkgs != null)
+ {
+ if (resourcePkgs.m_isCalculated)
+ {
+ return;
+ }
+ else
+ {
+ resourcePkgs.m_isCalculated = true;
+ }
+ }
+
+ // Create parallel lists for requirement and proposed candidate
+ // capability or actual capability if resource is resolved or not.
+ // We use parallel lists so we can calculate the packages spaces for
+ // resolved and unresolved resources in an identical fashion.
+ List<Requirement> reqs = new ArrayList();
+ List<Capability> caps = new ArrayList();
+ boolean isDynamicImporting = false;
+ Wiring wiring = rc.getWirings().get(resource);
+ if (wiring != null)
+ {
+ // Use wires to get actual requirements and satisfying capabilities.
+ for (Wire wire : wiring.getRequiredResourceWires(null))
+ {
+ // Wrap the requirement as a hosted requirement if it comes
+ // from a fragment, since we will need to know the host. We
+ // also need to wrap if the requirement is a dynamic import,
+ // since that requirement will be shared with any other
+ // matching dynamic imports.
+ Requirement r = wire.getRequirement();
+ if (!r.getResource().equals(wire.getRequirer())
+ || ((r.getDirectives()
+ .get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE) != null)
+ && r.getDirectives()
+ .get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE)
+ .equals(PackageNamespace.RESOLUTION_DYNAMIC)))
+ {
+ r = new WrappedRequirement(wire.getRequirer(), r);
+ }
+ // Wrap the capability as a hosted capability if it comes
+ // from a fragment, since we will need to know the host.
+ Capability c = wire.getCapability();
+ if (!c.getResource().equals(wire.getProvider()))
+ {
+ c = new WrappedCapability(wire.getProvider(), c);
+ }
+ reqs.add(r);
+ caps.add(c);
+ }
+
+ // Since the resource is resolved, it could be dynamically importing,
+ // so check to see if there are candidates for any of its dynamic
+ // imports.
+ //
+ // NOTE: If the resource is dynamically importing, the fact that
+ // the dynamic import is added here last to the parallel reqs/caps
+ // list is used later when checking to see if the package being
+ // dynamically imported shadows an existing provider.
+ for (Requirement req
+ : Util.getDynamicRequirements(wiring.getResourceRequirements(null)))
+ {
+ // Get the candidates for the current requirement.
+ List<Capability> candCaps = allCandidates.getCandidates(req);
+ // Optional requirements may not have any candidates.
+ if (candCaps == null)
+ {
+ continue;
+ }
+ // Grab first (i.e., highest priority) candidate.
+ Capability cap = candCaps.get(0);
+ reqs.add(req);
+ caps.add(cap);
+ isDynamicImporting = true;
+ // Can only dynamically import one at a time, so break
+ // out of the loop after the first.
+ break;
+ }
+ }
+ else
+ {
+ for (Requirement req : resource.getRequirements(null))
+ {
+ String resolution = req.getDirectives()
+ .get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ if ((resolution == null)
+ || !resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC))
+ {
+ // Get the candidates for the current requirement.
+ List<Capability> candCaps = allCandidates.getCandidates(req);
+ // Optional requirements may not have any candidates.
+ if (candCaps == null)
+ {
+ continue;
+ }
+
+ // Grab first (i.e., highest priority) candidate.
+ Capability cap = candCaps.get(0);
+ reqs.add(req);
+ caps.add(cap);
+ }
+ }
+ }
+
+ // First, add all exported packages to the target resource's package space.
+ calculateExportedPackages(rc, resource, allCandidates, resourcePkgMap);
+ resourcePkgs = resourcePkgMap.get(resource);
+
+ // Second, add all imported packages to the target resource's package space.
+ for (int i = 0; i < reqs.size(); i++)
+ {
+ Requirement req = reqs.get(i);
+ Capability cap = caps.get(i);
+ calculateExportedPackages(rc, cap.getResource(), allCandidates, resourcePkgMap);
+
+ // If this resource is dynamically importing, then the last requirement
+ // is the dynamic import being resolved, since it is added last to the
+ // parallel lists above. For the dynamically imported package, make
+ // sure that the resource doesn't already have a provider for that
+ // package, which would be illegal and shouldn't be allowed.
+ if (isDynamicImporting && ((i + 1) == reqs.size()))
+ {
+ String pkgName = (String)
+ cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ if (resourcePkgs.m_exportedPkgs.containsKey(pkgName)
+ || resourcePkgs.m_importedPkgs.containsKey(pkgName)
+ || resourcePkgs.m_requiredPkgs.containsKey(pkgName))
+ {
+ throw new IllegalArgumentException(
+ "Resource "
+ + resource
+ + " cannot dynamically import package '"
+ + pkgName
+ + "' since it already has access to it."
+ );
+ }
+ }
+
+ mergeCandidatePackages(
+ rc, resource, req, cap, resourcePkgMap, allCandidates,
+ new HashMap<Resource, List<Capability>>());
+ }
+
+ // Third, have all candidates to calculate their package spaces.
+ for (int i = 0; i < caps.size(); i++)
+ {
+ calculatePackageSpaces(
+ rc, caps.get(i).getResource(), allCandidates, resourcePkgMap,
+ usesCycleMap, cycle);
+ }
+
+ // Fourth, if the target resource is unresolved or is dynamically importing,
+ // then add all the uses constraints implied by its imported and required
+ // packages to its package space.
+ // NOTE: We do not need to do this for resolved resources because their
+ // package space is consistent by definition and these uses constraints
+ // are only needed to verify the consistency of a resolving resource. The
+ // only exception is if a resolved resource is dynamically importing, then
+ // we need to calculate its uses constraints again to make sure the new
+ // import is consistent with the existing package space.
+ if ((wiring == null) || isDynamicImporting)
+ {
+ // Merge uses constraints from required capabilities.
+ for (int i = 0; i < reqs.size(); i++)
+ {
+ Requirement req = reqs.get(i);
+ Capability cap = caps.get(i);
+ // Ignore bundle/package requirements, since they are
+ // considered below.
+ if (!req.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE)
+ && !req.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ List<Requirement> blameReqs = new ArrayList<Requirement>();
+ blameReqs.add(req);
+
+ mergeUses(
+ rc,
+ resource,
+ resourcePkgs,
+ cap,
+ blameReqs,
+ resourcePkgMap,
+ allCandidates,
+ usesCycleMap);
+ }
+ }
+ // Merge uses constraints from imported packages.
+ for (Entry<String, List<Blame>> entry : resourcePkgs.m_importedPkgs.entrySet())
+ {
+ for (Blame blame : entry.getValue())
+ {
+ // Ignore resources that import from themselves.
+ if (!blame.m_cap.getResource().equals(resource))
+ {
+ List<Requirement> blameReqs = new ArrayList();
+ blameReqs.add(blame.m_reqs.get(0));
+
+ mergeUses(
+ rc,
+ resource,
+ resourcePkgs,
+ blame.m_cap,
+ blameReqs,
+ resourcePkgMap,
+ allCandidates,
+ usesCycleMap);
+ }
+ }
+ }
+ // Merge uses constraints from required bundles.
+ for (Entry<String, List<Blame>> entry : resourcePkgs.m_requiredPkgs.entrySet())
+ {
+ for (Blame blame : entry.getValue())
+ {
+ List<Requirement> blameReqs = new ArrayList();
+ blameReqs.add(blame.m_reqs.get(0));
+
+ mergeUses(
+ rc,
+ resource,
+ resourcePkgs,
+ blame.m_cap,
+ blameReqs,
+ resourcePkgMap,
+ allCandidates,
+ usesCycleMap);
+ }
+ }
+ }
+ }
+
+ private void mergeCandidatePackages(
+ ResolveContext rc, Resource current, Requirement currentReq,
+ Capability candCap, Map<Resource, Packages> resourcePkgMap,
+ Candidates allCandidates, Map<Resource, List<Capability>> cycles)
+ {
+ List<Capability> cycleCaps = cycles.get(current);
+ if (cycleCaps == null)
+ {
+ cycleCaps = new ArrayList<Capability>();
+ cycles.put(current, cycleCaps);
+ }
+ if (cycleCaps.contains(candCap))
+ {
+ return;
+ }
+ cycleCaps.add(candCap);
+
+ if (candCap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ mergeCandidatePackage(
+ current, false, currentReq, candCap, resourcePkgMap);
+ }
+ else if (candCap.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
+ {
+// TODO: FELIX3 - THIS NEXT LINE IS A HACK. IMPROVE HOW/WHEN WE CALCULATE EXPORTS.
+ calculateExportedPackages(
+ rc, candCap.getResource(), allCandidates, resourcePkgMap);
+
+ // Get the candidate's package space to determine which packages
+ // will be visible to the current resource.
+ Packages candPkgs = resourcePkgMap.get(candCap.getResource());
+
+ // We have to merge all exported packages from the candidate,
+ // since the current resource requires it.
+ for (Entry<String, Blame> entry : candPkgs.m_exportedPkgs.entrySet())
+ {
+ mergeCandidatePackage(
+ current,
+ true,
+ currentReq,
+ entry.getValue().m_cap,
+ resourcePkgMap);
+ }
+
+ // If the candidate requires any other bundles with reexport visibility,
+ // then we also need to merge their packages too.
+ Wiring candWiring = rc.getWirings().get(candCap.getResource());
+ if (candWiring != null)
+ {
+ for (Wire w : candWiring.getRequiredResourceWires(null))
+ {
+ if (w.getRequirement().getNamespace()
+ .equals(BundleNamespace.BUNDLE_NAMESPACE))
+ {
+ String value = w.getRequirement()
+ .getDirectives()
+ .get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE);
+ if ((value != null)
+ && value.equals(BundleNamespace.VISIBILITY_REEXPORT))
+ {
+ mergeCandidatePackages(
+ rc,
+ current,
+ currentReq,
+ w.getCapability(),
+ resourcePkgMap,
+ allCandidates,
+ cycles);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (Requirement req : candCap.getResource().getRequirements(null))
+ {
+ if (req.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
+ {
+ String value =
+ req.getDirectives()
+ .get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE);
+ if ((value != null)
+ && value.equals(BundleNamespace.VISIBILITY_REEXPORT)
+ && (allCandidates.getCandidates(req) != null))
+ {
+ mergeCandidatePackages(
+ rc,
+ current,
+ currentReq,
+ allCandidates.getCandidates(req).iterator().next(),
+ resourcePkgMap,
+ allCandidates,
+ cycles);
+ }
+ }
+ }
+ }
+ }
+
+ cycles.remove(current);
+ }
+
+ private void mergeCandidatePackage(
+ Resource current, boolean requires,
+ Requirement currentReq, Capability candCap,
+ Map<Resource, Packages> resourcePkgMap)
+ {
+ if (candCap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ // Merge the candidate capability into the resource's package space
+ // for imported or required packages, appropriately.
+
+ String pkgName = (String)
+ candCap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+
+ List blameReqs = new ArrayList();
+ blameReqs.add(currentReq);
+
+ Packages currentPkgs = resourcePkgMap.get(current);
+
+ Map<String, List<Blame>> packages = (requires)
+ ? currentPkgs.m_requiredPkgs
+ : currentPkgs.m_importedPkgs;
+ List<Blame> blames = packages.get(pkgName);
+ if (blames == null)
+ {
+ blames = new ArrayList<Blame>();
+ packages.put(pkgName, blames);
+ }
+ blames.add(new Blame(candCap, blameReqs));
+
+//dumpResourcePkgs(current, currentPkgs);
+ }
+ }
+
+ private void mergeUses(
+ ResolveContext rc, Resource current, Packages currentPkgs,
+ Capability mergeCap, List<Requirement> blameReqs,
+ Map<Resource, Packages> resourcePkgMap,
+ Candidates allCandidates,
+ Map<Capability, List<Resource>> cycleMap)
+ {
+ // If there are no uses, then just return.
+ // If the candidate resource is the same as the current resource,
+ // then we don't need to verify and merge the uses constraints
+ // since this will happen as we build up the package space.
+ if (current.equals(mergeCap.getResource()))
+ {
+ return;
+ }
+
+ // Check for cycles.
+ List<Resource> list = cycleMap.get(mergeCap);
+ if ((list != null) && list.contains(current))
+ {
+ return;
+ }
+ list = (list == null) ? new ArrayList<Resource>() : list;
+ list.add(current);
+ cycleMap.put(mergeCap, list);
+
+ for (Capability candSourceCap : getPackageSources(rc, mergeCap, resourcePkgMap))
+ {
+ List<String> uses;
+// TODO: RFC-112 - Need impl-specific type
+// if (candSourceCap instanceof FelixCapability)
+// {
+// uses = ((FelixCapability) candSourceCap).getUses();
+// }
+// else
+ {
+ uses = Collections.EMPTY_LIST;
+ String s = candSourceCap.getDirectives()
+ .get(Namespace.CAPABILITY_USES_DIRECTIVE);
+ if (s != null)
+ {
+ // Parse these uses directive.
+ StringTokenizer tok = new StringTokenizer(s, ",");
+ uses = new ArrayList(tok.countTokens());
+ while (tok.hasMoreTokens())
+ {
+ uses.add(tok.nextToken().trim());
+ }
+ }
+ }
+ for (String usedPkgName : uses)
+ {
+ Packages candSourcePkgs = resourcePkgMap.get(candSourceCap.getResource());
+ List<Blame> candSourceBlames;
+ // Check to see if the used package is exported.
+ Blame candExportedBlame = candSourcePkgs.m_exportedPkgs.get(usedPkgName);
+ if (candExportedBlame != null)
+ {
+ candSourceBlames = new ArrayList(1);
+ candSourceBlames.add(candExportedBlame);
+ }
+ else
+ {
+ // If the used package is not exported, check to see if it
+ // is required.
+ candSourceBlames = candSourcePkgs.m_requiredPkgs.get(usedPkgName);
+ // Lastly, if the used package is not required, check to see if it
+ // is imported.
+ candSourceBlames = (candSourceBlames != null)
+ ? candSourceBlames : candSourcePkgs.m_importedPkgs.get(usedPkgName);
+ }
+
+ // If the used package cannot be found, then just ignore it
+ // since it has no impact.
+ if (candSourceBlames == null)
+ {
+ continue;
+ }
+
+ List<Blame> usedCaps = currentPkgs.m_usedPkgs.get(usedPkgName);
+ if (usedCaps == null)
+ {
+ usedCaps = new ArrayList<Blame>();
+ currentPkgs.m_usedPkgs.put(usedPkgName, usedCaps);
+ }
+ for (Blame blame : candSourceBlames)
+ {
+ if (blame.m_reqs != null)
+ {
+ List<Requirement> blameReqs2 = new ArrayList(blameReqs);
+ blameReqs2.add(blame.m_reqs.get(blame.m_reqs.size() - 1));
+ usedCaps.add(new Blame(blame.m_cap, blameReqs2));
+ mergeUses(rc, current, currentPkgs, blame.m_cap, blameReqs2,
+ resourcePkgMap, allCandidates, cycleMap);
+ }
+ else
+ {
+ usedCaps.add(new Blame(blame.m_cap, blameReqs));
+ mergeUses(rc, current, currentPkgs, blame.m_cap, blameReqs,
+ resourcePkgMap, allCandidates, cycleMap);
+ }
+ }
+ }
+ }
+ }
+
+ private void checkPackageSpaceConsistency(
+ ResolveContext rc,
+ Resource resource,
+ Candidates allCandidates,
+ Map<Resource, Packages> resourcePkgMap,
+ Map<Resource, Object> resultCache) throws ResolutionException
+ {
+ if (rc.getWirings().containsKey(resource))
+ {
+ return;
+ }
+ checkDynamicPackageSpaceConsistency(
+ rc, resource, allCandidates, resourcePkgMap, resultCache);
+ }
+
+ private void checkDynamicPackageSpaceConsistency(
+ ResolveContext rc,
+ Resource resource,
+ Candidates allCandidates,
+ Map<Resource, Packages> resourcePkgMap,
+ Map<Resource, Object> resultCache) throws ResolutionException
+ {
+ if (resultCache.containsKey(resource))
+ {
+ return;
+ }
+
+ Packages pkgs = resourcePkgMap.get(resource);
+
+ ResolutionException rethrow = null;
+ Candidates permutation = null;
+ Set<Requirement> mutated = null;
+
+ // Check for conflicting imports from fragments.
+ for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
+ {
+ if (entry.getValue().size() > 1)
+ {
+ Blame sourceBlame = null;
+ for (Blame blame : entry.getValue())
+ {
+ if (sourceBlame == null)
+ {
+ sourceBlame = blame;
+ }
+ else if (!sourceBlame.m_cap.getResource().equals(blame.m_cap.getResource()))
+ {
+ // Try to permutate the conflicting requirement.
+ permutate(allCandidates, blame.m_reqs.get(0), m_importPermutations);
+ // Try to permutate the source requirement.
+ permutate(allCandidates, sourceBlame.m_reqs.get(0), m_importPermutations);
+ // Report conflict.
+ ResolutionException ex = new ResolutionException(
+ "Uses constraint violation. Unable to resolve resource "
+ + Util.getSymbolicName(resource)
+ + " [" + resource
+ + "] because it is exposed to package '"
+ + entry.getKey()
+ + "' from resources "
+ + Util.getSymbolicName(sourceBlame.m_cap.getResource())
+ + " [" + sourceBlame.m_cap.getResource()
+ + "] and "
+ + Util.getSymbolicName(blame.m_cap.getResource())
+ + " [" + blame.m_cap.getResource()
+ + "] via two dependency chains.\n\nChain 1:\n"
+ + toStringBlame(rc, allCandidates, sourceBlame)
+ + "\n\nChain 2:\n"
+ + toStringBlame(rc, allCandidates, blame),
+ null,
+ Collections.singleton(blame.m_reqs.get(0)));
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "Candidate permutation failed due to a conflict with a "
+ + "fragment import; will try another if possible.",
+ ex);
+ throw ex;
+ }
+ }
+ }
+ }
+
+ // Check if there are any uses conflicts with exported packages.
+ for (Entry<String, Blame> entry : pkgs.m_exportedPkgs.entrySet())
+ {
+ String pkgName = entry.getKey();
+ Blame exportBlame = entry.getValue();
+ if (!pkgs.m_usedPkgs.containsKey(pkgName))
+ {
+ continue;
+ }
+ for (Blame usedBlame : pkgs.m_usedPkgs.get(pkgName))
+ {
+ if (!isCompatible(rc, exportBlame.m_cap, usedBlame.m_cap, resourcePkgMap))
+ {
+ // Create a candidate permutation that eliminates all candidates
+ // that conflict with existing selected candidates.
+ permutation = (permutation != null)
+ ? permutation
+ : allCandidates.copy();
+ rethrow = (rethrow != null)
+ ? rethrow
+ : new ResolutionException(
+ "Uses constraint violation. Unable to resolve resource "
+ + Util.getSymbolicName(resource)
+ + " [" + resource
+ + "] because it exports package '"
+ + pkgName
+ + "' and is also exposed to it from resource "
+ + Util.getSymbolicName(usedBlame.m_cap.getResource())
+ + " [" + usedBlame.m_cap.getResource()
+ + "] via the following dependency chain:\n\n"
+ + toStringBlame(rc, allCandidates, usedBlame),
+ null,
+ null);
+
+ mutated = (mutated != null)
+ ? mutated
+ : new HashSet<Requirement>();
+
+ for (int reqIdx = usedBlame.m_reqs.size() - 1; reqIdx >= 0; reqIdx--)
+ {
+ Requirement req = usedBlame.m_reqs.get(reqIdx);
+
+ // If we've already permutated this requirement in another
+ // uses constraint, don't permutate it again just continue
+ // with the next uses constraint.
+ if (mutated.contains(req))
+ {
+ break;
+ }
+
+ // See if we can permutate the candidates for blamed
+ // requirement; there may be no candidates if the resource
+ // associated with the requirement is already resolved.
+ List<Capability> candidates = permutation.getCandidates(req);
+ if ((candidates != null) && (candidates.size() > 1))
+ {
+ mutated.add(req);
+ // Remove the conflicting candidate.
+ candidates.remove(0);
+ // Continue with the next uses constraint.
+ break;
+ }
+ }
+ }
+ }
+
+ if (rethrow != null)
+ {
+ if (mutated.size() > 0)
+ {
+ m_usesPermutations.add(permutation);
+ }
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "Candidate permutation failed due to a conflict between "
+ + "an export and import; will try another if possible.",
+ rethrow);
+ throw rethrow;
+ }
+ }
+
+ // Check if there are any uses conflicts with imported packages.
+ for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
+ {
+ for (Blame importBlame : entry.getValue())
+ {
+ String pkgName = entry.getKey();
+ if (!pkgs.m_usedPkgs.containsKey(pkgName))
+ {
+ continue;
+ }
+ for (Blame usedBlame : pkgs.m_usedPkgs.get(pkgName))
+ {
+ if (!isCompatible(rc, importBlame.m_cap, usedBlame.m_cap, resourcePkgMap))
+ {
+ // Create a candidate permutation that eliminates any candidates
+ // that conflict with existing selected candidates.
+ permutation = (permutation != null)
+ ? permutation
+ : allCandidates.copy();
+ rethrow = (rethrow != null)
+ ? rethrow
+ : new ResolutionException(
+ "Uses constraint violation. Unable to resolve resource "
+ + Util.getSymbolicName(resource)
+ + " [" + resource
+ + "] because it is exposed to package '"
+ + pkgName
+ + "' from resources "
+ + Util.getSymbolicName(importBlame.m_cap.getResource())
+ + " [" + importBlame.m_cap.getResource()
+ + "] and "
+ + Util.getSymbolicName(usedBlame.m_cap.getResource())
+ + " [" + usedBlame.m_cap.getResource()
+ + "] via two dependency chains.\n\nChain 1:\n"
+ + toStringBlame(rc, allCandidates, importBlame)
+ + "\n\nChain 2:\n"
+ + toStringBlame(rc, allCandidates, usedBlame),
+ null,
+ null);
+
+ mutated = (mutated != null)
+ ? mutated
+ : new HashSet();
+
+ for (int reqIdx = usedBlame.m_reqs.size() - 1; reqIdx >= 0; reqIdx--)
+ {
+ Requirement req = usedBlame.m_reqs.get(reqIdx);
+
+ // If we've already permutated this requirement in another
+ // uses constraint, don't permutate it again just continue
+ // with the next uses constraint.
+ if (mutated.contains(req))
+ {
+ break;
+ }
+
+ // See if we can permutate the candidates for blamed
+ // requirement; there may be no candidates if the resource
+ // associated with the requirement is already resolved.
+ List<Capability> candidates = permutation.getCandidates(req);
+ if ((candidates != null) && (candidates.size() > 1))
+ {
+ mutated.add(req);
+ // Remove the conflicting candidate.
+ candidates.remove(0);
+ // Continue with the next uses constraint.
+ break;
+ }
+ }
+ }
+ }
+
+ // If there was a uses conflict, then we should add a uses
+ // permutation if we were able to permutate any candidates.
+ // Additionally, we should try to push an import permutation
+ // for the original import to force a backtracking on the
+ // original candidate decision if no viable candidate is found
+ // for the conflicting uses constraint.
+ if (rethrow != null)
+ {
+ // Add uses permutation if we mutated any candidates.
+ if (mutated.size() > 0)
+ {
+ m_usesPermutations.add(permutation);
+ }
+
+ // Try to permutate the candidate for the original
+ // import requirement; only permutate it if we haven't
+ // done so already.
+ Requirement req = importBlame.m_reqs.get(0);
+ if (!mutated.contains(req))
+ {
+ // Since there may be lots of uses constraint violations
+ // with existing import decisions, we may end up trying
+ // to permutate the same import a lot of times, so we should
+ // try to check if that the case and only permutate it once.
+ permutateIfNeeded(allCandidates, req, m_importPermutations);
+ }
+
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "Candidate permutation failed due to a conflict between "
+ + "imports; will try another if possible.",
+ rethrow);
+ throw rethrow;
+ }
+ }
+ }
+
+ resultCache.put(resource, Boolean.TRUE);
+
+ // Now check the consistency of all resources on which the
+ // current resource depends. Keep track of the current number
+ // of permutations so we know if the lower level check was
+ // able to create a permutation or not in the case of failure.
+ int permCount = m_usesPermutations.size() + m_importPermutations.size();
+ for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
+ {
+ for (Blame importBlame : entry.getValue())
+ {
+ if (!resource.equals(importBlame.m_cap.getResource()))
+ {
+ try
+ {
+ checkPackageSpaceConsistency(
+ rc, importBlame.m_cap.getResource(),
+ allCandidates, resourcePkgMap, resultCache);
+ }
+ catch (ResolutionException ex)
+ {
+ // If the lower level check didn't create any permutations,
+ // then we should create an import permutation for the
+ // requirement with the dependency on the failing resource
+ // to backtrack on our current candidate selection.
+ if (permCount == (m_usesPermutations.size() + m_importPermutations.size()))
+ {
+ Requirement req = importBlame.m_reqs.get(0);
+ permutate(allCandidates, req, m_importPermutations);
+ }
+ throw ex;
+ }
+ }
+ }
+ }
+ }
+
+ private static void permutate(
+ Candidates allCandidates, Requirement req, List<Candidates> permutations)
+ {
+ List<Capability> candidates = allCandidates.getCandidates(req);
+ if ((candidates != null) && (candidates.size() > 1))
+ {
+ Candidates perm = allCandidates.copy();
+ candidates = perm.getCandidates(req);
+ candidates.remove(0);
+ permutations.add(perm);
+ }
+ }
+
+ private static void permutateIfNeeded(
+ Candidates allCandidates, Requirement req, List<Candidates> permutations)
+ {
+ List<Capability> candidates = allCandidates.getCandidates(req);
+ if ((candidates != null) && (candidates.size() > 1))
+ {
+ // Check existing permutations to make sure we haven't
+ // already permutated this requirement. This check for
+ // duplicate permutations is simplistic. It assumes if
+ // there is any permutation that contains a different
+ // initial candidate for the requirement in question,
+ // then it has already been permutated.
+ boolean permutated = false;
+ for (Candidates existingPerm : permutations)
+ {
+ List<Capability> existingPermCands = existingPerm.getCandidates(req);
+ if (!existingPermCands.get(0).equals(candidates.get(0)))
+ {
+ permutated = true;
+ }
+ }
+ // If we haven't already permutated the existing
+ // import, do so now.
+ if (!permutated)
+ {
+ permutate(allCandidates, req, permutations);
+ }
+ }
+ }
+
+ private static void calculateExportedPackages(
+ ResolveContext rc,
+ Resource resource,
+ Candidates allCandidates,
+ Map<Resource, Packages> resourcePkgMap)
+ {
+ Packages packages = resourcePkgMap.get(resource);
+ if (packages != null)
+ {
+ return;
+ }
+ packages = new Packages(resource);
+
+ // Get all exported packages.
+ Wiring wiring = rc.getWirings().get(resource);
+ List<Capability> caps = (wiring != null)
+ ? wiring.getResourceCapabilities(null)
+ : resource.getCapabilities(null);
+ Map<String, Capability> exports = new HashMap<String, Capability>(caps.size());
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ if (!cap.getResource().equals(resource))
+ {
+ cap = new WrappedCapability(resource, cap);
+ }
+ exports.put(
+ (String) cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE),
+ cap);
+ }
+ }
+ // Remove substitutable exports that were imported.
+ // For resolved resources Wiring.getCapabilities()
+ // already excludes imported substitutable exports, but
+ // for resolving resources we must look in the candidate
+ // map to determine which exports are substitutable.
+ if (!exports.isEmpty())
+ {
+ if (wiring == null)
+ {
+ for (Requirement req : resource.getRequirements(null))
+ {
+ if (req.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ List<Capability> cands = allCandidates.getCandidates(req);
+ if ((cands != null) && !cands.isEmpty())
+ {
+ String pkgName = (String) cands.get(0)
+ .getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ exports.remove(pkgName);
+ }
+ }
+ }
+ }
+
+ // Add all non-substituted exports to the resources's package space.
+ for (Entry<String, Capability> entry : exports.entrySet())
+ {
+ packages.m_exportedPkgs.put(
+ entry.getKey(), new Blame(entry.getValue(), null));
+ }
+ }
+
+ resourcePkgMap.put(resource, packages);
+ }
+
+ private boolean isCompatible(
+ ResolveContext rc, Capability currentCap, Capability candCap,
+ Map<Resource, Packages> resourcePkgMap)
+ {
+ if ((currentCap != null) && (candCap != null))
+ {
+ if (currentCap.equals(candCap))
+ {
+ return true;
+ }
+
+ List<Capability> currentSources =
+ getPackageSources(
+ rc,
+ currentCap,
+ resourcePkgMap);
+ List<Capability> candSources =
+ getPackageSources(
+ rc,
+ candCap,
+ resourcePkgMap);
+
+ return currentSources.containsAll(candSources)
+ || candSources.containsAll(currentSources);
+ }
+ return true;
+ }
+
+ private Map<Capability, List<Capability>> m_packageSourcesCache = new HashMap();
+
+ private List<Capability> getPackageSources(
+ ResolveContext rc, Capability cap, Map<Resource, Packages> resourcePkgMap)
+ {
+ // If it is a package, then calculate sources for it.
+ if (cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ List<Capability> sources = m_packageSourcesCache.get(cap);
+ if (sources == null)
+ {
+ sources = getPackageSourcesInternal(
+ rc, cap, resourcePkgMap, new ArrayList(), new HashSet());
+ m_packageSourcesCache.put(cap, sources);
+ }
+ return sources;
+ }
+
+ // Otherwise, need to return generic capabilies that have
+ // uses constraints so they are included for consistency
+ // checking.
+ String uses = cap.getDirectives().get(Namespace.CAPABILITY_USES_DIRECTIVE);
+ if ((uses != null) && (uses.length() > 0))
+ {
+ return Collections.singletonList(cap);
+ }
+
+ return Collections.EMPTY_LIST;
+ }
+
+ private static List<Capability> getPackageSourcesInternal(
+ ResolveContext rc, Capability cap, Map<Resource, Packages> resourcePkgMap,
+ List<Capability> sources, Set<Capability> cycleMap)
+ {
+ if (cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ if (cycleMap.contains(cap))
+ {
+ return sources;
+ }
+ cycleMap.add(cap);
+
+ // Get the package name associated with the capability.
+ String pkgName = cap.getAttributes()
+ .get(PackageNamespace.PACKAGE_NAMESPACE).toString();
+
+ // Since a resource can export the same package more than once, get
+ // all package capabilities for the specified package name.
+ Wiring wiring = rc.getWirings().get(cap.getResource());
+ List<Capability> caps = (wiring != null)
+ ? wiring.getResourceCapabilities(null)
+ : cap.getResource().getCapabilities(null);
+ for (Capability sourceCap : caps)
+ {
+ if (sourceCap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE)
+ && sourceCap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE).equals(pkgName))
+ {
+ // Since capabilities may come from fragments, we need to check
+ // for that case and wrap them.
+ if (!cap.getResource().equals(sourceCap.getResource()))
+ {
+ sources.add(new WrappedCapability(cap.getResource(), sourceCap));
+ }
+ else
+ {
+ sources.add(sourceCap);
+ }
+ }
+ }
+
+ // Then get any addition sources for the package from required bundles.
+ Packages pkgs = resourcePkgMap.get(cap.getResource());
+ List<Blame> required = pkgs.m_requiredPkgs.get(pkgName);
+ if (required != null)
+ {
+ for (Blame blame : required)
+ {
+ getPackageSourcesInternal(rc, blame.m_cap, resourcePkgMap, sources, cycleMap);
+ }
+ }
+ }
+
+ return sources;
+ }
+
+ private static Resource getDeclaredResource(Resource resource)
+ {
+ if (resource instanceof WrappedResource)
+ {
+ return ((WrappedResource) resource).getDeclaredResource();
+ }
+ return resource;
+ }
+
+ private static Capability getDeclaredCapability(Capability c)
+ {
+ if (c instanceof HostedCapability)
+ {
+ return ((HostedCapability) c).getDeclaredCapability();
+ }
+ return c;
+ }
+
+ private static Requirement getDeclaredRequirement(Requirement r)
+ {
+ if (r instanceof WrappedRequirement)
+ {
+ return ((WrappedRequirement) r).getDeclaredRequirement();
+ }
+ return r;
+ }
+
+ private static Map<Resource, List<Wire>> populateWireMap(
+ ResolveContext rc, Resource resource, Map<Resource, Packages> resourcePkgMap,
+ Map<Resource, List<Wire>> wireMap, Candidates allCandidates)
+ {
+ Resource unwrappedResource = getDeclaredResource(resource);
+ if (!rc.getWirings().containsKey(unwrappedResource)
+ && !wireMap.containsKey(unwrappedResource))
+ {
+ wireMap.put(unwrappedResource, (List<Wire>) Collections.EMPTY_LIST);
+
+ List<Wire> packageWires = new ArrayList<Wire>();
+ List<Wire> bundleWires = new ArrayList<Wire>();
+ List<Wire> capabilityWires = new ArrayList<Wire>();
+
+ for (Requirement req : resource.getRequirements(null))
+ {
+ List<Capability> cands = allCandidates.getCandidates(req);
+ if ((cands != null) && (cands.size() > 0))
+ {
+ Capability cand = cands.get(0);
+ // Do not create wires for the osgi.wiring.* namespaces
+ // if the provider and requirer are the same resource;
+ // allow such wires for non-OSGi wiring namespaces.
+ if (!cand.getNamespace().startsWith("osgi.wiring.")
+ || !resource.equals(cand.getResource()))
+ {
+ if (!rc.getWirings().containsKey(cand.getResource()))
+ {
+ populateWireMap(rc, cand.getResource(),
+ resourcePkgMap, wireMap, allCandidates);
+ }
+ Wire wire = new WireImpl(
+ unwrappedResource,
+ getDeclaredRequirement(req),
+ getDeclaredResource(cand.getResource()),
+ getDeclaredCapability(cand));
+ if (req.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ packageWires.add(wire);
+ }
+ else if (req.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
+ {
+ bundleWires.add(wire);
+ }
+ else
+ {
+ capabilityWires.add(wire);
+ }
+ }
+ }
+ }
+
+ // Combine package wires with require wires last.
+ packageWires.addAll(bundleWires);
+ packageWires.addAll(capabilityWires);
+ wireMap.put(unwrappedResource, packageWires);
+
+ // Add host wire for any fragments.
+ if (resource instanceof WrappedResource)
+ {
+ List<Resource> fragments = ((WrappedResource) resource).getFragments();
+ for (Resource fragment : fragments)
+ {
+ // Get wire list for the fragment from the wire map.
+ // If there isn't one, then create one. Note that we won't
+ // add the wire list to the wire map until the end, so
+ // we can determine below if this is the first time we've
+ // seen the fragment while populating wires to avoid
+ // creating duplicate non-payload wires if the fragment
+ // is attached to more than one host.
+ List<Wire> fragmentWires = wireMap.get(fragment);
+ fragmentWires = (fragmentWires == null)
+ ? new ArrayList<Wire>() : fragmentWires;
+
+ // Loop through all of the fragment's requirements and create
+ // any necessary wires for non-payload requirements.
+ for (Requirement req : fragment.getRequirements(null))
+ {
+ // Only look at non-payload requirements.
+ if (!isPayload(req))
+ {
+ // If this is the host requirement, then always create
+ // a wire for it to the current resource.
+ if (req.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
+ {
+ fragmentWires.add(
+ new WireImpl(
+ getDeclaredResource(fragment),
+ req,
+ unwrappedResource,
+ unwrappedResource.getCapabilities(
+ HostNamespace.HOST_NAMESPACE).get(0)));
+ }
+ // Otherwise, if the fragment isn't already resolved and
+ // this is the first time we are seeing it, then create
+ // a wire for the non-payload requirement.
+ else if (!rc.getWirings().containsKey(fragment)
+ && !wireMap.containsKey(fragment))
+ {
+ Wire wire = createWire(req, allCandidates);
+ if (wire != null)
+ {
+ fragmentWires.add(wire);
+ }
+ }
+ }
+ }
+
+ // Finally, add the fragment's wire list to the wire map.
+ wireMap.put(fragment, fragmentWires);
+ }
+ }
+ }
+
+ return wireMap;
+ }
+
+ private static Wire createWire(Requirement requirement, Candidates allCandidates)
+ {
+ List<Capability> candidates = allCandidates.getCandidates(requirement);
+ if (candidates == null || candidates.isEmpty())
+ {
+ return null;
+ }
+ Capability cand = candidates.get(0);
+ return new WireImpl(
+ getDeclaredResource(requirement.getResource()),
+ getDeclaredRequirement(requirement),
+ getDeclaredResource(cand.getResource()),
+ getDeclaredCapability(cand));
+ }
+
+ private static boolean isPayload(Requirement fragmentReq)
+ {
+ // this is where we would add other non-payload namespaces
+ if (ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE
+ .equals(fragmentReq.getNamespace()))
+ {
+ return false;
+ }
+ if (HostNamespace.HOST_NAMESPACE.equals(fragmentReq.getNamespace()))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private static Map<Resource, List<Wire>> populateDynamicWireMap(
+ ResolveContext rc, Resource resource, Requirement dynReq,
+ Map<Resource, Packages> resourcePkgMap,
+ Map<Resource, List<Wire>> wireMap, Candidates allCandidates)
+ {
+ wireMap.put(resource, (List<Wire>) Collections.EMPTY_LIST);
+
+ List<Wire> packageWires = new ArrayList<Wire>();
+
+ // Get the candidates for the current dynamic requirement.
+ List<Capability> candCaps = allCandidates.getCandidates(dynReq);
+ // Record the dynamic candidate.
+ Capability dynCand = candCaps.get(0);
+
+ if (!rc.getWirings().containsKey(dynCand.getResource()))
+ {
+ populateWireMap(rc, dynCand.getResource(), resourcePkgMap,
+ wireMap, allCandidates);
+ }
+
+ packageWires.add(
+ new WireImpl(
+ resource,
+ dynReq,
+ getDeclaredResource(dynCand.getResource()),
+ getDeclaredCapability(dynCand)));
+
+ wireMap.put(resource, packageWires);
+
+ return wireMap;
+ }
+
+ private static void dumpResourcePkgMap(
+ ResolveContext rc, Map<Resource, Packages> resourcePkgMap)
+ {
+ System.out.println("+++RESOURCE PKG MAP+++");
+ for (Entry<Resource, Packages> entry : resourcePkgMap.entrySet())
+ {
+ dumpResourcePkgs(rc, entry.getKey(), entry.getValue());
+ }
+ }
+
+ private static void dumpResourcePkgs(
+ ResolveContext rc, Resource resource, Packages packages)
+ {
+ Wiring wiring = rc.getWirings().get(resource);
+ System.out.println(resource
+ + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)"));
+ System.out.println(" EXPORTED");
+ for (Entry<String, Blame> entry : packages.m_exportedPkgs.entrySet())
+ {
+ System.out.println(" " + entry.getKey() + " - " + entry.getValue());
+ }
+ System.out.println(" IMPORTED");
+ for (Entry<String, List<Blame>> entry : packages.m_importedPkgs.entrySet())
+ {
+ System.out.println(" " + entry.getKey() + " - " + entry.getValue());
+ }
+ System.out.println(" REQUIRED");
+ for (Entry<String, List<Blame>> entry : packages.m_requiredPkgs.entrySet())
+ {
+ System.out.println(" " + entry.getKey() + " - " + entry.getValue());
+ }
+ System.out.println(" USED");
+ for (Entry<String, List<Blame>> entry : packages.m_usedPkgs.entrySet())
+ {
+ System.out.println(" " + entry.getKey() + " - " + entry.getValue());
+ }
+ }
+
+ private static String toStringBlame(
+ ResolveContext rc, Candidates allCandidates, Blame blame)
+ {
+ StringBuffer sb = new StringBuffer();
+ if ((blame.m_reqs != null) && !blame.m_reqs.isEmpty())
+ {
+ for (int i = 0; i < blame.m_reqs.size(); i++)
+ {
+ Requirement req = blame.m_reqs.get(i);
+ sb.append(" ");
+ sb.append(Util.getSymbolicName(req.getResource()));
+ sb.append(" [");
+ sb.append(req.getResource().toString());
+ sb.append("]\n");
+ if (req.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ sb.append(" import: ");
+ }
+ else
+ {
+ sb.append(" require: ");
+ }
+ sb.append(req.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE));
+ sb.append("\n |");
+ if (req.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ sb.append("\n export: ");
+ }
+ else
+ {
+ sb.append("\n provide: ");
+ }
+ if ((i + 1) < blame.m_reqs.size())
+ {
+ Capability cap = getSatisfyingCapability(
+ rc,
+ allCandidates,
+ blame.m_reqs.get(i));
+ if (cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ sb.append(PackageNamespace.PACKAGE_NAMESPACE);
+ sb.append("=");
+ sb.append(cap.getAttributes()
+ .get(PackageNamespace.PACKAGE_NAMESPACE).toString());
+ Capability usedCap =
+ getSatisfyingCapability(
+ rc,
+ allCandidates,
+ blame.m_reqs.get(i + 1));
+ sb.append("; uses:=");
+ sb.append(usedCap.getAttributes()
+ .get(PackageNamespace.PACKAGE_NAMESPACE));
+ }
+ else
+ {
+ sb.append(cap);
+ }
+ sb.append("\n");
+ }
+ else
+ {
+ Capability export = getSatisfyingCapability(
+ rc,
+ allCandidates,
+ blame.m_reqs.get(i));
+ sb.append(export.getNamespace());
+ sb.append("=");
+ sb.append(export.getAttributes().get(export.getNamespace()).toString());
+ if (export.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE)
+ && !export.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE)
+ .equals(blame.m_cap.getAttributes().get(
+ PackageNamespace.PACKAGE_NAMESPACE)))
+ {
+ sb.append("; uses:=");
+ sb.append(blame.m_cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
+ sb.append("\n export: ");
+ sb.append(PackageNamespace.PACKAGE_NAMESPACE);
+ sb.append("=");
+ sb.append(blame.m_cap.getAttributes()
+ .get(PackageNamespace.PACKAGE_NAMESPACE).toString());
+ }
+ sb.append("\n ");
+ sb.append(Util.getSymbolicName(blame.m_cap.getResource()));
+ sb.append(" [");
+ sb.append(blame.m_cap.getResource().toString());
+ sb.append("]");
+ }
+ }
+ }
+ else
+ {
+ sb.append(blame.m_cap.getResource().toString());
+ }
+ return sb.toString();
+ }
+
+ private static Capability getSatisfyingCapability(
+ ResolveContext rc, Candidates allCandidates, Requirement req)
+ {
+ Capability cap = null;
+
+ // If the requiring revision is not resolved, then check in the
+ // candidate map for its matching candidate.
+ List<Capability> cands = allCandidates.getCandidates(req);
+ if (cands != null)
+ {
+ cap = cands.get(0);
+ }
+ // Otherwise, if the requiring revision is resolved then check
+ // in its wires for the capability satisfying the requirement.
+ else if (rc.getWirings().containsKey(req.getResource()))
+ {
+ List<Wire> wires =
+ rc.getWirings().get(req.getResource()).getRequiredResourceWires(null);
+ req = getDeclaredRequirement(req);
+ for (Wire w : wires)
+ {
+ if (w.getRequirement().equals(req))
+ {
+// TODO: RESOLVER - This is not 100% correct, since requirements for
+// dynamic imports with wildcards will reside on many wires and
+// this code only finds the first one, not necessarily the correct
+// one. This is only used for the diagnostic message, but it still
+// could confuse the user.
+ cap = w.getCapability();
+ break;
+ }
+ }
+ }
+
+ return cap;
+ }
+
+ private static class Packages
+ {
+ private final Resource m_resource;
+ public final Map<String, Blame> m_exportedPkgs = new HashMap();
+ public final Map<String, List<Blame>> m_importedPkgs = new HashMap();
+ public final Map<String, List<Blame>> m_requiredPkgs = new HashMap();
+ public final Map<String, List<Blame>> m_usedPkgs = new HashMap();
+ public boolean m_isCalculated = false;
+
+ public Packages(Resource resource)
+ {
+ m_resource = resource;
+ }
+ }
+
+ private static class Blame
+ {
+ public final Capability m_cap;
+ public final List<Requirement> m_reqs;
+
+ public Blame(Capability cap, List<Requirement> reqs)
+ {
+ m_cap = cap;
+ m_reqs = reqs;
+ }
+
+ @Override
+ public String toString()
+ {
+ return m_cap.getResource()
+ + "." + m_cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE)
+ + (((m_reqs == null) || m_reqs.isEmpty())
+ ? " NO BLAME"
+ : " BLAMED ON " + m_reqs);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ return (o instanceof Blame) && m_reqs.equals(((Blame) o).m_reqs)
+ && m_cap.equals(((Blame) o).m_cap);
+ }
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ShadowList.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ShadowList.java
new file mode 100644
index 000000000..05734da46
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ShadowList.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+public class ShadowList<T> implements List<T>
+{
+ private final List<T> m_original;
+ private final List<T> m_shadow;
+
+ public ShadowList(List<T> original)
+ {
+ m_original = original;
+ m_shadow = new ArrayList<T>(original);
+ }
+
+ public List<T> getOriginal()
+ {
+ return m_original;
+ }
+
+ public int size()
+ {
+ return m_shadow.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return m_shadow.isEmpty();
+ }
+
+ public boolean contains(Object o)
+ {
+ return m_shadow.contains(o);
+ }
+
+ public Iterator<T> iterator()
+ {
+ return m_shadow.iterator();
+ }
+
+ public Object[] toArray()
+ {
+ return m_shadow.toArray();
+ }
+
+ public <T> T[] toArray(T[] ts)
+ {
+ return m_shadow.toArray(ts);
+ }
+
+ public boolean add(T e)
+ {
+ return m_shadow.add(e);
+ }
+
+ public boolean remove(Object o)
+ {
+ return m_shadow.remove(o);
+ }
+
+ public boolean containsAll(Collection<?> clctn)
+ {
+ return m_shadow.containsAll(clctn);
+ }
+
+ public boolean addAll(Collection<? extends T> clctn)
+ {
+ return m_shadow.addAll(clctn);
+ }
+
+ public boolean addAll(int i, Collection<? extends T> clctn)
+ {
+ return m_shadow.addAll(i, clctn);
+ }
+
+ public boolean removeAll(Collection<?> clctn)
+ {
+ return m_shadow.removeAll(clctn);
+ }
+
+ public boolean retainAll(Collection<?> clctn)
+ {
+ return m_shadow.retainAll(clctn);
+ }
+
+ public void clear()
+ {
+ m_shadow.clear();
+ }
+
+ public T get(int i)
+ {
+ return m_shadow.get(i);
+ }
+
+ public T set(int i, T e)
+ {
+ return m_shadow.set(i, e);
+ }
+
+ public void add(int i, T e)
+ {
+ m_shadow.add(i, e);
+ }
+
+ public T remove(int i)
+ {
+ return m_shadow.remove(i);
+ }
+
+ public int indexOf(Object o)
+ {
+ return m_shadow.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ return m_shadow.lastIndexOf(o);
+ }
+
+ public ListIterator<T> listIterator()
+ {
+ return m_shadow.listIterator();
+ }
+
+ public ListIterator<T> listIterator(int i)
+ {
+ return m_shadow.listIterator(i);
+ }
+
+ public List<T> subList(int i, int i1)
+ {
+ return m_shadow.subList(i, i1);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/SimpleHostedCapability.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/SimpleHostedCapability.java
new file mode 100644
index 000000000..98e2d4f3d
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/SimpleHostedCapability.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.Map;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+import org.osgi.service.resolver.HostedCapability;
+
+class SimpleHostedCapability implements HostedCapability
+{
+ private final Resource m_host;
+ private final Capability m_cap;
+
+ SimpleHostedCapability(Resource host, Capability cap)
+ {
+ m_host = host;
+ m_cap = cap;
+ }
+
+ public Resource getResource()
+ {
+ return m_host;
+ }
+
+ public Capability getDeclaredCapability()
+ {
+ return m_cap;
+ }
+
+ public String getNamespace()
+ {
+ return m_cap.getNamespace();
+ }
+
+ public Map<String, String> getDirectives()
+ {
+ return m_cap.getDirectives();
+ }
+
+ public Map<String, Object> getAttributes()
+ {
+ return m_cap.getAttributes();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Util.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Util.java
new file mode 100644
index 000000000..dc5a10003
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Util.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class Util
+{
+ public static String getSymbolicName(Resource resource)
+ {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(IdentityNamespace.IDENTITY_NAMESPACE))
+ {
+ return cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE).toString();
+ }
+ }
+ return null;
+ }
+
+ public static Version getVersion(Resource resource)
+ {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(IdentityNamespace.IDENTITY_NAMESPACE))
+ {
+ return (Version)
+ cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ }
+ }
+ return null;
+ }
+
+ public static boolean isFragment(Resource resource)
+ {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(IdentityNamespace.IDENTITY_NAMESPACE))
+ {
+ String type = (String)
+ cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE);
+ return (type != null) && type.equals(IdentityNamespace.TYPE_FRAGMENT);
+ }
+ }
+ return false;
+ }
+
+ public static boolean isOptional(Requirement req)
+ {
+ String resolution = req.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ return Namespace.RESOLUTION_OPTIONAL.equalsIgnoreCase(resolution);
+ }
+
+ public static List<Requirement> getDynamicRequirements(List<Requirement> reqs)
+ {
+ List<Requirement> result = new ArrayList<Requirement>();
+ if (reqs != null)
+ {
+ for (Requirement req : reqs)
+ {
+ String resolution = req.getDirectives()
+ .get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ if ((resolution != null)
+ && resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC))
+ {
+ result.add(req);
+ }
+ }
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WireImpl.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WireImpl.java
new file mode 100644
index 000000000..a79ac7114
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WireImpl.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+
+class WireImpl implements Wire
+{
+ private final Resource m_requirer;
+ private final Requirement m_req;
+ private final Resource m_provider;
+ private final Capability m_cap;
+
+ public WireImpl(
+ Resource requirer, Requirement req,
+ Resource provider, Capability cap)
+ {
+ m_requirer = requirer;
+ m_req = req;
+ m_provider = provider;
+ m_cap = cap;
+ }
+
+ public Resource getRequirer()
+ {
+ return m_requirer;
+ }
+
+ public Requirement getRequirement()
+ {
+ return m_req;
+ }
+
+ public Resource getProvider()
+ {
+ return m_provider;
+ }
+
+ public Capability getCapability()
+ {
+ return m_cap;
+ }
+
+ @Override
+ public String toString()
+ {
+ return m_req
+ + " -> "
+ + "[" + m_provider + "]";
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof Wire))
+ {
+ return false;
+ }
+ final Wire other = (Wire) obj;
+ if (this.m_requirer != other.getRequirer()
+ && (this.m_requirer == null || !this.m_requirer.equals(other.getRequirer())))
+ {
+ return false;
+ }
+ if (this.m_req != other.getRequirement()
+ && (this.m_req == null || !this.m_req.equals(other.getRequirement())))
+ {
+ return false;
+ }
+ if (this.m_provider != other.getProvider()
+ && (this.m_provider == null || !this.m_provider.equals(other.getProvider())))
+ {
+ return false;
+ }
+ if (this.m_cap != other.getCapability()
+ && (this.m_cap == null || !this.m_cap.equals(other.getCapability())))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 5;
+ hash = 29 * hash + (this.m_requirer != null ? this.m_requirer.hashCode() : 0);
+ hash = 29 * hash + (this.m_req != null ? this.m_req.hashCode() : 0);
+ hash = 29 * hash + (this.m_provider != null ? this.m_provider.hashCode() : 0);
+ hash = 29 * hash + (this.m_cap != null ? this.m_cap.hashCode() : 0);
+ return hash;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedCapability.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedCapability.java
new file mode 100644
index 000000000..9bbec36e2
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedCapability.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.Map;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+import org.osgi.service.resolver.HostedCapability;
+
+public class WrappedCapability implements HostedCapability
+{
+ private final Resource m_host;
+ private final Capability m_cap;
+
+ public WrappedCapability(Resource host, Capability cap)
+ {
+ m_host = host;
+ m_cap = cap;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final WrappedCapability other = (WrappedCapability) obj;
+ if (m_host != other.m_host && (m_host == null || !m_host.equals(other.m_host)))
+ {
+ return false;
+ }
+ if (m_cap != other.m_cap && (m_cap == null || !m_cap.equals(other.m_cap)))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 7;
+ hash = 37 * hash + (m_host != null ? m_host.hashCode() : 0);
+ hash = 37 * hash + (m_cap != null ? m_cap.hashCode() : 0);
+ return hash;
+ }
+
+ public Capability getDeclaredCapability()
+ {
+ return m_cap;
+ }
+
+ public Resource getResource()
+ {
+ return m_host;
+ }
+
+ public String getNamespace()
+ {
+ return m_cap.getNamespace();
+ }
+
+ public Map<String, String> getDirectives()
+ {
+ return m_cap.getDirectives();
+ }
+
+ public Map<String, Object> getAttributes()
+ {
+ return m_cap.getAttributes();
+ }
+
+// TODO: RFC-112 - Need impl-specific type.
+// public List<String> getUses()
+// {
+// return m_cap.getUses();
+// }
+
+ @Override
+ public String toString()
+ {
+ if (m_host == null)
+ {
+ return getAttributes().toString();
+ }
+ if (getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ return "[" + m_host + "] "
+ + getNamespace()
+ + "; "
+ + getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ }
+ return "[" + m_host + "] " + getNamespace() + "; " + getAttributes();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedRequirement.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedRequirement.java
new file mode 100644
index 000000000..a9d66dfea
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedRequirement.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.Map;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class WrappedRequirement implements Requirement
+{
+ private final Resource m_host;
+ private final Requirement m_req;
+
+ public WrappedRequirement(Resource host, Requirement req)
+ {
+ m_host = host;
+ m_req = req;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final WrappedRequirement other = (WrappedRequirement) obj;
+ if (m_host != other.m_host && (m_host == null || !m_host.equals(other.m_host)))
+ {
+ return false;
+ }
+ if (m_req != other.m_req && (m_req == null || !m_req.equals(other.m_req)))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 7;
+ hash = 37 * hash + (m_host != null ? m_host.hashCode() : 0);
+ hash = 37 * hash + (m_req != null ? m_req.hashCode() : 0);
+ return hash;
+ }
+
+ public Requirement getDeclaredRequirement()
+ {
+ return m_req;
+ }
+
+ public Resource getResource()
+ {
+ return m_host;
+ }
+
+ public String getNamespace()
+ {
+ return m_req.getNamespace();
+ }
+
+ public Map<String, String> getDirectives()
+ {
+ return m_req.getDirectives();
+ }
+
+ public Map<String, Object> getAttributes()
+ {
+ return m_req.getAttributes();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + m_host + "] "
+ + getNamespace()
+ + "; "
+ + getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedResource.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedResource.java
new file mode 100644
index 000000000..693e8bbcd
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/WrappedResource.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.resolver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+class WrappedResource implements Resource
+{
+ private final Resource m_host;
+ private final List<Resource> m_fragments;
+ private List<Capability> m_cachedCapabilities = null;
+ private List<Requirement> m_cachedRequirements = null;
+
+ public WrappedResource(Resource host, List<Resource> fragments)
+ {
+ m_host = host;
+ m_fragments = fragments;
+ }
+
+ public Resource getDeclaredResource()
+ {
+ return m_host;
+ }
+
+ public List<Resource> getFragments()
+ {
+ return m_fragments;
+ }
+
+ public List<Capability> getCapabilities(String namespace)
+ {
+ if (m_cachedCapabilities == null)
+ {
+ List<Capability> caps = new ArrayList<Capability>();
+
+ // Wrap host capabilities.
+ for (Capability cap : m_host.getCapabilities(null))
+ {
+ caps.add(new WrappedCapability(this, cap));
+ }
+
+ // Wrap fragment capabilities.
+ if (m_fragments != null)
+ {
+ for (Resource fragment : m_fragments)
+ {
+ for (Capability cap : fragment.getCapabilities(null))
+ {
+ // Filter out identity capabilities, since they
+ // are not part of the fragment payload.
+ if (!cap.getNamespace()
+ .equals(IdentityNamespace.IDENTITY_NAMESPACE))
+ {
+ caps.add(new WrappedCapability(this, cap));
+ }
+ }
+ }
+ }
+ m_cachedCapabilities = Collections.unmodifiableList(caps);
+ }
+ return m_cachedCapabilities;
+ }
+
+ public List<Requirement> getRequirements(String namespace)
+ {
+ if (m_cachedRequirements == null)
+ {
+ List<Requirement> reqs = new ArrayList<Requirement>();
+
+ // Wrap host requirements.
+ for (Requirement req : m_host.getRequirements(null))
+ {
+ reqs.add(new WrappedRequirement(this, req));
+ }
+
+ // Wrap fragment requirements.
+ if (m_fragments != null)
+ {
+ for (Resource fragment : m_fragments)
+ {
+ for (Requirement req : fragment.getRequirements(null))
+ {
+ // Filter out host and execution environment requirements,
+ // since they are not part of the fragment payload.
+ if (!req.getNamespace().equals(HostNamespace.HOST_NAMESPACE)
+ && !req.getNamespace().equals(
+ ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE))
+ {
+ reqs.add(new WrappedRequirement(this, req));
+ }
+ }
+ }
+ }
+ m_cachedRequirements = Collections.unmodifiableList(reqs);
+ }
+ return m_cachedRequirements;
+ }
+
+ public String toString()
+ {
+ return m_host.toString();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java
index 5783d5a9e..f66a38285 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java
@@ -12,29 +12,31 @@
package org.eclipse.core.runtime.adaptor;
import java.io.*;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.*;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.*;
import org.eclipse.core.runtime.internal.adaptor.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.baseadaptor.BaseStorageHook;
-import org.eclipse.osgi.internal.profile.Profile;
+import org.eclipse.osgi.framework.util.FilePath;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.location.*;
+import org.eclipse.osgi.launch.Equinox;
import org.eclipse.osgi.service.datalocation.Location;
-import org.eclipse.osgi.service.resolver.*;
+import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.service.runnable.ApplicationLauncher;
import org.eclipse.osgi.service.runnable.StartupMonitor;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.service.startlevel.StartLevel;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.util.tracker.ServiceTracker;
/**
@@ -54,12 +56,10 @@ import org.osgi.util.tracker.ServiceTracker;
* @noextend This class is not intended to be subclassed by clients.
*/
public class EclipseStarter {
- private static FrameworkAdaptor adaptor;
private static BundleContext context;
private static boolean initialize = false;
public static boolean debug = false;
private static boolean running = false;
- private static Framework framework = null;
private static ServiceRegistration<?> defaultMonitorRegistration = null;
private static ServiceRegistration<?> appLauncherRegistration = null;
private static ServiceRegistration<?> splashStreamRegistration = null;
@@ -108,7 +108,6 @@ public class EclipseStarter {
public static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
public static final String PROP_FRAMEWORK_SHAPE = "osgi.framework.shape"; //$NON-NLS-1$ //the shape of the fwk (jar, or folder)
public static final String PROP_NOSHUTDOWN = "osgi.noShutdown"; //$NON-NLS-1$
- private static final String PROP_FORCED_RESTART = "osgi.forcedRestart"; //$NON-NLS-1$
public static final String PROP_EXITCODE = "eclipse.exitcode"; //$NON-NLS-1$
public static final String PROP_EXITDATA = "eclipse.exitdata"; //$NON-NLS-1$
@@ -122,8 +121,6 @@ public class EclipseStarter {
private static final String REFERENCE_SCHEME = "reference:"; //$NON-NLS-1$
private static final String REFERENCE_PROTOCOL = "reference"; //$NON-NLS-1$
private static final String INITIAL_LOCATION = "initial@"; //$NON-NLS-1$
- /** string containing the classname of the adaptor to be used in this framework instance */
- protected static final String DEFAULT_ADAPTOR_CLASS = "org.eclipse.osgi.baseadaptor.BaseAdaptor"; //$NON-NLS-1$
private static final int DEFAULT_INITIAL_STARTLEVEL = 6; // default value for legacy purposes
private static final String DEFAULT_BUNDLES_STARTLEVEL = "4"; //$NON-NLS-1$
@@ -136,20 +133,68 @@ public class EclipseStarter {
private static ConsoleManager consoleMgr = null;
+ private static Map<String, String> configuration = null;
+ private static Framework framework = null;
+ private static EquinoxConfiguration equinoxConfig;
+ private static String[] allArgs = null;
+ private static String[] frameworkArgs = null;
+ private static String[] appArgs = null;
+
+ private synchronized static String getProperty(String key) {
+ if (equinoxConfig != null) {
+ return equinoxConfig.getProperty(key);
+ }
+ return getConfiguration().get(key);
+ }
+
+ private synchronized static String getProperty(String key, String dft) {
+ if (equinoxConfig != null) {
+ return equinoxConfig.getConfiguration(key, dft);
+ }
+ String result = getConfiguration().get(key);
+ return result == null ? dft : result;
+ }
+
+ private synchronized static Object setProperty(String key, String value) {
+ if (equinoxConfig != null) {
+ return equinoxConfig.setProperty(key, value);
+ }
+ return getConfiguration().put(key, value);
+ }
+
+ private synchronized static Object clearProperty(String key) {
+ if (equinoxConfig != null) {
+ return equinoxConfig.clearConfiguration(key);
+ }
+ return getConfiguration().remove(key);
+ }
+
+ private synchronized static Map<String, String> getConfiguration() {
+ if (configuration == null) {
+ configuration = new HashMap<String, String>();
+ // TODO hack
+ String useSystemProperties = System.getProperty(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES, "true"); //$NON-NLS-1$
+ if ("true".equals(useSystemProperties)) { //$NON-NLS-1$
+ configuration.put(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES, "true"); //$NON-NLS-1$
+ }
+ }
+ return configuration;
+ }
+
/**
* This is the main to start osgi.
* It only works when the framework is being jared as a single jar
*/
public static void main(String[] args) throws Exception {
- if (FrameworkProperties.getProperty("eclipse.startTime") == null) //$NON-NLS-1$
- FrameworkProperties.setProperty("eclipse.startTime", Long.toString(System.currentTimeMillis())); //$NON-NLS-1$
- if (FrameworkProperties.getProperty(PROP_NOSHUTDOWN) == null)
- FrameworkProperties.setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
+ if (getProperty("eclipse.startTime") == null) //$NON-NLS-1$
+ setProperty("eclipse.startTime", Long.toString(System.currentTimeMillis())); //$NON-NLS-1$
+ if (getProperty(PROP_NOSHUTDOWN) == null)
+ setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
// set the compatibility boot delegation flag to false to get "standard" OSGi behavior WRT boot delegation (bug 178477)
- if (FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION) == null)
- FrameworkProperties.setProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "false"); //$NON-NLS-1$
+ if (getProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION) == null)
+ setProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION, "false"); //$NON-NLS-1$
Object result = run(args, null);
- if (result instanceof Integer && !Boolean.valueOf(FrameworkProperties.getProperty(PROP_NOSHUTDOWN)).booleanValue())
+ if (result instanceof Integer && !Boolean.valueOf(getProperty(PROP_NOSHUTDOWN)).booleanValue())
System.exit(((Integer) result).intValue());
}
@@ -167,15 +212,13 @@ public class EclipseStarter {
* @throws Exception if anything goes wrong
*/
public static Object run(String[] args, Runnable endSplashHandler) throws Exception {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logEnter("EclipseStarter.run()", null); //$NON-NLS-1$
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING);
boolean startupFailed = true;
try {
startup(args, endSplashHandler);
startupFailed = false;
- if (Boolean.valueOf(FrameworkProperties.getProperty(PROP_IGNOREAPP)).booleanValue() || isForcedRestart())
+ if (Boolean.valueOf(getProperty(PROP_IGNOREAPP)).booleanValue() || isForcedRestart())
return null;
return run(null);
} catch (Throwable e) {
@@ -183,7 +226,7 @@ public class EclipseStarter {
if (endSplashHandler != null)
endSplashHandler.run();
// may use startupFailed to understand where the error happened
- FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, startupFailed ? EclipseAdaptorMsg.ECLIPSE_STARTUP_STARTUP_ERROR : EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null);
+ FrameworkLogEntry logEntry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, startupFailed ? EclipseAdaptorMsg.ECLIPSE_STARTUP_STARTUP_ERROR : EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
@@ -194,30 +237,22 @@ public class EclipseStarter {
// The application typically sets the exit code however the framework can request that
// it be re-started. We need to check for this and potentially override the exit code.
if (isForcedRestart())
- FrameworkProperties.setProperty(PROP_EXITCODE, "23"); //$NON-NLS-1$
- if (!Boolean.valueOf(FrameworkProperties.getProperty(PROP_NOSHUTDOWN)).booleanValue())
+ setProperty(PROP_EXITCODE, "23"); //$NON-NLS-1$
+ if (!Boolean.valueOf(getProperty(PROP_NOSHUTDOWN)).booleanValue())
shutdown();
} catch (Throwable e) {
- FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_SHUTDOWN_ERROR, 1, e, null);
+ FrameworkLogEntry logEntry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_SHUTDOWN_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
// TODO desperate measure - ideally, we should write this to disk (a la Main.log)
e.printStackTrace();
}
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logExit("EclipseStarter.run()"); //$NON-NLS-1$
- if (Profile.PROFILE) {
- String report = Profile.getProfileLog();
- // avoiding writing to the console if there is nothing to print
- if (report != null && report.length() > 0)
- System.out.println(report);
- }
}
// we only get here if an error happened
- if (FrameworkProperties.getProperty(PROP_EXITCODE) == null) {
- FrameworkProperties.setProperty(PROP_EXITCODE, "13"); //$NON-NLS-1$
- FrameworkProperties.setProperty(PROP_EXITDATA, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_CHECK_LOG, log == null ? null : log.getFile().getPath()));
+ if (getProperty(PROP_EXITCODE) == null) {
+ setProperty(PROP_EXITCODE, "13"); //$NON-NLS-1$
+ setProperty(PROP_EXITDATA, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_CHECK_LOG, log == null ? null : log.getFile().getPath()));
}
return null;
}
@@ -242,53 +277,41 @@ public class EclipseStarter {
* @throws Exception if anything goes wrong
*/
public static BundleContext startup(String[] args, Runnable endSplashHandler) throws Exception {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logEnter("EclipseStarter.startup()", null); //$NON-NLS-1$
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING);
- FrameworkProperties.initializeProperties();
processCommandLine(args);
- LocationManager.initializeLocations();
- loadConfigurationInfo();
finalizeProperties();
- if (Profile.PROFILE)
- Profile.initProps(); // catch any Profile properties set in eclipse.properties...
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("EclipseStarter.startup()", "props inited"); //$NON-NLS-1$ //$NON-NLS-2$
- adaptor = createAdaptor();
- log = adaptor.getFrameworkLog();
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("EclipseStarter.startup()", "adapter created"); //$NON-NLS-1$ //$NON-NLS-2$
- framework = new Framework(adaptor);
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("EclipseStarter.startup()", "OSGi created"); //$NON-NLS-1$ //$NON-NLS-2$
- context = framework.getBundle(0).getBundleContext();
+ framework = new Equinox(configuration);
+ framework.init();
+ context = framework.getBundleContext();
+ ServiceReference<FrameworkLog> logRef = context.getServiceReference(FrameworkLog.class);
+ log = context.getService(logRef);
+ ServiceReference<EnvironmentInfo> configRef = context.getServiceReference(EnvironmentInfo.class);
+ equinoxConfig = (EquinoxConfiguration) context.getService(configRef);
+
+ equinoxConfig.setAllArgs(allArgs);
+ equinoxConfig.setFrameworkArgs(frameworkArgs);
+ equinoxConfig.setAppArgs(appArgs);
+
registerFrameworkShutdownHandlers();
publishSplashScreen(endSplashHandler);
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("EclipseStarter.startup()", "osgi launched"); //$NON-NLS-1$ //$NON-NLS-2$
- consoleMgr = ConsoleManager.startConsole(framework);
- if (Profile.PROFILE && Profile.STARTUP) {
- Profile.logTime("EclipseStarter.startup()", "console started"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- framework.launch();
- // save the cached timestamp before loading basic bundles; this is needed so we can do a proper timestamp check when logging resolver errors
- long stateStamp = adaptor.getState().getTimeStamp();
+ consoleMgr = ConsoleManager.startConsole(context, equinoxConfig);
+
Bundle[] startBundles = loadBasicBundles();
- if (startBundles == null || ("true".equals(FrameworkProperties.getProperty(PROP_REFRESH_BUNDLES)) && refreshPackages(getCurrentBundles(false)))) { //$NON-NLS-1$
+ if (startBundles == null || ("true".equals(getProperty(PROP_REFRESH_BUNDLES)) && refreshPackages(getCurrentBundles(false)))) { //$NON-NLS-1$
waitForShutdown();
return context; // cannot continue; loadBasicBundles caused refreshPackages to shutdown the framework
}
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("EclipseStarter.startup()", "loading basic bundles"); //$NON-NLS-1$ //$NON-NLS-2$
+ framework.start();
+ if (isForcedRestart()) {
+ return context;
+ }
// set the framework start level to the ultimate value. This will actually start things
// running if they are persistently active.
setStartLevel(getStartLevel());
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("EclipseStarter.startup()", "StartLevel set"); //$NON-NLS-1$ //$NON-NLS-2$
// they should all be active by this time
ensureBundlesActive(startBundles);
@@ -296,21 +319,16 @@ public class EclipseStarter {
try {
consoleMgr.checkForConsoleBundle();
} catch (BundleException e) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null);
+ FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null);
log.log(entry);
}
- if (debug || FrameworkProperties.getProperty(PROP_DEV) != null)
- // only spend time showing unresolved bundles in dev/debug mode and the state has changed
- if (stateStamp != adaptor.getState().getTimeStamp())
- logUnresolvedBundles(context.getBundles());
+ // TODO should log unresolved bundles if in debug or dev mode
running = true;
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logExit("EclipseStarter.startup()"); //$NON-NLS-1$
return context;
}
private static int getStartLevel() {
- String level = FrameworkProperties.getProperty(PROP_INITIAL_STARTLEVEL);
+ String level = getProperty(PROP_INITIAL_STARTLEVEL);
if (level != null)
try {
return Integer.parseInt(level);
@@ -334,8 +352,6 @@ public class EclipseStarter {
* @throws Exception if anything goes wrong
*/
public static Object run(Object argument) throws Exception {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logEnter("EclipseStarter.run(Object)()", null); //$NON-NLS-1$
if (!running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_NOT_RUNNING);
// if we are just initializing, do not run the application just return.
@@ -343,9 +359,9 @@ public class EclipseStarter {
return new Integer(0);
try {
if (appLauncher == null) {
- boolean launchDefault = Boolean.valueOf(FrameworkProperties.getProperty(PROP_APPLICATION_LAUNCHDEFAULT, "true")).booleanValue(); //$NON-NLS-1$
+ boolean launchDefault = Boolean.valueOf(getProperty(PROP_APPLICATION_LAUNCHDEFAULT, "true")).booleanValue(); //$NON-NLS-1$
// create the ApplicationLauncher and register it as a service
- appLauncher = new EclipseAppLauncher(context, Boolean.valueOf(FrameworkProperties.getProperty(PROP_ALLOW_APPRELAUNCH)).booleanValue(), launchDefault, log);
+ appLauncher = new EclipseAppLauncher(context, Boolean.valueOf(getProperty(PROP_ALLOW_APPRELAUNCH)).booleanValue(), launchDefault, log, equinoxConfig);
appLauncherRegistration = context.registerService(ApplicationLauncher.class.getName(), appLauncher, null);
// must start the launcher AFTER service restration because this method
// blocks and runs the application on the current thread. This method
@@ -354,8 +370,9 @@ public class EclipseStarter {
}
return appLauncher.reStart(argument);
} catch (Exception e) {
- if (log != null && context != null) // context can be null if OSGi failed to launch (bug 151413)
- logUnresolvedBundles(context.getBundles());
+ if (log != null && context != null) { // context can be null if OSGi failed to launch (bug 151413)
+ // TODO Should log unresolved bundles here
+ }
throw e;
}
}
@@ -396,115 +413,31 @@ public class EclipseStarter {
consoleMgr.stopConsole();
consoleMgr = null;
}
- framework.close();
+ framework.stop();
+ framework.waitForStop(0);
framework = null;
+ configuration = null;
+ equinoxConfig = null;
context = null;
running = false;
}
private static void ensureBundlesActive(Bundle[] bundles) {
- ServiceTracker<StartLevel, StartLevel> tracker = null;
- try {
- for (int i = 0; i < bundles.length; i++) {
- if (bundles[i].getState() != Bundle.ACTIVE) {
- if (bundles[i].getState() == Bundle.INSTALLED) {
- // Log that the bundle is not resolved
- log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundles[i].getLocation()), 0, null, null));
- continue;
- }
- // check that the startlevel allows the bundle to be active (111550)
- if (tracker == null) {
- tracker = new ServiceTracker<StartLevel, StartLevel>(context, StartLevel.class.getName(), null);
- tracker.open();
- }
- StartLevel sl = tracker.getService();
- if (sl != null && (sl.getBundleStartLevel(bundles[i]) <= sl.getStartLevel())) {
- log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_ACTIVE, bundles[i]), 0, null, null));
- }
- }
- }
- } finally {
- if (tracker != null)
- tracker.close();
- }
- }
-
- private static void logUnresolvedBundles(Bundle[] bundles) {
- State state = adaptor.getState();
- FrameworkLog logService = adaptor.getFrameworkLog();
- StateHelper stateHelper = adaptor.getPlatformAdmin().getStateHelper();
-
- // first lets look for missing leaf constraints (bug 114120)
- VersionConstraint[] leafConstraints = stateHelper.getUnsatisfiedLeaves(state.getBundles());
- // hash the missing leaf constraints by the declaring bundles
- Map<BundleDescription, List<VersionConstraint>> missing = new HashMap<BundleDescription, List<VersionConstraint>>();
- for (int i = 0; i < leafConstraints.length; i++) {
- // only include non-optional and non-dynamic constraint leafs
- if (leafConstraints[i] instanceof BundleSpecification && ((BundleSpecification) leafConstraints[i]).isOptional())
- continue;
- if (leafConstraints[i] instanceof ImportPackageSpecification) {
- if (ImportPackageSpecification.RESOLUTION_OPTIONAL.equals(((ImportPackageSpecification) leafConstraints[i]).getDirective(Constants.RESOLUTION_DIRECTIVE)))
- continue;
- if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(((ImportPackageSpecification) leafConstraints[i]).getDirective(Constants.RESOLUTION_DIRECTIVE)))
- continue;
- }
- BundleDescription bundle = leafConstraints[i].getBundle();
- List<VersionConstraint> constraints = missing.get(bundle);
- if (constraints == null) {
- constraints = new ArrayList<VersionConstraint>();
- missing.put(bundle, constraints);
- }
- constraints.add(leafConstraints[i]);
- }
-
- // found some bundles with missing leaf constraints; log them first
- if (missing.size() > 0) {
- FrameworkLogEntry[] rootChildren = new FrameworkLogEntry[missing.size()];
- int rootIndex = 0;
- for (Iterator<BundleDescription> iter = missing.keySet().iterator(); iter.hasNext(); rootIndex++) {
- BundleDescription description = iter.next();
- String symbolicName = description.getSymbolicName() == null ? FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME : description.getSymbolicName();
- String generalMessage = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, description.getLocation());
- List<VersionConstraint> constraints = missing.get(description);
- FrameworkLogEntry[] logChildren = new FrameworkLogEntry[constraints.size()];
- for (int i = 0; i < logChildren.length; i++)
- logChildren[i] = new FrameworkLogEntry(symbolicName, FrameworkLogEntry.WARNING, 0, MessageHelper.getResolutionFailureMessage(constraints.get(i)), 0, null, null);
- rootChildren[rootIndex] = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, generalMessage, 0, null, logChildren);
- }
- logService.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_ROOTS_NOT_RESOLVED, 0, null, rootChildren));
- }
-
- // There may be some bundles unresolved for other reasons, causing the system to be unresolved
- // log all unresolved constraints now
- List<FrameworkLogEntry> allChildren = new ArrayList<FrameworkLogEntry>();
- for (int i = 0; i < bundles.length; i++)
- if (bundles[i].getState() == Bundle.INSTALLED) {
- String symbolicName = bundles[i].getSymbolicName() == null ? FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME : bundles[i].getSymbolicName();
- String generalMessage = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundles[i]);
- BundleDescription description = state.getBundle(bundles[i].getBundleId());
- // for some reason, the state does not know about that bundle
- if (description == null)
+ for (int i = 0; i < bundles.length; i++) {
+ if (bundles[i].getState() != Bundle.ACTIVE) {
+ if (bundles[i].getState() == Bundle.INSTALLED) {
+ // Log that the bundle is not resolved
+ log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundles[i].getLocation()), 0, null, null));
continue;
- FrameworkLogEntry[] logChildren = null;
- VersionConstraint[] unsatisfied = stateHelper.getUnsatisfiedConstraints(description);
- if (unsatisfied.length > 0) {
- // the bundle wasn't resolved due to some of its constraints were unsatisfiable
- logChildren = new FrameworkLogEntry[unsatisfied.length];
- for (int j = 0; j < unsatisfied.length; j++)
- logChildren[j] = new FrameworkLogEntry(symbolicName, FrameworkLogEntry.WARNING, 0, MessageHelper.getResolutionFailureMessage(unsatisfied[j]), 0, null, null);
- } else {
- ResolverError[] resolverErrors = state.getResolverErrors(description);
- if (resolverErrors.length > 0) {
- logChildren = new FrameworkLogEntry[resolverErrors.length];
- for (int j = 0; j < resolverErrors.length; j++)
- logChildren[j] = new FrameworkLogEntry(symbolicName, FrameworkLogEntry.WARNING, 0, resolverErrors[j].toString(), 0, null, null);
- }
}
-
- allChildren.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, generalMessage, 0, null, logChildren));
+ // check that the startlevel allows the bundle to be active (111550)
+ FrameworkStartLevel fwStartLevel = context.getBundle().adapt(FrameworkStartLevel.class);
+ BundleStartLevel bundleStartLevel = bundles[i].adapt(BundleStartLevel.class);
+ if (fwStartLevel != null && (bundleStartLevel.getStartLevel() <= fwStartLevel.getStartLevel())) {
+ log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_ACTIVE, bundles[i]), 0, null, null));
+ }
}
- if (allChildren.size() > 0)
- logService.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_ALL_NOT_RESOLVED, 0, null, allChildren.toArray(new FrameworkLogEntry[allChildren.size()])));
+ }
}
private static void publishSplashScreen(final Runnable endSplashHandler) {
@@ -526,7 +459,7 @@ public class EclipseStarter {
try {
Dictionary<String, Object> monitorProps = new Hashtable<String, Object>();
monitorProps.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE));
- defaultMonitorRegistration = context.registerService(StartupMonitor.class.getName(), new DefaultStartupMonitor(endSplashHandler), monitorProps);
+ defaultMonitorRegistration = context.registerService(StartupMonitor.class.getName(), new DefaultStartupMonitor(endSplashHandler, equinoxConfig), monitorProps);
} catch (IllegalStateException e) {
//splash handler did not provide the necessary methods, ignore it
}
@@ -598,11 +531,11 @@ public class EclipseStarter {
*/
private static Bundle[] loadBasicBundles() {
long startTime = System.currentTimeMillis();
- String osgiBundles = FrameworkProperties.getProperty(PROP_BUNDLES);
- String osgiExtensions = FrameworkProperties.getProperty(PROP_EXTENSIONS);
+ String osgiBundles = getProperty(PROP_BUNDLES);
+ String osgiExtensions = getProperty(PROP_EXTENSIONS);
if (osgiExtensions != null && osgiExtensions.length() > 0) {
osgiBundles = osgiExtensions + ',' + osgiBundles;
- FrameworkProperties.setProperty(PROP_BUNDLES, osgiBundles);
+ setProperty(PROP_BUNDLES, osgiBundles);
}
String[] installEntries = getArrayFromList(osgiBundles, ","); //$NON-NLS-1$
// get the initial bundle list from the installEntries
@@ -638,7 +571,7 @@ public class EclipseStarter {
private static InitialBundle[] getInitialBundles(String[] installEntries) {
searchCandidates.clear();
List<InitialBundle> result = new ArrayList<InitialBundle>(installEntries.length);
- int defaultStartLevel = Integer.parseInt(FrameworkProperties.getProperty(PROP_BUNDLES_STARTLEVEL, DEFAULT_BUNDLES_STARTLEVEL));
+ int defaultStartLevel = Integer.parseInt(getProperty(PROP_BUNDLES_STARTLEVEL, DEFAULT_BUNDLES_STARTLEVEL));
String syspath = getSysPath();
// should canonicalize the syspath.
try {
@@ -646,6 +579,16 @@ public class EclipseStarter {
} catch (IOException ioe) {
// do nothing
}
+ Collection<ServiceReference<Location>> installLocRef;
+ try {
+ installLocRef = context.getServiceReferences(Location.class, Location.INSTALL_FILTER);
+ } catch (InvalidSyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ Location installLocation = installLocRef == null ? null : context.getService(installLocRef.iterator().next());
+ if (installLocation == null) {
+ throw new IllegalStateException("No install location found.");
+ }
for (int i = 0; i < installEntries.length; i++) {
String name = installEntries[i];
int level = defaultStartLevel;
@@ -671,16 +614,16 @@ public class EclipseStarter {
try {
URL location = searchForBundle(name, syspath);
if (location == null) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_BUNDLE_NOT_FOUND, installEntries[i]), 0, null, null);
+ FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_BUNDLE_NOT_FOUND, installEntries[i]), 0, null, null);
log.log(entry);
// skip this entry
continue;
}
- location = makeRelative(LocationManager.getInstallLocation().getURL(), location);
+ location = makeRelative(installLocation.getURL(), location);
String locationString = INITIAL_LOCATION + location.toExternalForm();
result.add(new InitialBundle(locationString, location, level, start));
} catch (IOException e) {
- log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
+ log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
}
}
return result.toArray(new InitialBundle[result.size()]);
@@ -688,20 +631,13 @@ public class EclipseStarter {
// returns true if the refreshPackages operation caused the framework to shutdown
private static boolean refreshPackages(Bundle[] bundles) {
- ServiceReference<?> packageAdminRef = context.getServiceReference(PackageAdmin.class.getName());
- PackageAdmin packageAdmin = null;
- if (packageAdminRef != null)
- packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
- if (packageAdmin == null)
+ FrameworkWiring frameworkWiring = context.getBundle().adapt(FrameworkWiring.class);
+ if (frameworkWiring == null)
return false;
- // TODO this is such a hack it is silly. There are still cases for race conditions etc
- // but this should allow for some progress...
- final Semaphore semaphore = new Semaphore(0);
+ Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.PACKAGES_REFRESHED);
- context.addFrameworkListener(listener);
context.addBundleListener(listener);
- packageAdmin.refreshPackages(bundles);
- context.ungetService(packageAdminRef);
+ frameworkWiring.refreshBundles(Arrays.asList(bundles), listener);
updateSplash(semaphore, listener);
if (isForcedRestart())
return true;
@@ -709,40 +645,20 @@ public class EclipseStarter {
}
private static void waitForShutdown() {
- if (!isForcedRestart())
- return;
// wait for the system bundle to stop
- Bundle systemBundle = framework.getBundle(0);
- int i = 0;
- while (i < 5000 && (systemBundle.getState() & (Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING)) != 0) {
- i += 200;
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- break;
- }
+ try {
+ framework.waitForStop(0);
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ throw new RuntimeException(e);
}
}
- /**
- * Creates and returns the adaptor
- *
- * @return a FrameworkAdaptor object
- */
- private static FrameworkAdaptor createAdaptor() throws Exception {
- String adaptorClassName = FrameworkProperties.getProperty(PROP_ADAPTOR, DEFAULT_ADAPTOR_CLASS);
- Class<?> adaptorClass = Class.forName(adaptorClassName);
- Class<?>[] constructorArgs = new Class[] {String[].class};
- Constructor<?> constructor = adaptorClass.getConstructor(constructorArgs);
- return (FrameworkAdaptor) constructor.newInstance(new Object[] {new String[0]});
- }
-
- private static String[] processCommandLine(String[] args) throws Exception {
- EclipseEnvironmentInfo.setAllArgs(args);
+ private static void processCommandLine(String[] args) throws Exception {
+ allArgs = args;
if (args.length == 0) {
- EclipseEnvironmentInfo.setFrameworkArgs(args);
- EclipseEnvironmentInfo.setAllArgs(args);
- return args;
+ frameworkArgs = args;
+ return;
}
int[] configArgs = new int[args.length];
configArgs[0] = -1; // need to initialize the first element to something that could not be an index.
@@ -756,7 +672,7 @@ public class EclipseStarter {
// simply enable debug. Otherwise, assume that that the following arg is
// actually the filename of an options file. This will be processed below.
if (args[i].equalsIgnoreCase(DEBUG) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
- FrameworkProperties.setProperty(PROP_DEBUG, ""); //$NON-NLS-1$
+ setProperty(PROP_DEBUG, ""); //$NON-NLS-1$
debug = true;
found = true;
}
@@ -766,7 +682,7 @@ public class EclipseStarter {
// simply enable development mode. Otherwise, assume that that the following arg is
// actually some additional development time class path entries. This will be processed below.
if (args[i].equalsIgnoreCase(DEV) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
- FrameworkProperties.setProperty(PROP_DEV, ""); //$NON-NLS-1$
+ setProperty(PROP_DEV, ""); //$NON-NLS-1$
found = true;
}
@@ -778,24 +694,24 @@ public class EclipseStarter {
// look for the clean flag.
if (args[i].equalsIgnoreCase(CLEAN)) {
- FrameworkProperties.setProperty(PROP_CLEAN, "true"); //$NON-NLS-1$
+ setProperty(PROP_CLEAN, "true"); //$NON-NLS-1$
found = true;
}
// look for the consoleLog flag
if (args[i].equalsIgnoreCase(CONSOLE_LOG)) {
- FrameworkProperties.setProperty(PROP_CONSOLE_LOG, "true"); //$NON-NLS-1$
+ setProperty(PROP_CONSOLE_LOG, "true"); //$NON-NLS-1$
found = true;
}
// look for the console with no port.
if (args[i].equalsIgnoreCase(CONSOLE) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
- FrameworkProperties.setProperty(PROP_CONSOLE, ""); //$NON-NLS-1$
+ setProperty(PROP_CONSOLE, ""); //$NON-NLS-1$
found = true;
}
if (args[i].equalsIgnoreCase(NOEXIT)) {
- FrameworkProperties.setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
+ setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
found = true;
}
@@ -812,73 +728,73 @@ public class EclipseStarter {
// look for the console and port.
if (args[i - 1].equalsIgnoreCase(CONSOLE)) {
- FrameworkProperties.setProperty(PROP_CONSOLE, arg);
+ setProperty(PROP_CONSOLE, arg);
found = true;
}
// look for the configuration location .
if (args[i - 1].equalsIgnoreCase(CONFIGURATION)) {
- FrameworkProperties.setProperty(LocationManager.PROP_CONFIG_AREA, arg);
+ setProperty(EquinoxLocations.PROP_CONFIG_AREA, arg);
found = true;
}
// look for the data location for this instance.
if (args[i - 1].equalsIgnoreCase(DATA)) {
- FrameworkProperties.setProperty(LocationManager.PROP_INSTANCE_AREA, arg);
+ setProperty(EquinoxLocations.PROP_INSTANCE_AREA, arg);
found = true;
}
// look for the user location for this instance.
if (args[i - 1].equalsIgnoreCase(USER)) {
- FrameworkProperties.setProperty(LocationManager.PROP_USER_AREA, arg);
+ setProperty(EquinoxLocations.PROP_USER_AREA, arg);
found = true;
}
// look for the launcher location
if (args[i - 1].equalsIgnoreCase(LAUNCHER)) {
- FrameworkProperties.setProperty(LocationManager.PROP_LAUNCHER, arg);
+ setProperty(EquinoxLocations.PROP_LAUNCHER, arg);
found = true;
}
// look for the development mode and class path entries.
if (args[i - 1].equalsIgnoreCase(DEV)) {
- FrameworkProperties.setProperty(PROP_DEV, arg);
+ setProperty(PROP_DEV, arg);
found = true;
}
// look for the debug mode and option file location.
if (args[i - 1].equalsIgnoreCase(DEBUG)) {
- FrameworkProperties.setProperty(PROP_DEBUG, arg);
+ setProperty(PROP_DEBUG, arg);
debug = true;
found = true;
}
// look for the window system.
if (args[i - 1].equalsIgnoreCase(WS)) {
- FrameworkProperties.setProperty(PROP_WS, arg);
+ setProperty(PROP_WS, arg);
found = true;
}
// look for the operating system
if (args[i - 1].equalsIgnoreCase(OS)) {
- FrameworkProperties.setProperty(PROP_OS, arg);
+ setProperty(PROP_OS, arg);
found = true;
}
// look for the system architecture
if (args[i - 1].equalsIgnoreCase(ARCH)) {
- FrameworkProperties.setProperty(PROP_ARCH, arg);
+ setProperty(PROP_ARCH, arg);
found = true;
}
// look for the nationality/language
if (args[i - 1].equalsIgnoreCase(NL)) {
- FrameworkProperties.setProperty(PROP_NL, arg);
+ setProperty(PROP_NL, arg);
found = true;
}
// look for the locale extensions
if (args[i - 1].equalsIgnoreCase(NL_EXTENSIONS)) {
- FrameworkProperties.setProperty(PROP_NL_EXTENSIONS, arg);
+ setProperty(PROP_NL_EXTENSIONS, arg);
found = true;
}
@@ -891,12 +807,13 @@ public class EclipseStarter {
// remove all the arguments consumed by this argument parsing
if (configArgIndex == 0) {
- EclipseEnvironmentInfo.setFrameworkArgs(new String[0]);
- EclipseEnvironmentInfo.setAppArgs(args);
- return args;
+ frameworkArgs = new String[0];
+ appArgs = args;
+ equinoxConfig.setAppArgs(args);
+ return;
}
- String[] appArgs = new String[args.length - configArgIndex];
- String[] frameworkArgs = new String[configArgIndex];
+ appArgs = new String[args.length - configArgIndex];
+ frameworkArgs = new String[configArgIndex];
configArgIndex = 0;
int j = 0;
int k = 0;
@@ -907,9 +824,7 @@ public class EclipseStarter {
} else
appArgs[j++] = args[i];
}
- EclipseEnvironmentInfo.setFrameworkArgs(frameworkArgs);
- EclipseEnvironmentInfo.setAppArgs(appArgs);
- return appArgs;
+ return;
}
/**
@@ -923,10 +838,10 @@ public class EclipseStarter {
}
protected static String getSysPath() {
- String result = FrameworkProperties.getProperty(PROP_SYSPATH);
+ String result = getProperty(PROP_SYSPATH);
if (result != null)
return result;
- result = getSysPathFromURL(FrameworkProperties.getProperty(PROP_FRAMEWORK));
+ result = getSysPathFromURL(getProperty(PROP_FRAMEWORK));
if (result == null)
result = getSysPathFromCodeSource();
if (result == null)
@@ -936,7 +851,7 @@ public class EclipseStarter {
chars[0] = Character.toLowerCase(chars[0]);
result = new String(chars);
}
- FrameworkProperties.setProperty(PROP_SYSPATH, result);
+ setProperty(PROP_SYSPATH, result);
return result;
}
@@ -965,7 +880,7 @@ public class EclipseStarter {
String result = url.getFile();
if (result.endsWith(".jar")) { //$NON-NLS-1$
result = result.substring(0, result.lastIndexOf('/'));
- if ("folder".equals(FrameworkProperties.getProperty(PROP_FRAMEWORK_SHAPE))) //$NON-NLS-1$
+ if ("folder".equals(getProperty(PROP_FRAMEWORK_SHAPE))) //$NON-NLS-1$
result = result.substring(0, result.lastIndexOf('/'));
} else {
if (result.endsWith("/")) //$NON-NLS-1$
@@ -1013,58 +928,50 @@ public class EclipseStarter {
curInitBundles[i].uninstall();
toRefresh.add(curInitBundles[i]);
} catch (BundleException e) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_UNINSTALL, curInitBundles[i].getLocation()), 0, e, null);
+ FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_UNINSTALL, curInitBundles[i].getLocation()), 0, e, null);
log.log(entry);
}
}
}
private static void installBundles(InitialBundle[] initialBundles, Bundle[] curInitBundles, List<Bundle> startBundles, List<Bundle> lazyActivationBundles, List<Bundle> toRefresh) {
- ServiceReference<?> reference = context.getServiceReference(StartLevel.class.getName());
- StartLevel startService = null;
- if (reference != null)
- startService = (StartLevel) context.getService(reference);
- try {
- for (int i = 0; i < initialBundles.length; i++) {
- Bundle osgiBundle = getBundleByLocation(initialBundles[i].locationString, curInitBundles);
- try {
- // don't need to install if it is already installed
- if (osgiBundle == null) {
- InputStream in = initialBundles[i].location.openStream();
- try {
- osgiBundle = context.installBundle(initialBundles[i].locationString, in);
- } catch (BundleException e) {
- StatusException status = e instanceof StatusException ? (StatusException) e : null;
- if (status != null && status.getStatusCode() == StatusException.CODE_OK && status.getStatus() instanceof Bundle) {
- osgiBundle = (Bundle) status.getStatus();
- } else
- throw e;
+ for (int i = 0; i < initialBundles.length; i++) {
+ Bundle osgiBundle = getBundleByLocation(initialBundles[i].locationString, curInitBundles);
+ try {
+ // don't need to install if it is already installed
+ if (osgiBundle == null) {
+ InputStream in = initialBundles[i].location.openStream();
+ try {
+ osgiBundle = context.installBundle(initialBundles[i].locationString, in);
+ } catch (BundleException e) {
+ if (e.getType() == BundleException.DUPLICATE_BUNDLE_ERROR) {
+ continue;
+ // TODO should attempt to lookup the existing bundle
}
- // only check for lazy activation header if this is a newly installed bundle and is not marked for persistent start
- if (!initialBundles[i].start && hasLazyActivationPolicy(osgiBundle))
- lazyActivationBundles.add(osgiBundle);
+ throw e;
}
- // always set the startlevel incase it has changed (bug 111549)
- // this is a no-op if the level is the same as previous launch.
- if ((osgiBundle.getState() & Bundle.UNINSTALLED) == 0 && initialBundles[i].level >= 0 && startService != null)
- startService.setBundleStartLevel(osgiBundle, initialBundles[i].level);
- // if this bundle is supposed to be started then add it to the start list
- if (initialBundles[i].start)
- startBundles.add(osgiBundle);
- // include basic bundles in case they were not resolved before
- if ((osgiBundle.getState() & Bundle.INSTALLED) != 0)
- toRefresh.add(osgiBundle);
- } catch (BundleException e) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundles[i].location), 0, e, null);
- log.log(entry);
- } catch (IOException e) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundles[i].location), 0, e, null);
- log.log(entry);
+ // only check for lazy activation header if this is a newly installed bundle and is not marked for persistent start
+ if (!initialBundles[i].start && hasLazyActivationPolicy(osgiBundle))
+ lazyActivationBundles.add(osgiBundle);
}
+ // always set the startlevel incase it has changed (bug 111549)
+ // this is a no-op if the level is the same as previous launch.
+ if ((osgiBundle.getState() & Bundle.UNINSTALLED) == 0 && initialBundles[i].level >= 0) {
+ osgiBundle.adapt(BundleStartLevel.class).setStartLevel(initialBundles[i].level);
+ }
+ // if this bundle is supposed to be started then add it to the start list
+ if (initialBundles[i].start)
+ startBundles.add(osgiBundle);
+ // include basic bundles in case they were not resolved before
+ if ((osgiBundle.getState() & Bundle.INSTALLED) != 0)
+ toRefresh.add(osgiBundle);
+ } catch (BundleException e) {
+ FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundles[i].location), 0, e, null);
+ log.log(entry);
+ } catch (IOException e) {
+ FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundles[i].location), 0, e, null);
+ log.log(entry);
}
- } finally {
- if (reference != null)
- context.ungetService(reference);
}
}
@@ -1088,10 +995,10 @@ public class EclipseStarter {
}
} else {
// check for Eclipse specific lazy start headers "Eclipse-LazyStart" and "Eclipse-AutoStart"
- String eclipseLazyStart = headers.get(Constants.ECLIPSE_LAZYSTART);
+ String eclipseLazyStart = headers.get(EquinoxModuleDataNamespace.LAZYSTART_HEADER);
if (eclipseLazyStart == null)
- eclipseLazyStart = headers.get(Constants.ECLIPSE_AUTOSTART);
- ManifestElement[] elements = ManifestElement.parseHeader(Constants.ECLIPSE_LAZYSTART, eclipseLazyStart);
+ eclipseLazyStart = headers.get(EquinoxModuleDataNamespace.AUTOSTART_HEADER);
+ ManifestElement[] elements = ManifestElement.parseHeader(EquinoxModuleDataNamespace.AUTOSTART_HEADER, eclipseLazyStart);
if (elements != null && elements.length > 0) {
// if the value is true then it is lazy activated
if ("true".equals(elements[0].getValue())) //$NON-NLS-1$
@@ -1120,60 +1027,12 @@ public class EclipseStarter {
} catch (BundleException e) {
if ((bundle.getState() & Bundle.RESOLVED) != 0) {
// only log errors if the bundle is resolved
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_START, bundle.getLocation()), 0, e, null);
+ FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_START, bundle.getLocation()), 0, e, null);
log.log(entry);
}
}
}
- private static void loadConfigurationInfo() {
- Location configArea = LocationManager.getConfigurationLocation();
- if (configArea == null)
- return;
-
- URL location = null;
- try {
- location = new URL(configArea.getURL().toExternalForm() + LocationManager.CONFIG_FILE);
- } catch (MalformedURLException e) {
- // its ok. This should never happen
- }
- mergeProperties(FrameworkProperties.getProperties(), loadProperties(location));
- }
-
- private static Properties loadProperties(URL location) {
- Properties result = new Properties();
- if (location == null)
- return result;
- try {
- InputStream in = location.openStream();
- try {
- result.load(in);
- } finally {
- in.close();
- }
- } catch (IOException e) {
- // its ok if there is no file. We'll just use the defaults for everything
- // TODO but it might be nice to log something with gentle wording (i.e., it is not an error)
- }
- return substituteVars(result);
- }
-
- private static Properties substituteVars(Properties result) {
- if (result == null) {
- //nothing todo.
- return null;
- }
- for (Enumeration<Object> eKeys = result.keys(); eKeys.hasMoreElements();) {
- Object key = eKeys.nextElement();
- if (key instanceof String) {
- String value = result.getProperty((String) key);
- if (value != null)
- result.put(key, BaseStorageHook.substituteVars(value));
- }
- }
- return result;
- }
-
/**
* Returns a URL which is equivalent to the given URL relative to the
* specified base URL. Works only for file: URLs
@@ -1215,26 +1074,12 @@ public class EclipseStarter {
return relative;
}
- private static void mergeProperties(Properties destination, Properties source) {
- for (Enumeration<?> e = source.keys(); e.hasMoreElements();) {
- String key = (String) e.nextElement();
- String value = source.getProperty(key);
- if (destination.getProperty(key) == null)
- destination.setProperty(key, value);
- }
- }
-
private static void setStartLevel(final int value) {
- ServiceReference<?> reference = context.getServiceReference(StartLevel.class.getName());
- final StartLevel startLevel = reference != null ? (StartLevel) context.getService(reference) : null;
- if (startLevel == null)
- return;
+ FrameworkStartLevel fwkStartLevel = context.getBundle().adapt(FrameworkStartLevel.class);
final Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.STARTLEVEL_CHANGED);
- context.addFrameworkListener(listener);
context.addBundleListener(listener);
- startLevel.setStartLevel(value);
- context.ungetService(reference);
+ fwkStartLevel.setStartLevel(value, listener);
updateSplash(semaphore, listener);
}
@@ -1301,7 +1146,7 @@ public class EclipseStarter {
// Pre-check if file exists, if not, and it contains escape characters,
// try decoding the path
if (!startFile.exists() && start.indexOf('%') >= 0) {
- String decodePath = FrameworkProperties.decode(start);
+ String decodePath = EquinoxConfiguration.decode(start);
File f = new File(decodePath);
if (f.exists())
startFile = f;
@@ -1408,8 +1253,8 @@ public class EclipseStarter {
private static void finalizeProperties() {
// if check config is unknown and we are in dev mode,
- if (FrameworkProperties.getProperty(PROP_DEV) != null && FrameworkProperties.getProperty(PROP_CHECK_CONFIG) == null)
- FrameworkProperties.setProperty(PROP_CHECK_CONFIG, "true"); //$NON-NLS-1$
+ if (getProperty(PROP_DEV) != null && getProperty(PROP_CHECK_CONFIG) == null)
+ setProperty(PROP_CHECK_CONFIG, "true"); //$NON-NLS-1$
}
private static class InitialBundle {
@@ -1443,9 +1288,9 @@ public class EclipseStarter {
return;
for (Map.Entry<String, String> entry : initialProperties.entrySet()) {
if (entry.getValue() != null)
- FrameworkProperties.setProperty(entry.getKey(), entry.getValue());
+ setProperty(entry.getKey(), entry.getValue());
else
- FrameworkProperties.clearProperty(entry.getKey());
+ clearProperty(entry.getKey());
}
}
@@ -1464,7 +1309,7 @@ public class EclipseStarter {
}
private static boolean isForcedRestart() {
- return Boolean.valueOf(FrameworkProperties.getProperty(PROP_FORCED_RESTART)).booleanValue();
+ return Boolean.valueOf(getProperty(EquinoxConfiguration.PROP_FORCED_RESTART)).booleanValue();
}
/*
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/package.html
index 65b481997..65b481997 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/package.html
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/ConsoleManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/ConsoleManager.java
new file mode 100644
index 000000000..5f77f763b
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/ConsoleManager.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.runtime.internal.adaptor;
+
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.osgi.framework.*;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+public class ConsoleManager {
+
+ public static final String PROP_CONSOLE = "osgi.console"; //$NON-NLS-1$
+ public static final String CONSOLE_BUNDLE = "org.eclipse.equinox.console"; //$NON-NLS-1$
+ public static final String PROP_CONSOLE_ENABLED = "osgi.console.enable.builtin"; //$NON-NLS-1$
+
+ private final BundleContext context;
+ private final EquinoxConfiguration equinoxConfig;
+ private final String consoleBundle;
+ private final String consolePort;
+
+ public ConsoleManager(BundleContext context, EquinoxConfiguration equinoxConfig) {
+ this.equinoxConfig = equinoxConfig;
+ String port = null;
+ String consolePropValue = equinoxConfig.getConfiguration(PROP_CONSOLE);
+ if (consolePropValue != null) {
+ int index = consolePropValue.lastIndexOf(":"); //$NON-NLS-1$
+ port = consolePropValue.substring(index + 1);
+ }
+ this.consolePort = port != null ? port.trim() : port;
+ String enabled = equinoxConfig.getConfiguration(PROP_CONSOLE_ENABLED, CONSOLE_BUNDLE);
+ this.context = context;
+ if (!"true".equals(enabled) || "none".equals(consolePort)) { //$NON-NLS-1$ //$NON-NLS-2$
+ this.consoleBundle = "false".equals(enabled) ? CONSOLE_BUNDLE : enabled; //$NON-NLS-1$
+ if (consolePort == null || consolePort.length() > 0) {
+ // no -console was specified or it has specified none or a port for telnet;
+ // need to make sure the gogo shell does not create an interactive console on standard in/out
+ equinoxConfig.setProperty("gosh.args", "--nointeractive"); //$NON-NLS-1$//$NON-NLS-2$
+ } else {
+ // Need to make sure we don't shutdown the framework if no console is around (bug 362412)
+ equinoxConfig.setProperty("gosh.args", "--noshutdown"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ return;
+ }
+ this.consoleBundle = "unknown"; //$NON-NLS-1$
+ }
+
+ public static ConsoleManager startConsole(BundleContext context, EquinoxConfiguration equinoxConfig) {
+ ConsoleManager consoleManager = new ConsoleManager(context, equinoxConfig);
+ return consoleManager;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void checkForConsoleBundle() throws BundleException {
+ if ("none".equals(consolePort)) //$NON-NLS-1$
+ return;
+ // otherwise we need to check for the equinox console bundle and start it
+ ServiceReference<PackageAdmin> paRef = context.getServiceReference(PackageAdmin.class);
+ PackageAdmin pa = paRef == null ? null : context.getService(paRef);
+ Bundle[] consoles = pa.getBundles(consoleBundle, null);
+ if (consoles == null || consoles.length == 0) {
+ if (consolePort != null)
+ throw new BundleException("Could not find bundle: " + consoleBundle, BundleException.UNSUPPORTED_OPERATION); //$NON-NLS-1$
+ return;
+ }
+ try {
+ consoles[0].start(Bundle.START_TRANSIENT);
+ } catch (BundleException e) {
+ throw new BundleException("Could not start bundle: " + consoleBundle, BundleException.UNSUPPORTED_OPERATION, e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Stops the OSGi Command console
+ *
+ */
+ public void stopConsole() {
+ // nothing
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/DefaultStartupMonitor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/DefaultStartupMonitor.java
index 9ac29d38d..95e58a2e7 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/DefaultStartupMonitor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/DefaultStartupMonitor.java
@@ -12,14 +12,14 @@ package org.eclipse.core.runtime.internal.adaptor;
import java.lang.reflect.Method;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
-import org.eclipse.core.runtime.internal.stats.StatsManager;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.service.runnable.StartupMonitor;
public class DefaultStartupMonitor implements StartupMonitor {
- private Method updateMethod = null;
- private Runnable splashHandler = null;
+ private final Method updateMethod;
+ private final Runnable splashHandler;
+ private final EquinoxConfiguration equinoxConfig;
/**
* Create a new startup monitor using the given splash handler. The splash handle must
@@ -28,8 +28,9 @@ public class DefaultStartupMonitor implements StartupMonitor {
* @param splashHandler
* @throws IllegalStateException
*/
- public DefaultStartupMonitor(Runnable splashHandler) throws IllegalStateException {
+ public DefaultStartupMonitor(Runnable splashHandler, EquinoxConfiguration equinoxConfig) throws IllegalStateException {
this.splashHandler = splashHandler;
+ this.equinoxConfig = equinoxConfig;
try {
updateMethod = splashHandler.getClass().getMethod("updateSplash", (Class[]) null); //$NON-NLS-1$
@@ -58,11 +59,10 @@ public class DefaultStartupMonitor implements StartupMonitor {
public void applicationRunning() {
if (EclipseStarter.debug) {
- String timeString = FrameworkProperties.getProperty("eclipse.startTime"); //$NON-NLS-1$
+ String timeString = equinoxConfig.getConfiguration("eclipse.startTime"); //$NON-NLS-1$
long time = timeString == null ? 0L : Long.parseLong(timeString);
System.out.println("Application Started: " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
}
- StatsManager.doneBooting();
splashHandler.run();
}
}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java
index a4106fdb6..d4dc9072f 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java
@@ -14,12 +14,11 @@ package org.eclipse.core.runtime.internal.adaptor;
import java.lang.reflect.Method;
import java.util.Map;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.profile.Profile;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.location.EclipseAdaptorMsg;
import org.eclipse.osgi.service.runnable.*;
import org.osgi.framework.*;
@@ -32,12 +31,14 @@ public class EclipseAppLauncher implements ApplicationLauncher {
private boolean relaunch = false;
private boolean failOnNoDefault = false;
private FrameworkLog log;
+ private final EquinoxConfiguration equinoxConfig;
- public EclipseAppLauncher(BundleContext context, boolean relaunch, boolean failOnNoDefault, FrameworkLog log) {
+ public EclipseAppLauncher(BundleContext context, boolean relaunch, boolean failOnNoDefault, FrameworkLog log, EquinoxConfiguration equinoxConfig) {
this.context = context;
this.relaunch = relaunch;
this.failOnNoDefault = failOnNoDefault;
this.log = log;
+ this.equinoxConfig = equinoxConfig;
findRunnableService();
}
@@ -81,9 +82,9 @@ public class EclipseAppLauncher implements ApplicationLauncher {
if (!relaunch || (context.getBundle().getState() & Bundle.ACTIVE) == 0)
throw e;
if (log != null)
- log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null));
+ log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null));
}
- doRelaunch = (relaunch && (context.getBundle().getState() & Bundle.ACTIVE) != 0) || FrameworkProperties.getProperty(Constants.PROP_OSGI_RELAUNCH) != null;
+ doRelaunch = (relaunch && (context.getBundle().getState() & Bundle.ACTIVE) != 0);
} while (doRelaunch);
return result;
}
@@ -99,18 +100,14 @@ public class EclipseAppLauncher implements ApplicationLauncher {
// this must happen after we have acquired an application (by acquiring waitForAppLock above).
runningLock.acquire();
if (EclipseStarter.debug) {
- String timeString = FrameworkProperties.getProperty("eclipse.startTime"); //$NON-NLS-1$
+ String timeString = equinoxConfig.getConfiguration("eclipse.startTime"); //$NON-NLS-1$
long time = timeString == null ? 0L : Long.parseLong(timeString);
System.out.println("Starting application: " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
}
- if (Profile.PROFILE && (Profile.STARTUP || Profile.BENCHMARK))
- Profile.logTime("EclipseStarter.run(Object)()", "framework initialized! starting application..."); //$NON-NLS-1$ //$NON-NLS-2$
try {
// run the actual application on the current thread (main).
return runnable.run(appContext != null ? appContext : defaultContext);
} finally {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logExit("EclipseStarter.run(Object)()"); //$NON-NLS-1$
// free the runnable application and release the lock to allow another app to be launched.
runnable = null;
appContext = null;
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java
index 0ef4bffcf..0ef4bffcf 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/BasicReadWriteLock.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/BasicReadWriteLock.java
index 621d31f9b..621d31f9b 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/BasicReadWriteLock.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/BasicReadWriteLock.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/EventAdminAdapter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/EventAdminAdapter.java
index 66a92b11e..66a92b11e 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/EventAdminAdapter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/EventAdminAdapter.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/EventAdminLogListener.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/EventAdminLogListener.java
index 02877e4e1..02877e4e1 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/EventAdminLogListener.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/EventAdminLogListener.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java
index 76134e0eb..76134e0eb 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogEntryImpl.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java
index f6a038994..f6a038994 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceImpl.java
index d8567fa43..d8567fa43 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceImpl.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogServiceFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogServiceFactory.java
index 0ae7ca266..0ae7ca266 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogServiceFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogServiceFactory.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogServiceImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogServiceImpl.java
index a2760e94d..a2760e94d 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogServiceImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/ExtendedLogServiceImpl.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/LogServiceManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/LogServiceManager.java
index e9fcc27ec..a08d17a4e 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/LogServiceManager.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/LogServiceManager.java
@@ -13,7 +13,7 @@ import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.*;
import org.eclipse.equinox.log.*;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.osgi.framework.*;
import org.osgi.service.log.*;
@@ -265,7 +265,7 @@ public class LogServiceManager implements BundleListener, FrameworkListener, Ser
}
public String getSymbolicName() {
- return FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME;
+ return EquinoxContainer.NAME;
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/LoggerImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/LoggerImpl.java
index 0a5559201..0a5559201 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/LoggerImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/LoggerImpl.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/SerializedTaskQueue.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/SerializedTaskQueue.java
index 9c15ad453..9c15ad453 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/SerializedTaskQueue.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/equinox/log/internal/SerializedTaskQueue.java
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/Module.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/Module.java
new file mode 100644
index 000000000..16d551629
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/Module.java
@@ -0,0 +1,626 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
+import org.osgi.framework.*;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Capability;
+import org.osgi.service.resolver.ResolutionException;
+
+/**
+ * A module represents a set of revisions installed in a
+ * module {@link ModuleContainer container}.
+ * @since 3.10
+ */
+public abstract class Module implements BundleReference, BundleStartLevel, Comparable<Module> {
+ /**
+ * The possible start options for a module
+ */
+ public static enum StartOptions {
+ /**
+ * The module start operation is transient and the persistent
+ * autostart or activation policy setting of the module is not modified.
+ */
+ TRANSIENT,
+ /**
+ * The module start operation must activate the module according to the module's declared
+ * activation policy.
+ */
+ USE_ACTIVATION_POLICY,
+ /**
+ * The module start operation is transient and the persistent activation policy
+ * setting will be used.
+ */
+ TRANSIENT_RESUME,
+ /**
+ * The module start operation is transient and will only happen if {@link Settings#AUTO_START auto start}
+ * setting is persistent.
+ */
+ TRANSIENT_IF_AUTO_START,
+ /**
+ * The module start operation that indicates the module is being started because of a
+ * lazy start trigger class load. This option must be used with the
+ * {@link StartOptions#TRANSIENT transient} options.
+ */
+ LAZY_TRIGGER;
+
+ /**
+ * Tests if this option is contained in the specified options
+ */
+ public boolean isContained(StartOptions... options) {
+ for (StartOptions option : options) {
+ if (equals(option)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * The possible start options for a module
+ */
+ public static enum StopOptions {
+ /**
+ * The module stop operation is transient and the persistent
+ * autostart setting of the module is not modified.
+ */
+ TRANSIENT;
+
+ /**
+ * Tests if this option is contained in the specified options
+ */
+ public boolean isContained(StopOptions... options) {
+ for (StopOptions option : options) {
+ if (equals(option)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * An enumeration of the possible {@link Module#getState() states} a module may be in.
+ */
+ public static enum State {
+ /**
+ * The module is installed but not yet resolved.
+ */
+ INSTALLED,
+ /**
+ * The module is resolved and able to be started.
+ */
+ RESOLVED,
+ /**
+ * The module is waiting for a {@link StartOptions#LAZY_TRIGGER trigger}
+ * class load to proceed with starting.
+ */
+ LAZY_STARTING,
+ /**
+ * The module is in the process of starting.
+ */
+ STARTING,
+ /**
+ * The module is now running.
+ */
+ ACTIVE,
+ /**
+ * The module is in the process of stopping
+ */
+ STOPPING,
+ /**
+ * The module is uninstalled and may not be used.
+ */
+ UNINSTALLED
+ }
+
+ /**
+ * An enumeration of persistent settings for a module
+ */
+ public static enum Settings {
+ /**
+ * The module has been set to auto start.
+ */
+ AUTO_START,
+ /**
+ * The module has been set to use its activation policy
+ */
+ USE_ACTIVATION_POLICY,
+ }
+
+ /**
+ * A set of {@link State states} that indicate a module is active.
+ */
+ public static final EnumSet<State> ACTIVE_SET = EnumSet.of(State.STARTING, State.LAZY_STARTING, State.ACTIVE, State.STOPPING);
+ /**
+ * A set of {@link State states} that indicate a module is resolved.
+ */
+ public static final EnumSet<State> RESOLVED_SET = EnumSet.of(State.RESOLVED, State.STARTING, State.LAZY_STARTING, State.ACTIVE, State.STOPPING);
+
+ private final Long id;
+ private final String location;
+ private final ModuleRevisions revisions;
+ final ReentrantLock stateChangeLock = new ReentrantLock();
+ private final EnumSet<ModuleEvent> stateTransitionEvents = EnumSet.noneOf(ModuleEvent.class);
+ private final EnumSet<Settings> settings;
+ private volatile State state = State.INSTALLED;
+ private volatile int startlevel;
+ private volatile long lastModified;
+
+ /**
+ * Constructs a new module with the specified id, location and
+ * container.
+ * @param id the new module id
+ * @param location the new module location
+ * @param container the container for the new module
+ * @param settings the persisted settings. May be {@code null} if there are no settings.
+ * @param startlevel the persisted start level or initial start level.
+ */
+ public Module(Long id, String location, ModuleContainer container, EnumSet<Settings> settings, int startlevel) {
+ this.id = id;
+ this.location = location;
+ this.revisions = new ModuleRevisions(this, container);
+ this.settings = settings == null ? EnumSet.noneOf(Settings.class) : EnumSet.copyOf(settings);
+ this.startlevel = startlevel;
+ }
+
+ /**
+ * Returns the module id.
+ * @return the module id.
+ */
+ public final Long getId() {
+ return id;
+ }
+
+ /** Returns the module location
+ * @return the module location
+ */
+ public final String getLocation() {
+ return location;
+ }
+
+ /**
+ * Returns the {@link ModuleRevisions} associated with this module.
+ * @return the {@link ModuleRevisions} associated with this module
+ */
+ public final ModuleRevisions getRevisions() {
+ return revisions;
+ }
+
+ /**
+ * Returns the module container this module is contained in.
+ * @return the module container.
+ */
+ public ModuleContainer getContainer() {
+ return revisions.getContainer();
+ }
+
+ /**
+ * Returns the current {@link ModuleRevision revision} associated with this module.
+ * If the module is uninstalled then the last current revision is returned.
+ * @return the current {@link ModuleRevision revision} associated with this module.
+ */
+ public final ModuleRevision getCurrentRevision() {
+ return revisions.getCurrentRevision();
+ }
+
+ /**
+ * Returns the current {@link State state} of this module.
+ * @return the current state of this module.
+ */
+ public final State getState() {
+ return state;
+ }
+
+ final void setState(State state) {
+ this.state = state;
+ }
+
+ @Override
+ public final int getStartLevel() {
+ checkValid();
+ return this.startlevel;
+ }
+
+ @Override
+ public final void setStartLevel(int startLevel) {
+ revisions.getContainer().setStartLevel(this, startLevel);
+ }
+
+ @Override
+ public final boolean isPersistentlyStarted() {
+ checkValid();
+ return settings.contains(Settings.AUTO_START);
+ }
+
+ @Override
+ public final boolean isActivationPolicyUsed() {
+ checkValid();
+ return settings.contains(Settings.USE_ACTIVATION_POLICY);
+ }
+
+ final void storeStartLevel(int newStartLevel) {
+ this.startlevel = newStartLevel;
+ }
+
+ /**
+ * Returns the time when this module was last modified. A module is considered
+ * to be modified when it is installed, updated or uninstalled.
+ * <p>
+ * The time value is a the number of milliseconds since January 1, 1970, 00:00:00 UTC.
+ * @return the time when this bundle was last modified.
+ */
+ public final long getLastModified() {
+ return this.lastModified;
+ }
+
+ final void setlastModified(long lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ private static final EnumSet<ModuleEvent> VALID_RESOLVED_TRANSITION = EnumSet.of(ModuleEvent.STARTED);
+ private static final EnumSet<ModuleEvent> VALID_STOPPED_TRANSITION = EnumSet.of(ModuleEvent.UPDATED, ModuleEvent.UNRESOLVED, ModuleEvent.UNINSTALLED);
+
+ /**
+ * Acquires the module lock for state changes by the current thread for the specified
+ * transition event. Certain transition events locks may be nested within other
+ * transition event locks. For example, a resolved transition event lock may be
+ * nested within a started transition event lock. A stopped transition lock
+ * may be nested within an updated, unresolved or uninstalled transition lock.
+ * @param transitionEvent the transition event to acquire the lock for.
+ * @throws BundleException
+ */
+ protected final void lockStateChange(ModuleEvent transitionEvent) throws BundleException {
+ boolean previousInterruption = Thread.interrupted();
+ try {
+ boolean acquired = stateChangeLock.tryLock(5, TimeUnit.SECONDS);
+ if (acquired) {
+ boolean isValidTransition = true;
+ switch (transitionEvent) {
+ case STARTED :
+ case UPDATED :
+ case UNINSTALLED :
+ case UNRESOLVED :
+ // These states must be initiating transition states
+ // no other transition state is allowed when these are kicked off
+ isValidTransition = stateTransitionEvents.isEmpty();
+ break;
+ case RESOLVED :
+ isValidTransition = VALID_RESOLVED_TRANSITION.containsAll(stateTransitionEvents);
+ break;
+ case STOPPED :
+ isValidTransition = VALID_STOPPED_TRANSITION.containsAll(stateTransitionEvents);
+ break;
+ default :
+ isValidTransition = false;
+ break;
+ }
+ if (!isValidTransition) {
+ stateChangeLock.unlock();
+ } else {
+ stateTransitionEvents.add(transitionEvent);
+ return;
+ }
+ }
+ throw new BundleException("Unable to acquire the state change lock for the module: " + transitionEvent, BundleException.STATECHANGE_ERROR);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new BundleException("Unable to acquire the state change lock for the module.", BundleException.STATECHANGE_ERROR, e);
+ } finally {
+ if (previousInterruption) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Releases the lock for state changes for the specified transition event.
+ * @param transitionEvent
+ */
+ protected final void unlockStateChange(ModuleEvent transitionEvent) {
+ if (stateChangeLock.getHoldCount() == 0 || !stateTransitionEvents.contains(transitionEvent))
+ throw new IllegalMonitorStateException("Current thread does not hold the state change lock for: " + transitionEvent);
+ stateTransitionEvents.remove(transitionEvent);
+ stateChangeLock.unlock();
+ }
+
+ /**
+ * Returns true if the current thread holds the state change lock for the specified transition event.
+ * @param transitionEvent
+ * @return true if the current thread holds the state change lock for the specified transition event.
+ */
+ protected final boolean holdsTransitionEventLock(ModuleEvent transitionEvent) {
+ return stateChangeLock.getHoldCount() > 0 && stateTransitionEvents.contains(transitionEvent);
+ }
+
+ /**
+ * Starts this module
+ * @param options the options for starting
+ * @throws BundleException if an errors occurs while starting
+ */
+ public void start(StartOptions... options) throws BundleException {
+ revisions.getContainer().checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
+ if (options == null) {
+ options = new StartOptions[0];
+ }
+ ModuleEvent event;
+ if (StartOptions.LAZY_TRIGGER.isContained(options)) {
+ if (stateChangeLock.getHoldCount() > 0 && stateTransitionEvents.contains(ModuleEvent.STARTED)) {
+ // nothing to do here; the current thread is activating the bundle.
+ return;
+ }
+ }
+ BundleException startError = null;
+ lockStateChange(ModuleEvent.STARTED);
+ try {
+ checkValid();
+ if (StartOptions.TRANSIENT_IF_AUTO_START.isContained(options) && !settings.contains(Settings.AUTO_START)) {
+ // Do nothing
+ return;
+ }
+ checkFragment();
+ persistStartOptions(options);
+ if (getStartLevel() > getRevisions().getContainer().getStartLevel()) {
+ if (StartOptions.TRANSIENT.isContained(options)) {
+ throw new BundleException("Cannot transiently start a module whose start level is not met.", BundleException.START_TRANSIENT_ERROR);
+ }
+ // DO nothing
+ return;
+ }
+ if (State.ACTIVE.equals(getState()))
+ return;
+ if (getState().equals(State.INSTALLED)) {
+ try {
+ getRevisions().getContainer().resolve(Arrays.asList(this), true);
+ } catch (ResolutionException e) {
+ if (e.getCause() instanceof BundleException) {
+ throw (BundleException) e.getCause();
+ }
+ throw new BundleException("Could not resolve module.", BundleException.RESOLVE_ERROR, e);
+ }
+ }
+ if (getState().equals(State.INSTALLED)) {
+ throw new BundleException("Could not resolve module.", BundleException.RESOLVE_ERROR);
+ }
+ try {
+ event = doStart(options);
+ } catch (BundleException e) {
+ // must return state to resolved
+ setState(State.RESOLVED);
+ startError = e;
+ // must always publish the STOPPED event on error
+ event = ModuleEvent.STOPPED;
+ }
+ } finally {
+ unlockStateChange(ModuleEvent.STARTED);
+ }
+
+ if (event != null) {
+ if (!EnumSet.of(ModuleEvent.STARTED, ModuleEvent.LAZY_ACTIVATION, ModuleEvent.STOPPED).contains(event))
+ throw new IllegalStateException("Wrong event type: " + event);
+ publishEvent(event);
+ }
+
+ if (startError != null) {
+ throw startError;
+ }
+ }
+
+ final void publishEvent(ModuleEvent type) {
+ revisions.getContainer().getAdaptor().publishModuleEvent(type, this, this);
+ }
+
+ /**
+ * Stops this module.
+ * @param options options for stopping
+ * @throws BundleException if an error occurs while stopping
+ */
+ public void stop(StopOptions... options) throws BundleException {
+ revisions.getContainer().checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
+ if (options == null)
+ options = new StopOptions[0];
+ ModuleEvent event;
+ BundleException stopError = null;
+ lockStateChange(ModuleEvent.STOPPED);
+ try {
+ checkValid();
+ checkFragment();
+ persistStopOptions(options);
+ if (!Module.ACTIVE_SET.contains(getState()))
+ return;
+ try {
+ event = doStop();
+ } catch (BundleException e) {
+ stopError = e;
+ // must always publish the STOPPED event
+ event = ModuleEvent.STOPPED;
+ }
+ } finally {
+ unlockStateChange(ModuleEvent.STOPPED);
+ }
+
+ if (event != null) {
+ if (!ModuleEvent.STOPPED.equals(event))
+ throw new IllegalStateException("Wrong event type: " + event);
+ publishEvent(event);
+ }
+ if (stopError != null)
+ throw stopError;
+ }
+
+ private void checkFragment() throws BundleException {
+ ModuleRevision current = getCurrentRevision();
+ if ((current.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ throw new BundleException("Invalid operation on a fragment.", BundleException.INVALID_OPERATION);
+ }
+ }
+
+ @Override
+ public final int compareTo(Module o) {
+ int slcomp = getStartLevel() - o.getStartLevel();
+ if (slcomp != 0) {
+ return slcomp;
+ }
+ long idcomp = getId() - o.getId();
+ return (idcomp < 0L) ? -1 : ((idcomp > 0L) ? 1 : 0);
+ }
+
+ final void checkValid() {
+ if (getState().equals(State.UNINSTALLED))
+ throw new IllegalStateException("Module has been uninstalled.");
+ }
+
+ private ModuleEvent doStart(StartOptions... options) throws BundleException {
+ boolean isLazyTrigger = StartOptions.LAZY_TRIGGER.isContained(options);
+ if (isLazyTrigger) {
+ if (!State.LAZY_STARTING.equals(getState())) {
+ // need to make sure we transition through the lazy starting state
+ setState(State.LAZY_STARTING);
+ // need to publish the lazy event
+ unlockStateChange(ModuleEvent.STARTED);
+ try {
+ publishEvent(ModuleEvent.LAZY_ACTIVATION);
+ } finally {
+ lockStateChange(ModuleEvent.STARTED);
+ }
+ if (State.ACTIVE.equals(getState())) {
+ // A sync listener must have caused the bundle to activate
+ return null;
+ }
+ // continue on to normal starting
+ }
+ } else {
+ if (isLazyActivate(options)) {
+ if (State.LAZY_STARTING.equals(getState())) {
+ // a sync listener must have tried to start this module again with the lazy option
+ return null; // no event to publish; nothing to do
+ }
+ // set the lazy starting state and return lazy activation event for firing
+ setState(State.LAZY_STARTING);
+ return ModuleEvent.LAZY_ACTIVATION;
+ }
+ }
+
+ // time to actual start the module
+ if (!State.STARTING.equals(getState())) {
+ // TODO this starting state check should not be needed
+ // but we do it because of the way the system module init works
+ setState(State.STARTING);
+ publishEvent(ModuleEvent.STARTING);
+ }
+ try {
+ startWorker();
+ setState(State.ACTIVE);
+ return ModuleEvent.STARTED;
+ } catch (Throwable t) {
+ // must fire stopping event
+ setState(State.STOPPING);
+ publishEvent(ModuleEvent.STOPPING);
+ if (t instanceof BundleException)
+ throw (BundleException) t;
+ throw new BundleException("Error starting module.", BundleException.ACTIVATOR_ERROR, t);
+ }
+ }
+
+ /**
+ * Performs any work associated with starting a module. For example,
+ * loading and calling start on an activator.
+ * @throws BundleException
+ */
+ protected void startWorker() throws BundleException {
+ // Do nothing
+ }
+
+ private ModuleEvent doStop() throws BundleException {
+ setState(State.STOPPING);
+ publishEvent(ModuleEvent.STOPPING);
+ try {
+ stopWorker();
+ return ModuleEvent.STOPPED;
+ } catch (Throwable t) {
+ if (t instanceof BundleException)
+ throw (BundleException) t;
+ throw new BundleException("Error stopping module.", BundleException.ACTIVATOR_ERROR, t);
+ } finally {
+ // must always set the state to stopped
+ setState(State.RESOLVED);
+ }
+ }
+
+ /**
+ * @throws BundleException
+ */
+ protected void stopWorker() throws BundleException {
+ // Do nothing
+ }
+
+ @Override
+ public String toString() {
+ return "[id=" + id + "]";
+ }
+
+ private void persistStartOptions(StartOptions... options) {
+ if (StartOptions.TRANSIENT.isContained(options) || StartOptions.TRANSIENT_RESUME.isContained(options) || StartOptions.LAZY_TRIGGER.isContained(options)) {
+ return;
+ }
+
+ if (StartOptions.USE_ACTIVATION_POLICY.isContained(options)) {
+ settings.add(Settings.USE_ACTIVATION_POLICY);
+ } else {
+ settings.remove(Settings.USE_ACTIVATION_POLICY);
+ }
+ settings.add(Settings.AUTO_START);
+ revisions.getContainer().moduleDatabase.persistSettings(settings, this);
+ }
+
+ private void persistStopOptions(StopOptions... options) {
+ if (StopOptions.TRANSIENT.isContained(options))
+ return;
+ settings.clear();
+ revisions.getContainer().moduleDatabase.persistSettings(settings, this);
+ }
+
+ /**
+ * The container is done with the revision and it has been complete removed.
+ * This method allows the resources behind the revision to be cleaned up.
+ * @param revision the revision to clean up
+ */
+ abstract protected void cleanup(ModuleRevision revision);
+
+ final boolean isLazyActivate(StartOptions... options) {
+ if (StartOptions.TRANSIENT.isContained(options)) {
+ if (!StartOptions.USE_ACTIVATION_POLICY.isContained(options)) {
+ return false;
+ }
+ } else if (!settings.contains(Settings.USE_ACTIVATION_POLICY)) {
+ return false;
+ }
+ return hasLazyActivatePolicy();
+ }
+
+ private boolean hasLazyActivatePolicy() {
+ ModuleRevision current = getCurrentRevision();
+ if (current == null)
+ return false;
+ List<Capability> capabilities = current.getCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ if (capabilities.isEmpty())
+ return false;
+ Capability moduleData = capabilities.get(0);
+ return EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY_LAZY.equals(moduleData.getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY));
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java
new file mode 100644
index 000000000..d94b14f64
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.util.Map;
+import org.osgi.framework.wiring.BundleCapability;
+
+/**
+ * An implementation of {@link BundleCapability}.
+ * @since 3.10
+ */
+public final class ModuleCapability implements BundleCapability {
+ private final String namespace;
+ private final Map<String, String> directives;
+ private final Map<String, Object> attributes;
+ private final ModuleRevision revision;
+
+ ModuleCapability(String namespace, Map<String, String> directives, Map<String, Object> attributes, ModuleRevision revision) {
+ this.namespace = namespace;
+ this.directives = directives;
+ this.attributes = attributes;
+ this.revision = revision;
+ }
+
+ @Override
+ public ModuleRevision getRevision() {
+ return revision;
+ }
+
+ @Override
+ public String getNamespace() {
+ return namespace;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public ModuleRevision getResource() {
+ return revision;
+ }
+
+ @Override
+ public String toString() {
+ return namespace + ModuleRevision.toString(attributes, false) + ModuleRevision.toString(directives, true);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCollisionHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCollisionHook.java
new file mode 100644
index 000000000..d1b33b968
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCollisionHook.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.util.Collection;
+
+/**
+ * Hook used to determine if a module revision being installed or updated will cause a collision
+ * @since 3.10
+ */
+public interface ModuleCollisionHook {
+
+ /**
+ * Specifies a module install operation is being performed.
+ */
+ int INSTALLING = 1;
+
+ /**
+ * Specifies a module update operation is being performed.
+ */
+ int UPDATING = 2;
+
+ /**
+ * Filter bundle collisions hook method. This method is called during the
+ * install or update operation. The operation type will be
+ * {@link #INSTALLING installing} or {@link #UPDATING updating}. Depending
+ * on the operation type the target module and the collision candidate
+ * collection are the following:
+ * <ul>
+ * <li> {@link #INSTALLING installing} - The target is the module associated
+ * which is performing the install operation. The
+ * collision candidate collection contains the existing modules installed
+ * which have a current revision with the same symbolic name and version as the
+ * module being installed.
+ * <li> {@link #UPDATING updating} - The target is the module being updated.
+ * The collision candidate collection contains the existing modules installed which have
+ * a current revision with the same symbolic name and version as the content the target
+ * module is being updated to.
+ * </ul>
+ * This method can filter the collection of collision candidates by removing
+ * potential collisions. For the specified operation to succeed, the
+ * collection of collision candidates must be empty when this method returns.
+ *
+ * @param operationType The operation type. Must be the value of
+ * {@link #INSTALLING installing} or {@link #UPDATING updating}.
+ * @param target The target module used to determine what collision
+ * candidates to filter.
+ * @param collisionCandidates The collection of collision candidates.
+ */
+ void filterCollisions(int operationType, Module target, Collection<Module> collisionCandidates);
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
new file mode 100644
index 000000000..e8ee16ce1
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
@@ -0,0 +1,1417 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.eclipse.osgi.container.Module.StartOptions;
+import org.eclipse.osgi.container.Module.State;
+import org.eclipse.osgi.container.Module.StopOptions;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
+import org.eclipse.osgi.container.ModuleDatabase.Sort;
+import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement;
+import org.eclipse.osgi.framework.eventmgr.*;
+import org.eclipse.osgi.internal.container.LockSet;
+import org.osgi.framework.*;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.service.resolver.ResolutionException;
+
+/**
+ * A container for installing, updating, uninstalling and resolve modules.
+ * @since 3.10
+ */
+public final class ModuleContainer {
+
+ /**
+ * Used by install operations to establish a write lock on an install location
+ */
+ private final LockSet<String> locationLocks = new LockSet<String>();
+
+ /**
+ * Used by install and update operations to establish a write lock for a name
+ */
+ private final LockSet<String> nameLocks = new LockSet<String>();
+
+ /**
+ * An implementation of FrameworkWiring for this container
+ */
+ private final ContainerWiring frameworkWiring;
+
+ /**
+ * An implementation of FrameworkStartLevel for this container
+ */
+ private final ContainerStartLevel frameworkStartLevel;
+
+ /**
+ * The module database for this container.
+ */
+ final ModuleDatabase moduleDatabase;
+
+ /**
+ * The module adaptor for this container.
+ */
+ final ModuleContainerAdaptor adaptor;
+
+ /**
+ * The module resolver which implements the ResolverContext and handles calling the
+ * resolver service.
+ */
+ private final ModuleResolver moduleResolver;
+
+ private final Collection<SystemModule> refreshingSystemModule = new ArrayList<SystemModule>(1);
+
+ /**
+ * Constructs a new container with the specified collision hook, resolver hook, resolver and module database.
+ * @param adaptor the adaptor for the container
+ * @param moduledataBase the module database
+ */
+ public ModuleContainer(ModuleContainerAdaptor adaptor, ModuleDatabase moduledataBase) {
+ this.adaptor = adaptor;
+ this.moduleResolver = new ModuleResolver(adaptor);
+ this.moduleDatabase = moduledataBase;
+ this.frameworkWiring = new ContainerWiring();
+ this.frameworkStartLevel = new ContainerStartLevel();
+ }
+
+ /**
+ * Returns the adaptor for this container
+ * @return the adaptor for this container
+ */
+ public ModuleContainerAdaptor getAdaptor() {
+ return adaptor;
+ }
+
+ /**
+ * Returns the list of currently installed modules sorted by module id.
+ * @return the list of currently installed modules sorted by module id.
+ */
+ public List<Module> getModules() {
+ return moduleDatabase.getModules();
+ }
+
+ /**
+ * Returns the module installed with the specified id, or null if no
+ * such module is installed.
+ * @param id the id of the module
+ * @return the module with the specified id, or null of no such module is installed.
+ */
+ public Module getModule(long id) {
+ return moduleDatabase.getModule(id);
+ }
+
+ /**
+ * Returns the module installed with the specified location, or null if no
+ * such module is installed.
+ * @param location the location of the module
+ * @return the module with the specified location, or null of no such module is installed.
+ */
+ public Module getModule(String location) {
+ return moduleDatabase.getModule(location);
+ }
+
+ /**
+ * Returns a snapshot collection of revisions with the specified name
+ * and version. If version is {@code null} then all revisions with
+ * the specified name are returned.
+ * @param name the name of the modules
+ * @param version the version of the modules or {@code null}
+ * @return a snapshot collection of revisions with the specified name
+ * and version.
+ */
+ public Collection<ModuleRevision> getRevisions(String name, Version version) {
+ return moduleDatabase.getRevisions(name, version);
+ }
+
+ /**
+ * Installs a new module using the specified location. The specified
+ * builder is used to create a new {@link ModuleRevision revision}
+ * which will become the {@link Module#getCurrentRevision() current}
+ * revision of the new module.
+ * <p>
+ * If a module already exists with the specified location then the
+ * existing module is returned and the builder is not used.
+ * @param origin the module performing the install, may be {@code null}.
+ * @param location The location identifier of the module to install.
+ * @param builder the builder used to create the revision to install.
+ * @param revisionInfo the revision info for the new revision, may be {@code null}.
+ * @return a new module or a existing module if one exists at the
+ * specified location.
+ * @throws BundleException if some error occurs installing the module
+ */
+ public Module install(Module origin, String location, ModuleRevisionBuilder builder, Object revisionInfo) throws BundleException {
+ String name = builder.getSymbolicName();
+ boolean locationLocked = false;
+ boolean nameLocked = false;
+ try {
+ // Attempt to lock the location and name
+ try {
+ locationLocked = locationLocks.tryLock(location, 5, TimeUnit.SECONDS);
+ nameLocked = name != null && nameLocks.tryLock(name, 5, TimeUnit.SECONDS);
+ if (!locationLocked) {
+ throw new BundleException("Failed to obtain location lock for installation: " + location, BundleException.STATECHANGE_ERROR);
+ }
+ if (name != null && !nameLocked) {
+ throw new BundleException("Failed to obtain symbolic name lock for installation: " + name, BundleException.STATECHANGE_ERROR);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR, e);
+ }
+
+ Module existingLocation = null;
+ Collection<Module> collisionCandidates = Collections.emptyList();
+ moduleDatabase.lockRead();
+ try {
+ existingLocation = moduleDatabase.getModule(location);
+ if (existingLocation == null) {
+ // Collect existing current revisions with the same name and version as the revision we want to install
+ // This is to perform the collision check below
+ Collection<ModuleRevision> existingRevisionNames = moduleDatabase.getRevisions(name, builder.getVersion());
+ if (!existingRevisionNames.isEmpty()) {
+ collisionCandidates = new ArrayList<Module>(1);
+ for (ModuleRevision equinoxRevision : existingRevisionNames) {
+ if (!equinoxRevision.isCurrent())
+ continue; // only pay attention to current revisions
+ // need to prevent duplicates here; this is in case a revisions object contains multiple revision objects.
+ if (!collisionCandidates.contains(equinoxRevision.getRevisions().getModule()))
+ collisionCandidates.add(equinoxRevision.getRevisions().getModule());
+ }
+ }
+ }
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+ // Check that the existing location is visible from the origin module
+ if (existingLocation != null) {
+ if (origin != null) {
+ Bundle bundle = origin.getBundle();
+ BundleContext context = bundle == null ? null : bundle.getBundleContext();
+ if (context != null && context.getBundle(existingLocation.getId()) == null) {
+ Bundle b = existingLocation.getBundle();
+ throw new BundleException("Bundle \"" + b.getSymbolicName() + "\" version \"" + b.getVersion() + "\" is already installed at location: " + location, BundleException.REJECTED_BY_HOOK);
+ }
+ }
+ return existingLocation;
+ }
+ // Check that the bundle does not collide with other bundles with the same name and version
+ // This is from the perspective of the origin bundle
+ if (origin != null && !collisionCandidates.isEmpty()) {
+ adaptor.getModuleCollisionHook().filterCollisions(ModuleCollisionHook.INSTALLING, origin, collisionCandidates);
+ }
+ if (!collisionCandidates.isEmpty()) {
+ throw new BundleException("A bundle is already installed with name \"" + name + "\" and version \"" + builder.getVersion(), BundleException.DUPLICATE_BUNDLE_ERROR);
+ }
+
+ Module result = moduleDatabase.install(location, builder, revisionInfo);
+
+ adaptor.publishModuleEvent(ModuleEvent.INSTALLED, result, origin);
+
+ return result;
+ } finally {
+ if (locationLocked)
+ locationLocks.unlock(location);
+ if (nameLocked)
+ nameLocks.unlock(name);
+ }
+ }
+
+ /**
+ * Updates the specified module with a new revision. The specified
+ * builder is used to create a new {@link ModuleRevision revision}
+ * which will become the {@link Module#getCurrentRevision() current}
+ * revision of the new module.
+ * @param module the module to update
+ * @param builder the builder used to create the revision for the update.
+ * @param revisionInfo the revision info for the new revision, may be {@code null}.
+ * @throws BundleException if some error occurs updating the module
+ */
+ public void update(Module module, ModuleRevisionBuilder builder, Object revisionInfo) throws BundleException {
+ checkAdminPermission(module.getBundle(), AdminPermission.LIFECYCLE);
+ String name = builder.getSymbolicName();
+ boolean nameLocked = false;
+ try {
+ // Attempt to lock the name
+ try {
+ if (name != null && !(nameLocked = nameLocks.tryLock(name, 5, TimeUnit.SECONDS))) {
+ throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR, e);
+ }
+
+ Collection<Module> collisionCandidates = Collections.emptyList();
+ moduleDatabase.lockRead();
+ try {
+ // Collect existing bundles with the same name and version as the bundle we want to install
+ // This is to perform the collision check below
+ Collection<ModuleRevision> existingRevisionNames = moduleDatabase.getRevisions(name, builder.getVersion());
+ if (!existingRevisionNames.isEmpty()) {
+ collisionCandidates = new ArrayList<Module>(1);
+ for (ModuleRevision equinoxRevision : existingRevisionNames) {
+ if (!equinoxRevision.isCurrent())
+ continue;
+ Module m = equinoxRevision.getRevisions().getModule();
+ if (m.equals(module))
+ continue; // don't worry about the updating modules revisions
+ // need to prevent duplicates here; this is in case a revisions object contains multiple revision objects.
+ if (!collisionCandidates.contains(m))
+ collisionCandidates.add(m);
+ }
+ }
+
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+
+ // Check that the module does not collide with other modules with the same name and version
+ // This is from the perspective of the module being updated
+ if (module != null && !collisionCandidates.isEmpty()) {
+ adaptor.getModuleCollisionHook().filterCollisions(ModuleCollisionHook.UPDATING, module, collisionCandidates);
+ }
+
+ if (!collisionCandidates.isEmpty()) {
+ throw new BundleException("A bundle is already installed with name \"" + name + "\" and version \"" + builder.getVersion(), BundleException.DUPLICATE_BUNDLE_ERROR);
+ }
+
+ module.lockStateChange(ModuleEvent.UPDATED);
+ State previousState;
+ try {
+ module.checkValid();
+ previousState = module.getState();
+ if (Module.ACTIVE_SET.contains(previousState)) {
+ // throwing an exception from stop terminates update
+ module.stop(StopOptions.TRANSIENT);
+ }
+ if (Module.RESOLVED_SET.contains(previousState)) {
+ // set the state to installed and publish unresolved event
+ module.setState(State.INSTALLED);
+ adaptor.publishModuleEvent(ModuleEvent.UNRESOLVED, module, module);
+ }
+ moduleDatabase.update(module, builder, revisionInfo);
+ } finally {
+ module.unlockStateChange(ModuleEvent.UPDATED);
+ }
+ // only publish updated event on success
+ adaptor.publishModuleEvent(ModuleEvent.UPDATED, module, module);
+
+ if (Module.ACTIVE_SET.contains(previousState)) {
+ try {
+ // restart the module if necessary
+ module.start(StartOptions.TRANSIENT_RESUME);
+ } catch (BundleException e) {
+ getAdaptor().publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ }
+ } finally {
+ if (nameLocked)
+ nameLocks.unlock(name);
+ }
+ }
+
+ /**
+ * Uninstalls the specified module.
+ * @param module the module to uninstall
+ * @throws BundleException if some error occurs uninstalling the module
+ */
+ public void uninstall(Module module) throws BundleException {
+ checkAdminPermission(module.getBundle(), AdminPermission.LIFECYCLE);
+ module.lockStateChange(ModuleEvent.UNINSTALLED);
+ State previousState;
+ try {
+ module.checkValid();
+ previousState = module.getState();
+ if (Module.ACTIVE_SET.contains(module.getState())) {
+ try {
+ module.stop(StopOptions.TRANSIENT);
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ }
+ moduleDatabase.uninstall(module);
+ if (Module.RESOLVED_SET.contains(previousState)) {
+ // set the state to installed and publish unresolved event
+ module.setState(State.INSTALLED);
+ adaptor.publishModuleEvent(ModuleEvent.UNRESOLVED, module, module);
+ }
+ module.setState(State.UNINSTALLED);
+ } finally {
+ module.unlockStateChange(ModuleEvent.UNINSTALLED);
+ }
+ adaptor.publishModuleEvent(ModuleEvent.UNINSTALLED, module, module);
+ }
+
+ ModuleWiring getWiring(ModuleRevision revision) {
+ return moduleDatabase.getWiring(revision);
+ }
+
+ /**
+ * Returns the {@link FrameworkWiring} for this container
+ * @return the framework wiring for this container.
+ */
+ public FrameworkWiring getFrameworkWiring() {
+ return frameworkWiring;
+ }
+
+ /**
+ * Returns the {@link FrameworkStartLevel} for this container
+ * @return the framework start level for this container
+ */
+ public FrameworkStartLevel getFrameworkStartLevel() {
+ return frameworkStartLevel;
+ }
+
+ /**
+ * Attempts to resolve the current revisions of the specified modules.
+ * @param triggers the modules to resolve or {@code null} to resolve all unresolved
+ * current revisions.
+ * @param triggersMandatory true if the triggers must be resolved. This will result in
+ * a {@link ResolutionException} if set to true and one of the triggers could not be resolved.
+ * @throws ResolutionException if a resolution error occurs
+ * @see FrameworkWiring#resolveBundles(Collection)
+ */
+ public void resolve(Collection<Module> triggers, boolean triggersMandatory) throws ResolutionException {
+ if (isRefreshingSystemModule()) {
+ throw new ResolutionException("Unable to resolve while shutting down the framework.");
+ }
+ try {
+ while (!resolve0(triggers, triggersMandatory)) {
+ // nothing
+ }
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof BundleException) {
+ throw new ResolutionException(e.getCause());
+ }
+ throw e;
+ }
+ }
+
+ private boolean resolve0(Collection<Module> triggers, boolean triggersMandatory) throws ResolutionException {
+ if (triggers == null)
+ triggers = new ArrayList<Module>(0);
+ Collection<ModuleRevision> triggerRevisions = new ArrayList<ModuleRevision>(triggers.size());
+ Collection<ModuleRevision> unresolved = new ArrayList<ModuleRevision>();
+ Map<ModuleRevision, ModuleWiring> wiringClone;
+ long timestamp;
+ moduleDatabase.lockRead();
+ try {
+ timestamp = moduleDatabase.getRevisionsTimestamp();
+ wiringClone = moduleDatabase.getWiringsClone();
+ for (Module module : triggers) {
+ if (!State.UNINSTALLED.equals(module.getState())) {
+ ModuleRevision current = module.getCurrentRevision();
+ if (current != null)
+ triggerRevisions.add(current);
+ }
+ }
+ Collection<Module> allModules = moduleDatabase.getModules();
+ for (Module module : allModules) {
+ ModuleRevision revision = module.getCurrentRevision();
+ if (revision != null && !wiringClone.containsKey(revision))
+ unresolved.add(revision);
+ }
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+
+ Map<ModuleRevision, ModuleWiring> deltaWiring = moduleResolver.resolveDelta(triggerRevisions, triggersMandatory, unresolved, wiringClone, moduleDatabase);
+ if (deltaWiring.isEmpty())
+ return true; // nothing to do
+
+ Collection<Module> modulesResolved = new ArrayList<Module>();
+ for (ModuleRevision deltaRevision : deltaWiring.keySet()) {
+ if (!wiringClone.containsKey(deltaRevision))
+ modulesResolved.add(deltaRevision.getRevisions().getModule());
+ }
+
+ return applyDelta(deltaWiring, modulesResolved, timestamp);
+ }
+
+ public ModuleWire resolveDynamic(String dynamicPkgName, ModuleRevision revision) throws ResolutionException {
+ ModuleWire result;
+ Map<ModuleRevision, ModuleWiring> deltaWiring;
+ Collection<Module> modulesResolved;
+ long timestamp;
+ do {
+ result = null;
+ Map<ModuleRevision, ModuleWiring> wiringClone = null;
+ List<DynamicModuleRequirement> dynamicReqs = null;
+ Collection<ModuleRevision> unresolved = new ArrayList<ModuleRevision>();
+ moduleDatabase.lockRead();
+ try {
+ dynamicReqs = getDynamicRequirements(dynamicPkgName, revision);
+ if (dynamicReqs.isEmpty()) {
+ // do nothing
+ return null;
+ }
+ timestamp = moduleDatabase.getRevisionsTimestamp();
+ wiringClone = moduleDatabase.getWiringsClone();
+ Collection<Module> allModules = moduleDatabase.getModules();
+ for (Module module : allModules) {
+ ModuleRevision current = module.getCurrentRevision();
+ if (current != null && !wiringClone.containsKey(current))
+ unresolved.add(current);
+ }
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+
+ deltaWiring = null;
+ for (DynamicModuleRequirement dynamicReq : dynamicReqs) {
+ deltaWiring = moduleResolver.resolveDynamicDelta(dynamicReq, unresolved, wiringClone, moduleDatabase);
+ if (deltaWiring.get(revision) != null) {
+ break;
+ }
+ }
+ if (deltaWiring == null || deltaWiring.get(revision) == null)
+ return null; // nothing to do
+
+ modulesResolved = new ArrayList<Module>();
+ for (ModuleRevision deltaRevision : deltaWiring.keySet()) {
+ if (!wiringClone.containsKey(deltaRevision))
+ modulesResolved.add(deltaRevision.getRevisions().getModule());
+ }
+
+ // Save the result
+ ModuleWiring wiring = deltaWiring.get(revision);
+ if (wiring != null) {
+ List<ModuleWire> wires = wiring.getRequiredModuleWires(null);
+ result = wires.isEmpty() ? null : wires.get(wires.size() - 1);
+ // Doing a sanity check, may not be necessary
+ if (result != null) {
+ if (!PackageNamespace.PACKAGE_NAMESPACE.equals(result.getCapability().getNamespace()) || !dynamicPkgName.equals(result.getCapability().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))) {
+ throw new ResolutionException("Resolver provided an invalid dynamic wire: " + result);
+ }
+ }
+ }
+ } while (!applyDelta(deltaWiring, modulesResolved, timestamp));
+
+ return result;
+ }
+
+ private boolean applyDelta(Map<ModuleRevision, ModuleWiring> deltaWiring, Collection<Module> modulesResolved, long timestamp) {
+ Collection<Module> modulesLocked = new ArrayList<Module>(modulesResolved.size());
+ // now attempt to apply the delta
+ try {
+ // acquire the necessary RESOLVED state change lock
+ for (Module module : modulesResolved) {
+ try {
+ module.lockStateChange(ModuleEvent.RESOLVED);
+ modulesLocked.add(module);
+ } catch (BundleException e) {
+ // TODO throw some appropriate exception
+ throw new IllegalStateException("Could not acquire state change lock.", e);
+ }
+ }
+ moduleDatabase.lockWrite();
+ try {
+ if (timestamp != moduleDatabase.getRevisionsTimestamp())
+ return false; // need to try again
+ Map<ModuleRevision, ModuleWiring> wiringCopy = moduleDatabase.getWiringsCopy();
+ for (Map.Entry<ModuleRevision, ModuleWiring> deltaEntry : deltaWiring.entrySet()) {
+ ModuleWiring current = wiringCopy.get(deltaEntry.getKey());
+ if (current != null) {
+ // need to update the provided capabilities, provided and required wires for currently resolved
+ current.setCapabilities(deltaEntry.getValue().getModuleCapabilities(null));
+ current.setProvidedWires(deltaEntry.getValue().getProvidedModuleWires(null));
+ current.setRequiredWires(deltaEntry.getValue().getRequiredModuleWires(null));
+ deltaEntry.setValue(current); // set the real wiring into the delta
+ } else {
+ modulesResolved.add(deltaEntry.getValue().getRevision().getRevisions().getModule());
+ }
+ }
+ moduleDatabase.mergeWiring(deltaWiring);
+ } finally {
+ moduleDatabase.unlockWrite();
+ }
+ // set the modules state to resolved
+ for (Module module : modulesLocked) {
+ module.setState(State.RESOLVED);
+ }
+ } finally {
+ for (Module module : modulesLocked) {
+ module.unlockStateChange(ModuleEvent.RESOLVED);
+ }
+ }
+
+ for (Module module : modulesLocked) {
+ adaptor.publishModuleEvent(ModuleEvent.RESOLVED, module, module);
+ }
+ return true;
+ }
+
+ private List<DynamicModuleRequirement> getDynamicRequirements(String dynamicPkgName, ModuleRevision revision) {
+ // TODO Will likely need to optimize this
+ if ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ // only do this for hosts
+ return null;
+ }
+ ModuleWiring wiring = revision.getWiring();
+ if (wiring == null) {
+ // not resolved!
+ return null;
+ }
+ List<DynamicModuleRequirement> result = new ArrayList<ModuleRequirement.DynamicModuleRequirement>(1);
+ // check the dynamic import packages
+ DynamicModuleRequirement dynamicRequirement;
+ for (ModuleRequirement requirement : wiring.getModuleRequirements(PackageNamespace.PACKAGE_NAMESPACE)) {
+ dynamicRequirement = requirement.getDynamicPackageRequirement(revision, dynamicPkgName);
+ if (dynamicRequirement != null) {
+ result.add(dynamicRequirement);
+ }
+ }
+
+ return result;
+ }
+
+ private Collection<Module> unresolve(Collection<Module> initial) {
+ Collection<Module> refreshTriggers = null;
+ while (refreshTriggers == null) {
+ refreshTriggers = unresolve0(initial);
+ }
+ return refreshTriggers;
+ }
+
+ private Collection<Module> unresolve0(Collection<Module> initial) {
+ Map<ModuleRevision, ModuleWiring> wiringCopy;
+ Collection<Module> refreshTriggers;
+ Collection<ModuleRevision> toRemoveRevisions;
+ Collection<ModuleWiring> toRemoveWirings;
+ Map<ModuleWiring, Collection<ModuleWire>> toRemoveWireLists;
+ long timestamp;
+ moduleDatabase.lockRead();
+ try {
+ checkSystemExtensionRefresh(initial);
+ timestamp = moduleDatabase.getRevisionsTimestamp();
+ wiringCopy = moduleDatabase.getWiringsCopy();
+ refreshTriggers = getRefreshClosure(initial, wiringCopy);
+ toRemoveRevisions = new ArrayList<ModuleRevision>();
+ toRemoveWirings = new ArrayList<ModuleWiring>();
+ toRemoveWireLists = new HashMap<ModuleWiring, Collection<ModuleWire>>();
+ for (Module module : refreshTriggers) {
+ boolean first = true;
+ for (ModuleRevision revision : module.getRevisions().getModuleRevisions()) {
+ ModuleWiring removedWiring = wiringCopy.remove(revision);
+ if (removedWiring != null) {
+ toRemoveWirings.add(removedWiring);
+ List<ModuleWire> removedWires = removedWiring.getRequiredModuleWires(null);
+ for (ModuleWire wire : removedWires) {
+ Collection<ModuleWire> providerWires = toRemoveWireLists.get(wire.getProviderWiring());
+ if (providerWires == null) {
+ providerWires = new ArrayList<ModuleWire>();
+ toRemoveWireLists.put(wire.getProviderWiring(), providerWires);
+ }
+ providerWires.add(wire);
+ }
+ }
+ if (!first || revision.getRevisions().isUninstalled()) {
+ toRemoveRevisions.add(revision);
+ }
+ first = false;
+ }
+ }
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+
+ Module systemModule = moduleDatabase.getModule(0);
+ if (refreshTriggers.contains(systemModule) && Module.ACTIVE_SET.contains(systemModule.getState())) {
+ refreshSystemModule();
+ return Collections.emptyList();
+ }
+ Collection<Module> modulesLocked = new ArrayList<Module>(refreshTriggers.size());
+ Collection<Module> modulesUnresolved = new ArrayList<Module>();
+ try {
+ // acquire module state change locks
+ try {
+ for (Module refreshModule : refreshTriggers) {
+ refreshModule.lockStateChange(ModuleEvent.UNRESOLVED);
+ modulesLocked.add(refreshModule);
+ }
+ } catch (BundleException e) {
+ // TODO throw some appropriate exception
+ throw new IllegalStateException("Could not acquire state change lock.", e);
+ }
+ // Stop any active bundles and remove non-active modules from the refreshTriggers
+ for (Iterator<Module> iTriggers = refreshTriggers.iterator(); iTriggers.hasNext();) {
+ Module refreshModule = iTriggers.next();
+ if (Module.ACTIVE_SET.contains(refreshModule.getState())) {
+ try {
+ refreshModule.stop(StopOptions.TRANSIENT);
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, refreshModule, e);
+ }
+ } else {
+ iTriggers.remove();
+ }
+ }
+
+ // do a sanity check on states of the modules, they must be INSTALLED, RESOLVED or UNINSTALLED
+ for (Module module : modulesLocked) {
+ if (Module.ACTIVE_SET.contains(module.getState())) {
+ throw new IllegalStateException("Module is in the wrong state: " + module + ": " + module.getState());
+ }
+ }
+
+ // finally apply the unresolve to the database
+ moduleDatabase.lockWrite();
+ try {
+ if (timestamp != moduleDatabase.getRevisionsTimestamp())
+ return null; // need to try again
+ // remove any wires from unresolved wirings that got removed
+ for (Map.Entry<ModuleWiring, Collection<ModuleWire>> entry : toRemoveWireLists.entrySet()) {
+ List<ModuleWire> provided = entry.getKey().getProvidedModuleWires(null);
+ provided.removeAll(entry.getValue());
+ entry.getKey().setProvidedWires(provided);
+ for (ModuleWire removedWire : entry.getValue()) {
+ // invalidate the wire
+ removedWire.invalidate();
+ }
+
+ }
+ // remove any revisions that got removed as part of the refresh
+ for (ModuleRevision removed : toRemoveRevisions) {
+ removed.getRevisions().removeRevision(removed);
+ moduleDatabase.removeCapabilities(removed);
+ }
+ // invalidate any removed wiring objects
+ for (ModuleWiring moduleWiring : toRemoveWirings) {
+ moduleWiring.invalidate();
+ }
+ moduleDatabase.setWiring(wiringCopy);
+ } finally {
+ moduleDatabase.unlockWrite();
+ }
+ // set the state of modules to unresolved
+ for (Module module : modulesLocked) {
+ if (State.RESOLVED.equals(module.getState())) {
+ module.setState(State.INSTALLED);
+ modulesUnresolved.add(module);
+ }
+ }
+ } finally {
+ for (Module module : modulesLocked) {
+ module.unlockStateChange(ModuleEvent.UNRESOLVED);
+ }
+ }
+
+ // publish unresolved events after giving up all locks
+ for (Module module : modulesUnresolved) {
+ adaptor.publishModuleEvent(ModuleEvent.UNRESOLVED, module, module);
+ }
+ return refreshTriggers;
+ }
+
+ private void checkSystemExtensionRefresh(Collection<Module> initial) {
+ if (initial == null) {
+ return;
+ }
+ Long zero = new Long(0);
+ for (Iterator<Module> iModules = initial.iterator(); iModules.hasNext();) {
+ Module m = iModules.next();
+ if (m.getId().equals(zero)) {
+ // never allow system bundle to be unresolved directly if the system module is active
+ if (Module.ACTIVE_SET.contains(m.getState())) {
+ iModules.remove();
+ }
+ } else {
+ if (Module.RESOLVED_SET.contains(m.getState())) {
+ // check if current revision is an extension of the system module
+ ModuleRevision current = m.getCurrentRevision();
+ if ((current.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ ModuleWiring wiring = current.getWiring();
+ if (wiring != null) {
+ List<ModuleWire> hostWires = wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ for (ModuleWire hostWire : hostWires) {
+ if (hostWire.getProvider().getRevisions().getModule().getId().equals(zero)) {
+ // The current revision is the extension to allow it to refresh
+ // this would just shutdown the framework for no reason
+ iModules.remove();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Refreshes the specified collection of modules.
+ * @param initial the modules to refresh or {@code null} to refresh the
+ * removal pending.
+ * @throws ResolutionException
+ * @see FrameworkWiring#refreshBundles(Collection, FrameworkListener...)
+ */
+ public void refresh(Collection<Module> initial) throws ResolutionException {
+ initial = initial == null ? null : new ArrayList<Module>(initial);
+ Collection<Module> refreshTriggers = unresolve(initial);
+ if (!isRefreshingSystemModule()) {
+ resolve(refreshTriggers, false);
+ for (Module module : refreshTriggers) {
+ try {
+ module.start(StartOptions.TRANSIENT_RESUME);
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the dependency closure of for the specified modules.
+ * @param initial The initial modules for which to generate the dependency closure
+ * @return A collection containing a snapshot of the dependency closure of the specified
+ * modules, or an empty collection if there were no specified modules.
+ */
+ public Collection<Module> getDependencyClosure(Collection<Module> initial) {
+ moduleDatabase.lockRead();
+ try {
+ return getRefreshClosure(initial, moduleDatabase.getWiringsCopy());
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ /**
+ * Returns the revisions that have {@link ModuleWiring#isCurrent() non-current}, {@link ModuleWiring#isInUse() in use} module wirings.
+ * @return A collection containing a snapshot of the revisions which have non-current, in use ModuleWirings,
+ * or an empty collection if there are no such revisions.
+ */
+ public Collection<ModuleRevision> getRemovalPending() {
+ return moduleDatabase.getRemovalPending();
+ }
+
+ /**
+ * Return the active start level value of this container.
+ *
+ * If the container is in the process of changing the start level this
+ * method must return the active start level if this differs from the
+ * requested start level.
+ *
+ * @return The active start level value of the Framework.
+ */
+ public int getStartLevel() {
+ return frameworkStartLevel.getStartLevel();
+ }
+
+ void setStartLevel(Module module, int startlevel) {
+ frameworkStartLevel.setStartLevel(module, startlevel);
+ }
+
+ void open() {
+ loadModules();
+ frameworkStartLevel.open();
+ frameworkWiring.open();
+ synchronized (refreshingSystemModule) {
+ refreshingSystemModule.clear();
+ }
+ }
+
+ void close() {
+ frameworkStartLevel.close();
+ frameworkWiring.close();
+ unloadModules();
+ }
+
+ private void loadModules() {
+ List<Module> modules = null;
+ moduleDatabase.lockRead();
+ try {
+ modules = getModules();
+ for (Module module : modules) {
+ try {
+ module.lockStateChange(ModuleEvent.RESOLVED);
+ ModuleWiring wiring = moduleDatabase.getWiring(module.getCurrentRevision());
+ if (wiring != null) {
+ module.setState(State.RESOLVED);
+ } else {
+ module.setState(State.INSTALLED);
+ }
+ } catch (BundleException e) {
+ throw new IllegalStateException("Unable to lock module state.", e); //$NON-NLS-1$
+ }
+ }
+ Map<ModuleRevision, ModuleWiring> wirings = moduleDatabase.getWiringsCopy();
+ for (ModuleWiring wiring : wirings.values()) {
+ wiring.validate();
+ }
+ } finally {
+ if (modules != null) {
+ for (Module module : modules) {
+ try {
+ module.unlockStateChange(ModuleEvent.RESOLVED);
+ } catch (IllegalMonitorStateException e) {
+ // ignore
+ }
+ }
+ }
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ private void unloadModules() {
+ List<Module> modules = null;
+ moduleDatabase.lockRead();
+ try {
+ modules = getModules();
+ for (Module module : modules) {
+ if (module.getId() != 0) {
+ try {
+ module.lockStateChange(ModuleEvent.UNINSTALLED);
+ } catch (BundleException e) {
+ throw new IllegalStateException("Unable to lock module state.", e); //$NON-NLS-1$
+ }
+ module.setState(State.UNINSTALLED);
+ }
+ }
+ Map<ModuleRevision, ModuleWiring> wirings = moduleDatabase.getWiringsCopy();
+ for (ModuleWiring wiring : wirings.values()) {
+ wiring.invalidate();
+ }
+ } finally {
+ if (modules != null) {
+ for (Module module : modules) {
+ if (module.getId() != 0) {
+ try {
+ module.unlockStateChange(ModuleEvent.UNINSTALLED);
+ } catch (IllegalMonitorStateException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ public void setInitialModuleStates() throws BundleException {
+ moduleDatabase.lockRead();
+ try {
+ List<Module> modules = getModules();
+ for (Module module : modules) {
+ if (module.getId() == 0) {
+ module.lockStateChange(ModuleEvent.UNINSTALLED);
+ try {
+ module.setState(State.INSTALLED);
+ } finally {
+ module.unlockStateChange(ModuleEvent.UNINSTALLED);
+ }
+ } else {
+ module.lockStateChange(ModuleEvent.UNINSTALLED);
+ try {
+ module.setState(State.UNINSTALLED);
+ } finally {
+ module.unlockStateChange(ModuleEvent.UNINSTALLED);
+ }
+ }
+ }
+ Map<ModuleRevision, ModuleWiring> wirings = moduleDatabase.getWiringsCopy();
+ for (ModuleWiring wiring : wirings.values()) {
+ wiring.invalidate();
+ }
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ Collection<Module> getRefreshClosure(Collection<Module> initial, Map<ModuleRevision, ModuleWiring> wiringCopy) {
+ Set<Module> refreshClosure = new HashSet<Module>();
+ if (initial == null) {
+ initial = new HashSet<Module>();
+ Collection<ModuleRevision> removalPending = moduleDatabase.getRemovalPending();
+ for (ModuleRevision revision : removalPending) {
+ initial.add(revision.getRevisions().getModule());
+ }
+ }
+ for (Module module : initial)
+ addDependents(module, wiringCopy, refreshClosure);
+ return refreshClosure;
+ }
+
+ private static void addDependents(Module module, Map<ModuleRevision, ModuleWiring> wiringCopy, Set<Module> refreshClosure) {
+ if (refreshClosure.contains(module))
+ return;
+ refreshClosure.add(module);
+ List<ModuleRevision> revisions = module.getRevisions().getModuleRevisions();
+ for (ModuleRevision revision : revisions) {
+ ModuleWiring wiring = wiringCopy.get(revision);
+ if (wiring == null)
+ continue;
+ List<ModuleWire> provided = wiring.getProvidedModuleWires(null);
+ // add all requirers of the provided wires
+ for (ModuleWire providedWire : provided) {
+ addDependents(providedWire.getRequirer().getRevisions().getModule(), wiringCopy, refreshClosure);
+ }
+ // add all hosts of a fragment
+ if (revision.getTypes() == BundleRevision.TYPE_FRAGMENT) {
+ List<ModuleWire> hosts = wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ for (ModuleWire hostWire : hosts) {
+ addDependents(hostWire.getProvider().getRevisions().getModule(), wiringCopy, refreshClosure);
+ }
+ }
+ }
+ }
+
+ static Collection<ModuleRevision> getDependencyClosure(ModuleRevision initial, Map<ModuleRevision, ModuleWiring> wiringCopy) {
+ Set<ModuleRevision> dependencyClosure = new HashSet<ModuleRevision>();
+ addDependents(initial, wiringCopy, dependencyClosure);
+ return dependencyClosure;
+ }
+
+ private static void addDependents(ModuleRevision revision, Map<ModuleRevision, ModuleWiring> wiringCopy, Set<ModuleRevision> dependencyClosure) {
+ if (dependencyClosure.contains(revision))
+ return;
+ dependencyClosure.add(revision);
+ ModuleWiring wiring = wiringCopy.get(revision);
+ if (wiring == null)
+ return;
+ List<ModuleWire> provided = wiring.getProvidedModuleWires(null);
+ // add all requirers of the provided wires
+ for (ModuleWire providedWire : provided) {
+ addDependents(providedWire.getRequirer(), wiringCopy, dependencyClosure);
+ }
+ // add all hosts of a fragment
+ if (revision.getTypes() == BundleRevision.TYPE_FRAGMENT) {
+ List<ModuleWire> hosts = wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ for (ModuleWire hostWire : hosts) {
+ addDependents(hostWire.getProvider(), wiringCopy, dependencyClosure);
+ }
+ }
+ }
+
+ Bundle getSystemBundle() {
+ Module systemModule = moduleDatabase.getModule(0);
+ return systemModule == null ? null : systemModule.getBundle();
+ }
+
+ void checkAdminPermission(Bundle bundle, String action) {
+ if (bundle == null)
+ return;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AdminPermission(bundle, action));
+ }
+
+ void refreshSystemModule() {
+ final SystemModule systemModule = (SystemModule) moduleDatabase.getModule(0);
+ synchronized (refreshingSystemModule) {
+ if (refreshingSystemModule.contains(systemModule)) {
+ return;
+ }
+ refreshingSystemModule.add(systemModule);
+ getAdaptor().refreshedSystemModule();
+ }
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ systemModule.lockStateChange(ModuleEvent.UNRESOLVED);
+ try {
+ systemModule.stop();
+ } finally {
+ systemModule.unlockStateChange(ModuleEvent.UNRESOLVED);
+ }
+ } catch (BundleException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ t.start();
+ }
+
+ boolean isRefreshingSystemModule() {
+ synchronized (refreshingSystemModule) {
+ return !refreshingSystemModule.isEmpty();
+ }
+ }
+
+ class ContainerWiring implements FrameworkWiring, EventDispatcher<ContainerWiring, FrameworkListener[], Collection<Module>> {
+ private final Object monitor = new Object();
+ private EventManager refreshThread = null;
+
+ @Override
+ public Bundle getBundle() {
+ return getSystemBundle();
+ }
+
+ @Override
+ public void refreshBundles(Collection<Bundle> bundles, FrameworkListener... listeners) {
+ checkAdminPermission(getBundle(), AdminPermission.RESOLVE);
+ Collection<Module> modules = getModules(bundles);
+
+ // queue to refresh in the background
+ // notice that we only do one refresh operation at a time
+ CopyOnWriteIdentityMap<ContainerWiring, FrameworkListener[]> dispatchListeners = new CopyOnWriteIdentityMap<ModuleContainer.ContainerWiring, FrameworkListener[]>();
+ dispatchListeners.put(this, listeners);
+ ListenerQueue<ContainerWiring, FrameworkListener[], Collection<Module>> queue = new ListenerQueue<ModuleContainer.ContainerWiring, FrameworkListener[], Collection<Module>>(getManager());
+ queue.queueListeners(dispatchListeners.entrySet(), this);
+
+ // dispatch the refresh job
+ queue.dispatchEventAsynchronous(0, modules);
+ }
+
+ @Override
+ public boolean resolveBundles(Collection<Bundle> bundles) {
+ checkAdminPermission(getBundle(), AdminPermission.RESOLVE);
+ Collection<Module> modules = getModules(bundles);
+ try {
+ resolve(modules, false);
+ } catch (ResolutionException e) {
+ return false;
+ }
+ if (modules == null) {
+ modules = ModuleContainer.this.getModules();
+ }
+ for (Module module : modules) {
+ if (getWiring(module.getCurrentRevision()) == null)
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public Collection<Bundle> getRemovalPendingBundles() {
+ moduleDatabase.lockRead();
+ try {
+ Collection<Bundle> removalPendingBundles = new HashSet<Bundle>();
+ Collection<ModuleRevision> removalPending = moduleDatabase.getRemovalPending();
+ for (ModuleRevision moduleRevision : removalPending) {
+ removalPendingBundles.add(moduleRevision.getBundle());
+ }
+ return removalPendingBundles;
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ @Override
+ public Collection<Bundle> getDependencyClosure(Collection<Bundle> bundles) {
+ Collection<Module> modules = getModules(bundles);
+ moduleDatabase.lockRead();
+ try {
+ Collection<Module> closure = getRefreshClosure(modules, moduleDatabase.getWiringsCopy());
+ Collection<Bundle> result = new ArrayList<Bundle>(closure.size());
+ for (Module module : closure) {
+ result.add(module.getBundle());
+ }
+ return result;
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ private Collection<Module> getModules(final Collection<Bundle> bundles) {
+ if (bundles == null)
+ return null;
+ return AccessController.doPrivileged(new PrivilegedAction<Collection<Module>>() {
+ @Override
+ public Collection<Module> run() {
+ Collection<Module> result = new ArrayList<Module>(bundles.size());
+ for (Bundle bundle : bundles) {
+ Module module = bundle.adapt(Module.class);
+ if (module == null)
+ throw new IllegalStateException("Could not adapt a bundle to a module."); //$NON-NLS-1$
+ result.add(module);
+ }
+ return result;
+ }
+ });
+ }
+
+ @Override
+ public void dispatchEvent(ContainerWiring eventListener, FrameworkListener[] frameworkListeners, int eventAction, Collection<Module> eventObject) {
+ try {
+ refresh(eventObject);
+ } catch (ResolutionException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, moduleDatabase.getModule(0), e);
+ } finally {
+ adaptor.publishContainerEvent(ContainerEvent.REFRESH, moduleDatabase.getModule(0), null, frameworkListeners);
+ }
+ }
+
+ private EventManager getManager() {
+ synchronized (monitor) {
+ if (refreshThread == null) {
+ refreshThread = new EventManager("Refresh Thread: " + adaptor.toString()); //$NON-NLS-1$
+ }
+ return refreshThread;
+ }
+ }
+
+ // because of bug 378491 we have to synchronize access to the manager
+ // so we can close and re-open ourselves
+ void close() {
+ synchronized (monitor) {
+ // force a manager to be created if it did not exist
+ EventManager manager = getManager();
+ // this prevents any operations until open is called
+ manager.close();
+ }
+ }
+
+ void open() {
+ synchronized (monitor) {
+ if (refreshThread != null) {
+ // Make sure it is closed just incase
+ refreshThread.close();
+ // a new one will be constructed on demand
+ refreshThread = null;
+ }
+ }
+ }
+ }
+
+ class ContainerStartLevel implements FrameworkStartLevel, EventDispatcher<Module, FrameworkListener[], Integer> {
+ static final int USE_BEGINNING_START_LEVEL = Integer.MIN_VALUE;
+ private static final int FRAMEWORK_STARTLEVEL = 1;
+ private static final int MODULE_STARTLEVEL = 2;
+ private final AtomicInteger activeStartLevel = new AtomicInteger(0);
+ private final Object eventManagerLock = new Object();
+ private EventManager startLevelThread = null;
+ private final Object frameworkStartLevelLock = new Object();
+
+ @Override
+ public Bundle getBundle() {
+ return getSystemBundle();
+ }
+
+ @Override
+ public int getStartLevel() {
+ return activeStartLevel.get();
+ }
+
+ void setStartLevel(Module module, int startlevel) {
+ checkAdminPermission(module.getBundle(), AdminPermission.EXECUTE);
+ if (module.getId() == 0) {
+ throw new IllegalArgumentException("Cannot set the start level of the system bundle.");
+ }
+ if (startlevel < 1) {
+ throw new IllegalArgumentException("Cannot set the start level to less than 1: " + startlevel);
+ }
+ if (module.getStartLevel() == startlevel) {
+ return; // do nothing
+ }
+ moduleDatabase.setStartLevel(module, startlevel);
+ // queue start level operation in the background
+ // notice that we only do one start level operation at a time
+ CopyOnWriteIdentityMap<Module, FrameworkListener[]> dispatchListeners = new CopyOnWriteIdentityMap<Module, FrameworkListener[]>();
+ dispatchListeners.put(module, new FrameworkListener[0]);
+ ListenerQueue<Module, FrameworkListener[], Integer> queue = new ListenerQueue<Module, FrameworkListener[], Integer>(getManager());
+ queue.queueListeners(dispatchListeners.entrySet(), this);
+
+ // dispatch the start level job
+ queue.dispatchEventAsynchronous(MODULE_STARTLEVEL, startlevel);
+ }
+
+ @Override
+ public void setStartLevel(int startlevel, FrameworkListener... listeners) {
+ checkAdminPermission(getBundle(), AdminPermission.STARTLEVEL);
+ if (startlevel < 1) {
+ throw new IllegalArgumentException("Cannot set the start level to less than 1: " + startlevel);
+ }
+
+ if (activeStartLevel.get() == 0) {
+ throw new IllegalStateException("The system has not be activated yet.");
+ }
+ // queue start level operation in the background
+ // notice that we only do one start level operation at a time
+ CopyOnWriteIdentityMap<Module, FrameworkListener[]> dispatchListeners = new CopyOnWriteIdentityMap<Module, FrameworkListener[]>();
+ dispatchListeners.put(moduleDatabase.getModule(0), listeners);
+ ListenerQueue<Module, FrameworkListener[], Integer> queue = new ListenerQueue<Module, FrameworkListener[], Integer>(getManager());
+ queue.queueListeners(dispatchListeners.entrySet(), this);
+
+ // dispatch the start level job
+ queue.dispatchEventAsynchronous(FRAMEWORK_STARTLEVEL, startlevel);
+ }
+
+ @Override
+ public int getInitialBundleStartLevel() {
+ return moduleDatabase.getInitialModuleStartLevel();
+ }
+
+ @Override
+ public void setInitialBundleStartLevel(int startlevel) {
+ checkAdminPermission(getBundle(), AdminPermission.STARTLEVEL);
+ moduleDatabase.setInitialModuleStartLevel(startlevel);
+ }
+
+ @Override
+ public void dispatchEvent(Module module, FrameworkListener[] listeners, int eventAction, Integer startlevel) {
+ switch (eventAction) {
+ case FRAMEWORK_STARTLEVEL :
+ doContainerStartLevel(module, startlevel, listeners);
+ break;
+ case MODULE_STARTLEVEL :
+ try {
+ if (getStartLevel() < startlevel) {
+ if (Module.ACTIVE_SET.contains(module.getState())) {
+ // Note that we don't need to hold the state change lock
+ // here when checking the active status because no other
+ // thread will successfully be able to start this bundle
+ // since the start-level is no longer met.
+ module.stop(StopOptions.TRANSIENT);
+ }
+ } else {
+ module.start(StartOptions.TRANSIENT_IF_AUTO_START, StartOptions.TRANSIENT_RESUME);
+ }
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ break;
+ default :
+ break;
+ }
+ }
+
+ void doContainerStartLevel(Module module, int newStartLevel, FrameworkListener... listeners) {
+ synchronized (frameworkStartLevelLock) {
+ if (newStartLevel == USE_BEGINNING_START_LEVEL) {
+ String beginningSL = adaptor.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL);
+ newStartLevel = beginningSL == null ? 1 : Integer.parseInt(beginningSL);
+ }
+ try {
+ int currentSL = getStartLevel();
+ // Note that we must get a new list of modules each time;
+ // this is because additional modules could have been installed from the previous start-level
+ if (newStartLevel > currentSL) {
+ for (int i = currentSL; i < newStartLevel; i++) {
+ int toStartLevel = i + 1;
+ activeStartLevel.set(toStartLevel);
+ incStartLevel(toStartLevel, moduleDatabase.getSortedModules(Sort.BY_START_LEVEL));
+ }
+ } else {
+ for (int i = currentSL; i > newStartLevel; i--) {
+ int toStartLevel = i - 1;
+ activeStartLevel.set(toStartLevel);
+ decStartLevel(toStartLevel, moduleDatabase.getSortedModules(Sort.BY_START_LEVEL, Sort.BY_DEPENDENCY));
+ }
+ }
+ adaptor.publishContainerEvent(ContainerEvent.START_LEVEL, module, null, listeners);
+ } catch (Error e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e, listeners);
+ throw e;
+ } catch (RuntimeException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e, listeners);
+ throw e;
+ }
+ }
+ }
+
+ private void incStartLevel(int toStartLevel, List<Module> sortedModules) {
+ incStartLevel(toStartLevel, sortedModules, true);
+ incStartLevel(toStartLevel, sortedModules, false);
+ }
+
+ private void incStartLevel(int toStartLevel, List<Module> sortedModules, boolean lazyOnly) {
+ for (Module module : sortedModules) {
+ if (isRefreshingSystemModule()) {
+ return;
+ }
+ try {
+ int moduleStartLevel = module.getStartLevel();
+ if (moduleStartLevel < toStartLevel) {
+ // skip modules who should have already been started
+ continue;
+ } else if (moduleStartLevel == toStartLevel) {
+ boolean isLazyStart = module.isLazyActivate();
+ if (lazyOnly ? isLazyStart : !isLazyStart) {
+ try {
+ module.start(StartOptions.TRANSIENT_IF_AUTO_START, StartOptions.TRANSIENT_RESUME);
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
+ } catch (IllegalStateException e) {
+ // been uninstalled
+ continue;
+ }
+ }
+ } else {
+ // can stop resuming since any remaining modules have a greater startlevel than the active startlevel
+ break;
+ }
+ } catch (IllegalStateException e) {
+ // been uninstalled
+ continue;
+ }
+ }
+ }
+
+ private void decStartLevel(int toStartLevel, List<Module> sortedModules) {
+ ListIterator<Module> iModules = sortedModules.listIterator(sortedModules.size());
+ while (iModules.hasPrevious()) {
+ Module module = iModules.previous();
+ try {
+ int moduleStartLevel = module.getStartLevel();
+ if (moduleStartLevel > toStartLevel + 1) {
+ // skip modules who should have already been stopped
+ continue;
+ } else if (moduleStartLevel <= toStartLevel) {
+ // stopped all modules we are going to for this start level
+ break;
+ }
+ try {
+ if (Module.ACTIVE_SET.contains(module.getState())) {
+ // Note that we don't need to hold the state change lock
+ // here when checking the active status because no other
+ // thread will successfully be able to start this bundle
+ // since the start-level is no longer met.
+ module.stop(StopOptions.TRANSIENT);
+ }
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ } catch (IllegalStateException e) {
+ // been uninstalled
+ continue;
+ }
+ }
+ }
+
+ private EventManager getManager() {
+ synchronized (eventManagerLock) {
+ if (startLevelThread == null) {
+ startLevelThread = new EventManager("Start Level: " + adaptor.toString()); //$NON-NLS-1$
+ }
+ return startLevelThread;
+ }
+ }
+
+ // because of bug 378491 we have to synchronize access to the manager
+ // so we can close and re-open ourselves
+ void close() {
+ synchronized (eventManagerLock) {
+ // force a manager to be created if it did not exist
+ EventManager manager = getManager();
+ // this prevents any operations until open is called
+ manager.close();
+ }
+ }
+
+ void open() {
+ synchronized (eventManagerLock) {
+ if (startLevelThread != null) {
+ // Make sure it is closed just incase
+ startLevelThread.close();
+ // a new one will be constructed on demand
+ startLevelThread = null;
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java
new file mode 100644
index 000000000..20684ff44
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.io.DataInputStream;
+import java.util.EnumSet;
+import org.apache.felix.resolver.Logger;
+import org.apache.felix.resolver.ResolverImpl;
+import org.eclipse.osgi.container.Module.Settings;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.osgi.service.resolver.Resolver;
+
+/**
+ * Adapts the behavior of a container.
+ * @since 3.10
+ */
+public abstract class ModuleContainerAdaptor {
+ public enum ContainerEvent {
+ REFRESH, START_LEVEL, STARTED, STOPPED, STOPPED_UPDATE, STOPPED_REFRESH, STOPPED_TIMEOUT, ERROR, WARNING, INFO
+ }
+
+ /**
+ * Event types that may be {@link #publishModuleEvent(ModuleEvent, Module, Module) published} for a module
+ * indicating a {@link Module#getState() state} change has occurred for a module.
+ */
+ public static enum ModuleEvent {
+ /**
+ * The module has been installed
+ */
+ INSTALLED,
+ /**
+ * The module has been activated with the lazy activation policy and
+ * is waiting a {@link Module.StartOptions#LAZY_TRIGGER trigger} class load.
+ */
+ LAZY_ACTIVATION,
+ /**
+ * The module has been resolved.
+ */
+ RESOLVED,
+ /**
+ * The module has beens started.
+ */
+ STARTED,
+ /**
+ * The module is about to be activated.
+ */
+ STARTING,
+ /**
+ * The module has been stopped.
+ */
+ STOPPED,
+ /**
+ * The module is about to be deactivated.
+ */
+ STOPPING,
+ /**
+ * The module has been uninstalled.
+ */
+ UNINSTALLED,
+ /**
+ * The module has been unresolved.
+ */
+ UNRESOLVED,
+ /**
+ * The module has been updated.
+ */
+ UPDATED
+ }
+
+ /**
+ * Returns the resolver the container will use. This implementation will
+ * return the default implementation of the resolver. Override this method
+ * to provide an alternative resolver implementation for the container.
+ * @return the resolver the container will use.
+ */
+ public Resolver getResolver() {
+ return new ResolverImpl(new Logger(4));
+ }
+
+ /**
+ * Returns the collision hook the container will use.
+ * @return the collision hook the container will use.
+ */
+ public abstract ModuleCollisionHook getModuleCollisionHook();
+
+ /**
+ * Returns the resolver hook factory the container will use.
+ * @return the resolver hook factory the container will use.
+ */
+ public abstract ResolverHookFactory getResolverHookFactory();
+
+ /**
+ * Publishes the specified container event.
+ * No locks are held by the container when this method is called
+ * @param type the type of event
+ * @param module the module associated with the event
+ * @param error the error associated with the event, may be {@code null}
+ * @param listeners additional listeners to publish the event to synchronously
+ */
+ public abstract void publishContainerEvent(ContainerEvent type, Module module, Throwable error, FrameworkListener... listeners);
+
+ /**
+ * Publishes the specified module event type for the specified module.
+ * No locks are held by the container when this method is called
+ * @param type the event type to publish
+ * @param module the module the event is associated with
+ * @param origin the module which is the origin of the event. For the event
+ * type {@link ModuleEvent#INSTALLED}, this is the module whose context was used
+ * to install the module. Otherwise it is the module itself. May be null only
+ * when the event is not of type {@link ModuleEvent#INSTALLED}.
+ */
+ public abstract void publishModuleEvent(ModuleEvent type, Module module, Module origin);
+
+ /**
+ * Returns the specified configuration property value
+ * @param key the key of the configuration property
+ * @return the configuration property value
+ */
+ public String getProperty(String key) {
+ return null;
+ }
+
+ /**
+ * Creates a new {@link ModuleLoader} for the specified wiring.
+ * @param wiring the module wiring to create a module loader for
+ * @return a new {@link ModuleLoader} for the specified wiring.
+ */
+ public ModuleLoader createModuleLoader(ModuleWiring wiring) {
+ throw new UnsupportedOperationException("Container adaptor does not support module class loaders.");
+ }
+
+ /**
+ * Creates a new module. This gets called when a new module is installed
+ * or when {@link ModuleDatabase#load(DataInputStream) loading} persistent data into this
+ * database.
+ * @param location the location for the module
+ * @param id the id for the module
+ * @param settings the settings for the module. May be {@code null} if there are no settings.
+ * @param startlevel the start level for the module
+ * @return the Module
+ */
+ public abstract Module createModule(String location, long id, EnumSet<Settings> settings, int startlevel);
+
+ /**
+ * Creates the system module. This gets called when the system module is installed
+ * or when {@link ModuleDatabase#load(DataInputStream) loading} persistent data into this
+ * database.
+ * <p>
+ * The returned system module must have an {@link Module#getId() id} of zero and a location
+ * of {@link Constants#SYSTEM_BUNDLE_LOCATION System Bundle}.
+ * @return the system module
+ */
+ public abstract SystemModule createSystemModule();
+
+ /**
+ * Returns the current revision info for a module with the specified location and id
+ * @param location the location of the module
+ * @param id the id of the module
+ * @return the revision info, may be {@code null}
+ */
+ public Object getRevisionInfo(String location, long id) {
+ return null;
+ }
+
+ /**
+ * After a revision is created this method is called with the specified revision info.
+ * @param revision the newly created revision
+ * @param revisionInfo the revision info that got associated with the revision
+ */
+ public void associateRevision(ModuleRevision revision, Object revisionInfo) {
+ // do nothing by default
+ }
+
+ /**
+ * This is called when a wiring is made invalid and allows the adaptor to react
+ * to this. This method is called while holding state change lock for the
+ * module as well as for the module database. Care must be taken not to introduce
+ * deadlock.
+ * @param moduleWiring the module wiring being invalidated
+ * @param current the current module loader associated with the wiring
+ */
+ public void invalidateWiring(ModuleWiring moduleWiring, ModuleLoader current) {
+ // do nothing by default
+ }
+
+ /**
+ * This is called if a request to refresh modules causes the system module
+ * to be refreshed. This causes the system module to be stopped in a back
+ * ground thread. This method is called before the background thread is
+ * started to stop the system module.
+ */
+ public void refreshedSystemModule() {
+ // do nothing by default
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java
new file mode 100644
index 000000000..570c9fd25
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java
@@ -0,0 +1,1564 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+import org.eclipse.osgi.container.Module.Settings;
+import org.eclipse.osgi.container.Module.State;
+import org.eclipse.osgi.container.ModuleRevisionBuilder.GenericInfo;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
+import org.eclipse.osgi.framework.util.ObjectPool;
+import org.eclipse.osgi.internal.container.Capabilities;
+import org.eclipse.osgi.internal.container.ComputeNodeOrder;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.*;
+import org.osgi.service.resolver.Resolver;
+
+/**
+ * A database for storing modules, their revisions and wiring states. The
+ * database is responsible for assigning ids and providing access to the
+ * capabilities provided by the revisions currently installed as well as
+ * the wiring states.
+ * <p>
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations must be thread safe. The database allows for concurrent
+ * read operations and all read operations are protected by the
+ * {@link #lockRead() read} lock. All write operations are
+ * protected by the {@link #lockWrite() write} lock. The read and write
+ * locks are reentrant and follow the semantics of the
+ * {@link ReentrantReadWriteLock}. Just like the {@code ReentrantReadWriteLock}
+ * the lock on a database can not be upgraded from a read to a write. Doing so will result in an
+ * {@link IllegalMonitorStateException} being thrown. This is behavior is different from
+ * the {@code ReentrantReadWriteLock} which results in a deadlock if an attempt is made
+ * to upgrade from a read to a write lock.
+ * <p>
+ * A database is associated with a {@link ModuleContainer container}. The container
+ * associated with a database provides public API for manipulating the modules
+ * and their wiring states. For example, installing, updating, uninstalling,
+ * resolving and unresolving modules. Except for the {@link #load(DataInputStream)},
+ * all other methods that perform write operations are intended to be used by
+ * the associated container.
+ * @since 3.10
+ */
+public class ModuleDatabase {
+ /**
+ * The adaptor for this database
+ */
+ private final ModuleContainerAdaptor adaptor;
+
+ /**
+ * A map of modules by location.
+ */
+ private final Map<String, Module> modulesByLocations;
+
+ /**
+ * A map of modules by id.
+ */
+ private final Map<Long, Module> modulesById;
+
+ /**
+ * A map of revision collections by symbolic name
+ */
+ private final Map<String, Collection<ModuleRevision>> revisionByName;
+
+ /**
+ * A map of revision wiring objects.
+ */
+ private final Map<ModuleRevision, ModuleWiring> wirings;
+
+ /**
+ * Holds the next id to be assigned to a module when it is installed
+ */
+ final AtomicLong nextId;
+
+ /**
+ * Holds the current timestamp for revisions of this database.
+ */
+ final AtomicLong revisionsTimeStamp;
+
+ /**
+ * Holds the current timestamp for all changes to this database.
+ * This includes changes to revisions and changes to module settings.
+ */
+ final AtomicLong allTimeStamp;
+
+ private final Capabilities capabilities;
+
+ /**
+ * A map of module settings keyed by module id.
+ */
+ private final Map<Long, EnumSet<Settings>> moduleSettings;
+
+ /**
+ * The initial module start level.
+ */
+ private int initialModuleStartLevel = 1;
+
+ /**
+ * Monitors read and write access to this database
+ */
+ private final ReentrantReadWriteLock monitor = new ReentrantReadWriteLock(true);
+
+ static enum Sort {
+ BY_DEPENDENCY, BY_START_LEVEL, BY_ID;
+ /**
+ * Tests if this option is contained in the specified options
+ */
+ public boolean isContained(Sort... options) {
+ for (Sort option : options) {
+ if (equals(option)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Constructs a new empty database.
+ */
+ public ModuleDatabase(ModuleContainerAdaptor adaptor) {
+ this.adaptor = adaptor;
+ this.modulesByLocations = new HashMap<String, Module>();
+ this.modulesById = new HashMap<Long, Module>();
+ this.revisionByName = new HashMap<String, Collection<ModuleRevision>>();
+ this.wirings = new HashMap<ModuleRevision, ModuleWiring>();
+ // Start at id 1 because 0 is reserved for the system bundle
+ this.nextId = new AtomicLong(1);
+ this.revisionsTimeStamp = new AtomicLong(0);
+ this.allTimeStamp = new AtomicLong(0);
+ this.moduleSettings = new HashMap<Long, EnumSet<Settings>>();
+ this.capabilities = new Capabilities();
+ }
+
+ /**
+ * Returns the module at the given location or null if no module exists
+ * at the given location.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @param location the location of the module.
+ * @return the module at the given location or null.
+ */
+ final Module getModule(String location) {
+ lockRead();
+ try {
+ return modulesByLocations.get(location);
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns the module at the given id or null if no module exists
+ * at the given location.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @param id the id of the module.
+ * @return the module at the given id or null.
+ */
+ final Module getModule(long id) {
+ lockRead();
+ try {
+ return modulesById.get(id);
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns a snapshot collection of revisions with the specified name
+ * and version. If version is {@code null} then all revisions with
+ * the specified name are returned.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @param name the name of the modules
+ * @param version the version of the modules or {@code null}
+ * @return a snapshot collection of revisions with the specified name
+ * and version.
+ */
+ final Collection<ModuleRevision> getRevisions(String name, Version version) {
+ lockRead();
+ try {
+ Collection<ModuleRevision> existingRevisions = revisionByName.get(name);
+
+ if (existingRevisions == null) {
+ return Collections.emptyList();
+ }
+
+ if (version == null) {
+ return new ArrayList<ModuleRevision>(existingRevisions);
+ }
+
+ Collection<ModuleRevision> sameVersion = new ArrayList<ModuleRevision>(1);
+ for (ModuleRevision revision : existingRevisions) {
+ if (revision.getVersion().equals(version)) {
+ sameVersion.add(revision);
+ }
+ }
+ return sameVersion;
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns a snapshot collection of current revisions which are fragments
+
+ * @return a snapshot collection of current revisions which are fragments
+ */
+ final Collection<ModuleRevision> getFragmentRevisions() {
+ Collection<ModuleRevision> fragments = new ArrayList<ModuleRevision>();
+ lockRead();
+ try {
+ for (Module module : modulesById.values()) {
+ ModuleRevision revision = module.getCurrentRevision();
+ if (revision != null && ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0)) {
+ fragments.add(revision);
+ }
+ }
+ return fragments;
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Installs a new revision using the specified builder, location and module.
+ * <p>
+ * A write operation protected by the {@link #lockWrite() write} lock.
+ * @param location the location to use for the installation
+ * @param builder the builder to use to create the new revision
+ * @param revisionInfo the revision info for the new revision, may be {@code null}.
+ * @return the installed module
+ */
+ final Module install(String location, ModuleRevisionBuilder builder, Object revisionInfo) {
+ lockWrite();
+ try {
+ int startlevel = Constants.SYSTEM_BUNDLE_LOCATION.equals(location) ? 0 : getInitialModuleStartLevel();
+ long id = Constants.SYSTEM_BUNDLE_LOCATION.equals(location) ? 0 : getNextIdAndIncrement();
+ EnumSet<Settings> settings = getActivationPolicySettings(builder);
+ Module module = load(location, builder, revisionInfo, id, settings, startlevel);
+ long currentTime = System.currentTimeMillis();
+ module.setlastModified(currentTime);
+ setSystemLastModified(currentTime);
+ incrementTimestamps(true);
+ return module;
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ private EnumSet<Settings> getActivationPolicySettings(ModuleRevisionBuilder builder) {
+ for (GenericInfo info : builder.getCapabilities()) {
+ if (EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE.equals(info.getNamespace())) {
+ if (EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY_LAZY.equals(info.getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY))) {
+ // TODO hack until p2 is fixed (bug 177641)
+ EnumSet<Settings> settings = EnumSet.noneOf(Settings.class);
+ settings.add(Settings.USE_ACTIVATION_POLICY);
+ settings.add(Settings.AUTO_START);
+ return settings;
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ final Module load(String location, ModuleRevisionBuilder builder, Object revisionInfo, long id, EnumSet<Settings> settings, int startlevel) {
+ // sanity check
+ checkWrite();
+ if (modulesByLocations.containsKey(location))
+ throw new IllegalArgumentException("Location is already used: " + location); //$NON-NLS-1$
+ if (modulesById.containsKey(id))
+ throw new IllegalArgumentException("Id is already used: " + id); //$NON-NLS-1$
+ Module module;
+ if (id == 0) {
+ module = adaptor.createSystemModule();
+ } else {
+ module = adaptor.createModule(location, id, settings, startlevel);
+ }
+ builder.addRevision(module, revisionInfo);
+ modulesByLocations.put(location, module);
+ modulesById.put(id, module);
+ if (settings != null)
+ moduleSettings.put(id, settings);
+ ModuleRevision newRevision = module.getCurrentRevision();
+ addToRevisionByName(newRevision);
+ addCapabilities(newRevision);
+ return module;
+ }
+
+ private void addToRevisionByName(ModuleRevision revision) {
+ // sanity check
+ checkWrite();
+
+ String name = revision.getSymbolicName();
+ Collection<ModuleRevision> sameName = revisionByName.get(name);
+ if (sameName == null) {
+ sameName = new ArrayList<ModuleRevision>(1);
+ revisionByName.put(name, sameName);
+ }
+ sameName.add(revision);
+ }
+
+ /**
+ * Uninstalls the specified module from this database.
+ * Uninstalling a module will attempt to clean up any removal pending
+ * revisions possible.
+ * <p>
+ * A write operation protected by the {@link #lockWrite() write} lock.
+ * @param module the module to uninstall
+ */
+ final void uninstall(Module module) {
+ lockWrite();
+ try {
+ ModuleRevisions uninstalling = module.getRevisions();
+ // mark the revisions as uninstalled before removing the revisions
+ uninstalling.uninstall();
+ // remove the location
+ modulesByLocations.remove(module.getLocation());
+ modulesById.remove(module.getId());
+ moduleSettings.remove(module.getId());
+ // remove the revisions by name
+ List<ModuleRevision> revisions = uninstalling.getModuleRevisions();
+ for (ModuleRevision revision : revisions) {
+ removeCapabilities(revision);
+ String name = revision.getSymbolicName();
+ if (name != null) {
+ Collection<ModuleRevision> sameName = revisionByName.get(name);
+ if (sameName != null) {
+ sameName.remove(revision);
+ }
+ }
+ // if the revision does not have a wiring it can safely be removed
+ // from the revisions for the module
+ ModuleWiring oldWiring = wirings.get(revision);
+ if (oldWiring == null) {
+ module.getRevisions().removeRevision(revision);
+ }
+ }
+
+ // attempt to cleanup any removal pendings
+ cleanupRemovalPending();
+ long currentTime = System.currentTimeMillis();
+ module.setlastModified(currentTime);
+ setSystemLastModified(currentTime);
+ incrementTimestamps(true);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ /**
+ * Updates the specified module with anew revision using the specified builder.
+ * <p>
+ * A write operation protected by the {@link #lockWrite() write} lock.
+ * @param module the module for which the revision provides an update for
+ * @param builder the builder to use to create the new revision
+ * @param revisionInfo the revision info for the new revision, may be {@code null}.
+ */
+ final void update(Module module, ModuleRevisionBuilder builder, Object revisionInfo) {
+ lockWrite();
+ try {
+ ModuleRevision oldRevision = module.getCurrentRevision();
+ ModuleRevision newRevision = builder.addRevision(module, revisionInfo);
+ String name = newRevision.getSymbolicName();
+ Collection<ModuleRevision> sameName = revisionByName.get(name);
+ if (sameName == null) {
+ sameName = new ArrayList<ModuleRevision>(1);
+ revisionByName.put(name, sameName);
+ }
+ sameName.add(newRevision);
+ addCapabilities(newRevision);
+
+ // remove the old revision by name
+ String oldName = oldRevision.getSymbolicName();
+ if (oldName != null) {
+ Collection<ModuleRevision> oldSameName = revisionByName.get(oldName);
+ if (oldSameName != null) {
+ oldSameName.remove(oldRevision);
+ }
+ }
+
+ // if the old revision does not have a wiring it can safely be removed
+ ModuleWiring oldWiring = wirings.get(oldRevision);
+ if (oldWiring == null) {
+ module.getRevisions().removeRevision(oldRevision);
+ removeCapabilities(oldRevision);
+ }
+ // attempt to clean up removal pendings
+ cleanupRemovalPending();
+
+ long currentTime = System.currentTimeMillis();
+ module.setlastModified(currentTime);
+ setSystemLastModified(currentTime);
+ incrementTimestamps(true);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ /**
+ * Examines the wirings to determine if there are any removal
+ * pending wiring objects that can be removed. We consider
+ * a removal pending wiring as removable if all dependent
+ * wiring are also removal pending.
+ */
+ private void cleanupRemovalPending() {
+ // sanity check
+ checkWrite();
+ Collection<ModuleRevision> removalPending = getRemovalPending();
+ for (ModuleRevision removed : removalPending) {
+ if (wirings.get(removed) == null)
+ continue;
+ Collection<ModuleRevision> dependencyClosure = ModuleContainer.getDependencyClosure(removed, wirings);
+ boolean allPendingRemoval = true;
+ for (ModuleRevision pendingRemoval : dependencyClosure) {
+ if (pendingRemoval.isCurrent()) {
+ allPendingRemoval = false;
+ break;
+ }
+ }
+ if (allPendingRemoval) {
+ for (ModuleRevision pendingRemoval : dependencyClosure) {
+ pendingRemoval.getRevisions().removeRevision(pendingRemoval);
+ removeCapabilities(pendingRemoval);
+ wirings.remove(pendingRemoval);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets all revisions with a removal pending wiring.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return all revisions with a removal pending wiring.
+ */
+ final Collection<ModuleRevision> getRemovalPending() {
+ Collection<ModuleRevision> removalPending = new ArrayList<ModuleRevision>();
+ lockRead();
+ try {
+ for (ModuleWiring wiring : wirings.values()) {
+ if (!wiring.isCurrent())
+ removalPending.add(wiring.getRevision());
+ }
+ } finally {
+ unlockRead();
+ }
+ return removalPending;
+ }
+
+ /**
+ * Returns the current wiring for the specified revision or
+ * null of no wiring exists for the revision.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @param revision the revision to get the wiring for
+ * @return the current wiring for the specified revision.
+ */
+ final ModuleWiring getWiring(ModuleRevision revision) {
+ lockRead();
+ try {
+ return wirings.get(revision);
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns a snapshot of the wirings for all revisions. This
+ * performs a shallow copy of each entry in the wirings map.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return a snapshot of the wirings for all revisions.
+ */
+ final Map<ModuleRevision, ModuleWiring> getWiringsCopy() {
+ lockRead();
+ try {
+ return new HashMap<ModuleRevision, ModuleWiring>(wirings);
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns a cloned snapshot of the wirings of all revisions. This
+ * performs a clone of each {@link ModuleWiring}. The
+ * {@link ModuleWiring#getRevision() revision},
+ * {@link ModuleWiring#getModuleCapabilities(String) capabilities},
+ * {@link ModuleWiring#getModuleRequirements(String) requirements},
+ * {@link ModuleWiring#getProvidedModuleWires(String) provided wires}, and
+ * {@link ModuleWiring#getRequiredModuleWires(String) required wires} of
+ * each wiring are copied into a cloned copy of the wiring.
+ * <p>
+ * The returned map of wirings may be safely read from while not holding
+ * any read or write locks on this database. This is useful for doing
+ * {@link Resolver#resolve(org.osgi.service.resolver.ResolveContext) resolve}
+ * operations without holding the read or write lock on this database.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return a cloned snapshot of the wirings of all revisions.
+ */
+ final Map<ModuleRevision, ModuleWiring> getWiringsClone() {
+ lockRead();
+ try {
+ Map<ModuleRevision, ModuleWiring> clonedWirings = new HashMap<ModuleRevision, ModuleWiring>();
+ for (Map.Entry<ModuleRevision, ModuleWiring> entry : wirings.entrySet()) {
+ ModuleWiring wiring = new ModuleWiring(entry.getKey(), entry.getValue().getModuleCapabilities(null), entry.getValue().getModuleRequirements(null), entry.getValue().getProvidedModuleWires(null), entry.getValue().getRequiredModuleWires(null), entry.getValue().getSubstitutedNames());
+ clonedWirings.put(entry.getKey(), wiring);
+ }
+ return clonedWirings;
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Replaces the complete wiring map with the specified wiring
+ * <p>
+ * A write operation protected by the {@link #lockWrite() write} lock.
+ * @param newWiring the new wiring to take effect. The values
+ * from the new wiring are copied.
+ */
+ final void setWiring(Map<ModuleRevision, ModuleWiring> newWiring) {
+ lockWrite();
+ try {
+ wirings.clear();
+ wirings.putAll(newWiring);
+ incrementTimestamps(true);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ /**
+ * Adds all the values from the specified delta wirings to the
+ * wirings current wirings
+ * <p>
+ * A write operation protected by the {@link #lockWrite() write} lock.
+ * @param deltaWiring the new wiring values to take effect.
+ * The values from the delta wiring are copied.
+ */
+ final void mergeWiring(Map<ModuleRevision, ModuleWiring> deltaWiring) {
+ lockWrite();
+ try {
+ wirings.putAll(deltaWiring);
+ incrementTimestamps(true);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ /**
+ * Returns a snapshot of all modules ordered by module ID.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return a snapshot of all modules.
+ */
+ final List<Module> getModules() {
+ return getSortedModules();
+ }
+
+ /**
+ * Returns a snapshot of all modules ordered according to the sort options
+ * @param sortOptions options for sorting
+ * @return a snapshot of all modules ordered according to the sort options
+ */
+ final List<Module> getSortedModules(Sort... sortOptions) {
+ lockRead();
+ try {
+ List<Module> modules = new ArrayList<Module>(modulesByLocations.values());
+ sortModules(modules, sortOptions);
+ return modules;
+ } finally {
+ unlockRead();
+ }
+ }
+
+ final void sortModules(List<Module> modules, Sort... sortOptions) {
+ if (modules.size() < 2)
+ return;
+ if (sortOptions == null || Sort.BY_ID.isContained(sortOptions) || sortOptions.length == 0) {
+ Collections.sort(modules, new Comparator<Module>() {
+ @Override
+ public int compare(Module m1, Module m2) {
+ return m1.getId().compareTo(m2.getId());
+ }
+ });
+ return;
+ }
+ // first sort by start-level
+ if (Sort.BY_START_LEVEL.isContained(sortOptions)) {
+ Collections.sort(modules);
+ }
+ if (Sort.BY_DEPENDENCY.isContained(sortOptions)) {
+ if (Sort.BY_START_LEVEL.isContained(sortOptions)) {
+ // sort each sublist that has modules of the same start level
+ int currentSL = modules.get(0).getStartLevel();
+ int currentSLindex = 0;
+ boolean lazy = false;
+ for (int i = 0; i < modules.size(); i++) {
+ Module module = modules.get(i);
+ if (currentSL != module.getStartLevel()) {
+ if (lazy)
+ sortByDependencies(modules.subList(currentSLindex, i));
+ currentSL = module.getStartLevel();
+ currentSLindex = i;
+ lazy = false;
+ }
+ lazy |= module.isLazyActivate();
+ }
+ // sort the last set of bundles
+ if (lazy)
+ sortByDependencies(modules.subList(currentSLindex, modules.size()));
+ } else {
+ // sort the whole list by dependency
+ sortByDependencies(modules);
+ }
+ }
+ }
+
+ private Collection<List<Module>> sortByDependencies(List<Module> toSort) {
+ // Build references so we can sort
+ List<Module[]> references = new ArrayList<Module[]>(toSort.size());
+ for (Module module : toSort) {
+ ModuleRevision current = module.getCurrentRevision();
+ if (current == null) {
+ continue;
+ }
+ ModuleWiring wiring = current.getWiring();
+ if (wiring == null) {
+ continue;
+ }
+ for (ModuleWire wire : wiring.getRequiredModuleWires(null)) {
+ references.add(new Module[] {wire.getRequirer().getRevisions().getModule(), wire.getProvider().getRevisions().getModule()});
+ }
+ }
+
+ // Sort an array using the references
+ Module[] sorted = toSort.toArray(new Module[toSort.size()]);
+ Object[][] cycles = ComputeNodeOrder.computeNodeOrder(sorted, references.toArray(new Module[references.size()][]));
+
+ // Apply the sorted array to the list
+ toSort.clear();
+ toSort.addAll(Arrays.asList(sorted));
+
+ if (cycles.length == 0)
+ return Collections.emptyList();
+
+ Collection<List<Module>> moduleCycles = new ArrayList<List<Module>>(cycles.length);
+ for (Object[] cycle : cycles) {
+ List<Module> moduleCycle = new ArrayList<Module>(cycle.length);
+ for (Object module : cycle) {
+ moduleCycle.add((Module) module);
+ }
+ moduleCycles.add(moduleCycle);
+ }
+ return moduleCycles;
+ }
+
+ /**
+ * Increments by one the next module ID
+ */
+ private long getNextIdAndIncrement() {
+ // sanity check
+ checkWrite();
+ return nextId.getAndIncrement();
+
+ }
+
+ private void checkWrite() {
+ if (monitor.getWriteHoldCount() == 0)
+ throw new IllegalMonitorStateException("Must hold the write lock.");
+ }
+
+ /**
+ * returns the next module ID
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return the next module ID
+ */
+ public final long getNextId() {
+ lockRead();
+ try {
+ return nextId.get();
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns the current timestamp for the revisions of this database.
+ * The timestamp is incremented any time a modification
+ * is made to the revisions in this database. For example:
+ * <ul>
+ * <li> installing a module
+ * <li> updating a module
+ * <li> uninstalling a module
+ * <li> modifying the wirings
+ * </ul>
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return the current timestamp of this database.
+ */
+ final public long getRevisionsTimestamp() {
+ lockRead();
+ try {
+ return revisionsTimeStamp.get();
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Returns the current timestamp for this database.
+ * The timestamp is incremented any time a modification
+ * is made to this database. This includes the modifications
+ * described in {@link #getRevisionsTimestamp() revisions timestamp}
+ * and the following modifications related to modules:
+ * <ul>
+ * <li> modifying the initial module start level
+ * <li> modifying a module start level
+ * <li> modifying a module settings
+ * </ul>
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * @return the current timestamp of this database.
+ */
+ final public long getTimestamp() {
+ lockRead();
+ try {
+ return allTimeStamp.get();
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Increments the timestamps of this database.
+ * @param incrementRevision indicates if the revision timestamp should change
+ */
+ private void incrementTimestamps(boolean incrementRevision) {
+ // sanity check
+ checkWrite();
+ if (incrementRevision) {
+ revisionsTimeStamp.incrementAndGet();
+ }
+ allTimeStamp.incrementAndGet();
+ }
+
+ private void setSystemLastModified(long currentTime) {
+ // sanity check
+ checkWrite();
+ Module systemModule = getModule(0);
+ if (systemModule != null) {
+ systemModule.setlastModified(currentTime);
+ }
+ }
+
+ /**
+ * @see ReadLock#lock()
+ */
+ public final void lockRead() {
+ monitor.readLock().lock();
+ }
+
+ /**
+ * Same as {@link WriteLock#lock()} except an illegal
+ * state exception is thrown if the current thread holds
+ * one or more read locks.
+ * @see WriteLock#lock()
+ * @throws IllegalMonitorStateException if the current thread holds
+ * one or more read locks.
+ */
+ public final void lockWrite() {
+ if (monitor.getReadHoldCount() > 0) {
+ // this is not supported and will cause deadlock if allowed to proceed.
+ // fail fast instead of deadlocking
+ throw new IllegalMonitorStateException("Requesting upgrade to write lock."); //$NON-NLS-1$
+ }
+ monitor.writeLock().lock();
+ }
+
+ /**
+ * @see ReadLock#unlock()
+ */
+ public final void unlockRead() {
+ monitor.readLock().unlock();
+ }
+
+ /**
+ * @see WriteLock#unlock()
+ */
+ public final void unlockWrite() {
+ monitor.writeLock().unlock();
+ }
+
+ /**
+ * Adds the {@link ModuleRevision#getModuleCapabilities(String) capabilities}
+ * provided by the specified revision to this database. These capabilities must
+ * become available for lookup with the {@link ModuleDatabase#findCapabilities(ModuleRequirement)}
+ * method.
+ * <p>
+ * This method must be called while holding the {@link #lockWrite() write} lock.
+ * @param revision the revision which has capabilities to add
+ */
+ protected void addCapabilities(ModuleRevision revision) {
+ checkWrite();
+ capabilities.addCapabilities(revision);
+ }
+
+ /**
+ * Removes the {@link ModuleRevision#getModuleCapabilities(String) capabilities}
+ * provided by the specified revision from this database. These capabilities
+ * must no longer be available for lookup with the
+ * {@link ModuleDatabase#findCapabilities(ModuleRequirement)} method.
+ * <p>
+ * This method must be called while holding the {@link #lockWrite() write} lock.
+ * @param revision
+ */
+ protected void removeCapabilities(ModuleRevision revision) {
+ checkWrite();
+ capabilities.removeCapabilities(revision);
+ }
+
+ /**
+ * Returns a mutable snapshot of capabilities that are candidates for
+ * satisfying the specified requirement.
+ * <p>
+ * A read operation protected by the {@link #lockRead() read} lock.
+ * Implementers of this method should acquire the read lock while
+ * finding capabilities.
+ * @param requirement the requirement
+ * @return the candidates for the requirement
+ */
+ protected List<ModuleCapability> findCapabilities(ModuleRequirement requirement) {
+ lockRead();
+ try {
+ return capabilities.findCapabilities(requirement);
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Writes this database in a format suitable for using the {@link #load(DataInputStream)}
+ * method. All modules are stored which have a current {@link ModuleRevision revision}.
+ * Only the current revision of each module is stored (no removal pending revisions
+ * are stored). Optionally the {@link ModuleWiring wiring} of each current revision
+ * may be stored. Wiring can only be stored if there are no {@link #getRemovalPending()
+ * removal pending} revisions.
+ * <p>
+ * This method acquires the {@link #lockRead() read} lock while writing this
+ * database.
+ * <p>
+ * After this database have been written, the output stream is flushed.
+ * The output stream remains open after this method returns.
+ * @param out the data output steam.
+ * @param persistWirings true if wirings should be persisted. This option will be ignored
+ * if there are {@link #getRemovalPending() removal pending} revisions.
+ * @throws IOException if writing this database to the specified output stream throws an IOException
+ */
+ public final void store(DataOutputStream out, boolean persistWirings) throws IOException {
+ lockRead();
+ try {
+ Persistence.store(this, out, persistWirings);
+ } finally {
+ unlockRead();
+ }
+ }
+
+ /**
+ * Loads information into this database from the input data stream. This data
+ * base must be empty and never been modified (the {@link #getRevisionsTimestamp() timestamp} is zero.
+ * All stored modules are loaded into this database. If the input stream contains
+ * wiring then it will also be loaded into this database.
+ * <p>
+ * Since this method modifies this database it is considered a write operation.
+ * This method acquires the {@link #lockWrite() write} lock while loading
+ * the information into this database.
+ * <p>
+ * The specified stream remains open after this method returns.
+ * @param in the data input stream.
+ * @throws IOException if an error occurred when reading from the input stream.
+ * @throws IllegalStateException if this database is not empty.
+ */
+ public final void load(DataInputStream in) throws IOException {
+ lockWrite();
+ try {
+ if (allTimeStamp.get() != 0)
+ throw new IllegalStateException("Can only load into a empty database."); //$NON-NLS-1$
+ Persistence.load(this, in);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ final void persistSettings(EnumSet<Settings> settings, Module module) {
+ lockWrite();
+ try {
+ EnumSet<Settings> existing = moduleSettings.get(module.getId());
+ if (!settings.equals(existing)) {
+ moduleSettings.put(module.getId(), EnumSet.copyOf(settings));
+ incrementTimestamps(false);
+ }
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ final void setStartLevel(Module module, int startlevel) {
+ lockWrite();
+ try {
+ module.checkValid();
+ module.storeStartLevel(startlevel);
+ incrementTimestamps(false);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ final int getInitialModuleStartLevel() {
+ lockRead();
+ try {
+ return this.initialModuleStartLevel;
+ } finally {
+ unlockRead();
+ }
+ }
+
+ final void setInitialModuleStartLevel(int initialStartlevel) {
+ lockWrite();
+ try {
+ this.initialModuleStartLevel = initialStartlevel;
+ incrementTimestamps(false);
+ } finally {
+ unlockWrite();
+ }
+ }
+
+ private static class Persistence {
+ private static final int VERSION = 1;
+ private static final byte NULL = 0;
+ private static final byte OBJECT = 1;
+ private static final byte LONG_STRING = 3;
+ private static final String UTF_8 = "UTF-8"; //$NON-NLS-1$
+
+ private static final byte VALUE_STRING = 0;
+ private static final byte VALUE_STRING_ARRAY = 1;
+ private static final byte VAlUE_BOOLEAN = 2;
+ private static final byte VALUE_INTEGER = 3;
+ private static final byte VALUE_LONG = 4;
+ private static final byte VALUE_DOUBLE = 5;
+ private static final byte VALUE_VERSION = 6;
+ private static final byte VALUE_URI = 7;
+ private static final byte VALUE_LIST = 8;
+
+ private static int addToWriteTable(Object object, Map<Object, Integer> objectTable) {
+ if (object == null)
+ throw new NullPointerException();
+ Integer cur = objectTable.get(object);
+ if (cur != null)
+ throw new IllegalStateException("Object is already in the write table: " + object); //$NON-NLS-1$
+ objectTable.put(object, new Integer(objectTable.size()));
+ // return the index of the object just added (i.e. size - 1)
+ return (objectTable.size() - 1);
+ }
+
+ private static void addToReadTable(Object object, int index, Map<Integer, Object> objectTable) {
+ objectTable.put(new Integer(index), object);
+ }
+
+ public static void store(ModuleDatabase moduleDatabase, DataOutputStream out, boolean persistWirings) throws IOException {
+ out.writeInt(VERSION);
+ out.writeLong(moduleDatabase.getRevisionsTimestamp());
+ out.writeLong(moduleDatabase.getTimestamp());
+ out.writeLong(moduleDatabase.getNextId());
+ out.writeInt(moduleDatabase.getInitialModuleStartLevel());
+
+ List<Module> modules = moduleDatabase.getModules();
+ out.writeInt(modules.size());
+
+ Map<Object, Integer> objectTable = new HashMap<Object, Integer>();
+ for (Module module : modules) {
+ writeModule(module, moduleDatabase, out, objectTable);
+ }
+
+ Collection<ModuleRevision> removalPendings = moduleDatabase.getRemovalPending();
+ // only persist wirings if there are no removals pending
+ persistWirings &= removalPendings.isEmpty();
+ out.writeBoolean(persistWirings);
+ if (!persistWirings) {
+ return;
+ }
+
+ Map<ModuleRevision, ModuleWiring> wirings = moduleDatabase.wirings;
+ // prime the object table with all the required wires
+ out.writeInt(wirings.size());
+ for (ModuleWiring wiring : wirings.values()) {
+ List<ModuleWire> requiredWires = wiring.getRequiredModuleWires(null);
+ out.writeInt(requiredWires.size());
+ for (ModuleWire wire : requiredWires) {
+ writeWire(wire, out, objectTable);
+ }
+ }
+
+ // now write all the info about each wiring using only indexes
+ for (ModuleWiring wiring : wirings.values()) {
+ writeWiring(wiring, out, objectTable);
+ }
+
+ out.flush();
+ }
+
+ public static void load(ModuleDatabase moduleDatabase, DataInputStream in) throws IOException {
+ int version = in.readInt();
+ if (version < VERSION)
+ throw new IOException("Perstence version is not correct for loading: " + version + " expecting: " + VERSION); //$NON-NLS-1$ //$NON-NLS-2$
+ long revisionsTimeStamp = in.readLong();
+ long allTimeStamp = in.readLong();
+ moduleDatabase.nextId.set(in.readLong());
+ moduleDatabase.setInitialModuleStartLevel(in.readInt());
+
+ int numModules = in.readInt();
+
+ Map<Integer, Object> objectTable = new HashMap<Integer, Object>();
+ for (int i = 0; i < numModules; i++) {
+ readModule(moduleDatabase, in, objectTable);
+ }
+
+ moduleDatabase.revisionsTimeStamp.set(revisionsTimeStamp);
+ moduleDatabase.allTimeStamp.set(allTimeStamp);
+ if (!in.readBoolean())
+ return; // no wires persisted
+
+ int numWirings = in.readInt();
+ // prime the table with all the required wires
+ for (int i = 0; i < numWirings; i++) {
+ int numWires = in.readInt();
+ for (int j = 0; j < numWires; j++) {
+ readWire(in, objectTable);
+ }
+ }
+
+ // now read all the info about each wiring using only indexes
+ Map<ModuleRevision, ModuleWiring> wirings = new HashMap<ModuleRevision, ModuleWiring>();
+ for (int i = 0; i < numWirings; i++) {
+ ModuleWiring wiring = readWiring(in, objectTable);
+ wirings.put(wiring.getRevision(), wiring);
+ }
+ // TODO need to do this without incrementing the timestamp
+ moduleDatabase.setWiring(wirings);
+
+ // need to set the resolution state of the modules
+ for (ModuleWiring wiring : wirings.values()) {
+ wiring.getRevision().getRevisions().getModule().setState(State.RESOLVED);
+ }
+
+ // Setting the timestamp at the end since some operations increment it
+ moduleDatabase.revisionsTimeStamp.set(revisionsTimeStamp);
+ moduleDatabase.allTimeStamp.set(allTimeStamp);
+ }
+
+ private static void writeModule(Module module, ModuleDatabase moduleDatabase, DataOutputStream out, Map<Object, Integer> objectTable) throws IOException {
+ ModuleRevision current = module.getCurrentRevision();
+ if (current == null)
+ return;
+ out.writeInt(addToWriteTable(current, objectTable));
+
+ writeString(module.getLocation(), out);
+ out.writeLong(module.getId());
+
+ writeString(current.getSymbolicName(), out);
+ writeVersion(current.getVersion(), out);
+ out.writeInt(current.getTypes());
+
+ List<Capability> capabilities = current.getCapabilities(null);
+ out.writeInt(capabilities.size());
+ for (Capability capability : capabilities) {
+ out.writeInt(addToWriteTable(capability, objectTable));
+ writeGenericInfo(capability.getNamespace(), capability.getAttributes(), capability.getDirectives(), out);
+ }
+
+ List<Requirement> requirements = current.getRequirements(null);
+ out.writeInt(requirements.size());
+ for (Requirement requirement : requirements) {
+ out.writeInt(addToWriteTable(requirement, objectTable));
+ writeGenericInfo(requirement.getNamespace(), requirement.getAttributes(), requirement.getDirectives(), out);
+ }
+
+ // settings
+ EnumSet<Settings> settings = moduleDatabase.moduleSettings.get(module.getId());
+ out.writeInt(settings == null ? 0 : settings.size());
+ if (settings != null) {
+ for (Settings setting : settings) {
+ writeString(setting.name(), out);
+ }
+ }
+
+ // startlevel
+ out.writeInt(module.getStartLevel());
+
+ // last modified
+ out.writeLong(module.getLastModified());
+ }
+
+ private static void readModule(ModuleDatabase moduleDatabase, DataInputStream in, Map<Integer, Object> objectTable) throws IOException {
+ ModuleRevisionBuilder builder = new ModuleRevisionBuilder();
+ int moduleIndex = in.readInt();
+ String location = readString(in);
+ long id = in.readLong();
+ builder.setSymbolicName(readString(in));
+ builder.setVersion(readVersion(in));
+ builder.setTypes(in.readInt());
+
+ int numCapabilities = in.readInt();
+ int[] capabilityIndexes = new int[numCapabilities];
+ for (int i = 0; i < numCapabilities; i++) {
+ capabilityIndexes[i] = in.readInt();
+ readGenericInfo(true, in, builder);
+ }
+
+ int numRequirements = in.readInt();
+ int[] requirementIndexes = new int[numRequirements];
+ for (int i = 0; i < numRequirements; i++) {
+ requirementIndexes[i] = in.readInt();
+ readGenericInfo(false, in, builder);
+ }
+
+ // settings
+ EnumSet<Settings> settings = null;
+ int numSettings = in.readInt();
+ if (numSettings > 0) {
+ settings = EnumSet.noneOf(Settings.class);
+ for (int i = 0; i < numSettings; i++) {
+ settings.add(Settings.valueOf(readString(in)));
+ }
+ }
+
+ // startlevel
+ int startlevel = in.readInt();
+ Object revisionInfo = moduleDatabase.adaptor.getRevisionInfo(location, id);
+ Module module = moduleDatabase.load(location, builder, revisionInfo, id, settings, startlevel);
+
+ // last modified
+ module.setlastModified(in.readLong());
+
+ ModuleRevision current = module.getCurrentRevision();
+ addToReadTable(current, moduleIndex, objectTable);
+
+ List<ModuleCapability> capabilities = current.getModuleCapabilities(null);
+ for (int i = 0; i < capabilities.size(); i++) {
+ addToReadTable(capabilities.get(i), capabilityIndexes[i], objectTable);
+ }
+
+ List<ModuleRequirement> requirements = current.getModuleRequirements(null);
+ for (int i = 0; i < requirements.size(); i++) {
+ addToReadTable(requirements.get(i), requirementIndexes[i], objectTable);
+ }
+ }
+
+ private static void writeWire(ModuleWire wire, DataOutputStream out, Map<Object, Integer> objectTable) throws IOException {
+ Wire w = wire;
+ Integer capability = objectTable.get(w.getCapability());
+ Integer provider = objectTable.get(w.getProvider());
+ Integer requirement = objectTable.get(w.getRequirement());
+ Integer requirer = objectTable.get(w.getRequirer());
+
+ if (capability == null || provider == null || requirement == null || requirer == null)
+ throw new NullPointerException("Could not find the expected indexes"); //$NON-NLS-1$
+
+ out.writeInt(addToWriteTable(wire, objectTable));
+
+ out.writeInt(capability);
+ out.writeInt(provider);
+ out.writeInt(requirement);
+ out.writeInt(requirer);
+ }
+
+ private static void readWire(DataInputStream in, Map<Integer, Object> objectTable) throws IOException {
+ int wireIndex = in.readInt();
+
+ ModuleCapability capability = (ModuleCapability) objectTable.get(in.readInt());
+ ModuleRevision provider = (ModuleRevision) objectTable.get(in.readInt());
+ ModuleRequirement requirement = (ModuleRequirement) objectTable.get(in.readInt());
+ ModuleRevision requirer = (ModuleRevision) objectTable.get(in.readInt());
+
+ if (capability == null || provider == null || requirement == null || requirer == null)
+ throw new NullPointerException("Could not find the expected indexes"); //$NON-NLS-1$
+
+ ModuleWire result = new ModuleWire(capability, provider, requirement, requirer);
+
+ addToReadTable(result, wireIndex, objectTable);
+ }
+
+ private static void writeWiring(ModuleWiring wiring, DataOutputStream out, Map<Object, Integer> objectTable) throws IOException {
+ Integer revisionIndex = objectTable.get(wiring.getRevision());
+ if (revisionIndex == null)
+ throw new NullPointerException("Could not find revision for wiring."); //$NON-NLS-1$
+ out.writeInt(revisionIndex);
+
+ List<ModuleCapability> capabilities = wiring.getModuleCapabilities(null);
+ out.writeInt(capabilities.size());
+ for (ModuleCapability capability : capabilities) {
+ Integer capabilityIndex = objectTable.get(capability);
+ if (capabilityIndex == null)
+ throw new NullPointerException("Could not find capability for wiring."); //$NON-NLS-1$
+ out.writeInt(capabilityIndex);
+ }
+
+ List<ModuleRequirement> requirements = wiring.getPersistentRequirements();
+ out.writeInt(requirements.size());
+ for (ModuleRequirement requirement : requirements) {
+ Integer requirementIndex = objectTable.get(requirement);
+ if (requirementIndex == null)
+ throw new NullPointerException("Could not find requirement for wiring."); //$NON-NLS-1$
+ out.writeInt(requirementIndex);
+ }
+
+ List<ModuleWire> providedWires = wiring.getPersistentProvidedWires();
+ out.writeInt(providedWires.size());
+ for (ModuleWire wire : providedWires) {
+ Integer wireIndex = objectTable.get(wire);
+ if (wireIndex == null)
+ throw new NullPointerException("Could not find provided wire for wiring."); //$NON-NLS-1$
+ out.writeInt(wireIndex);
+ }
+
+ List<ModuleWire> requiredWires = wiring.getPersistentRequiredWires();
+ out.writeInt(requiredWires.size());
+ for (ModuleWire wire : requiredWires) {
+ Integer wireIndex = objectTable.get(wire);
+ if (wireIndex == null)
+ throw new NullPointerException("Could not find required wire for wiring."); //$NON-NLS-1$
+ out.writeInt(wireIndex);
+ }
+
+ Collection<String> substituted = wiring.getSubstitutedNames();
+ out.writeInt(substituted.size());
+ for (String pkgName : substituted) {
+ writeString(pkgName, out);
+ }
+ }
+
+ private static ModuleWiring readWiring(DataInputStream in, Map<Integer, Object> objectTable) throws IOException {
+ ModuleRevision revision = (ModuleRevision) objectTable.get(in.readInt());
+ if (revision == null)
+ throw new NullPointerException("Could not find revision for wiring."); //$NON-NLS-1$
+
+ int numCapabilities = in.readInt();
+ List<ModuleCapability> capabilities = new ArrayList<ModuleCapability>(numCapabilities);
+ for (int i = 0; i < numCapabilities; i++) {
+ capabilities.add((ModuleCapability) objectTable.get(in.readInt()));
+ }
+
+ int numRequirements = in.readInt();
+ List<ModuleRequirement> requirements = new ArrayList<ModuleRequirement>(numRequirements);
+ for (int i = 0; i < numRequirements; i++) {
+ requirements.add((ModuleRequirement) objectTable.get(in.readInt()));
+ }
+
+ int numProvidedWires = in.readInt();
+ List<ModuleWire> providedWires = new ArrayList<ModuleWire>(numProvidedWires);
+ for (int i = 0; i < numProvidedWires; i++) {
+ providedWires.add((ModuleWire) objectTable.get(in.readInt()));
+ }
+
+ int numRequiredWires = in.readInt();
+ List<ModuleWire> requiredWires = new ArrayList<ModuleWire>(numRequiredWires);
+ for (int i = 0; i < numRequiredWires; i++) {
+ requiredWires.add((ModuleWire) objectTable.get(in.readInt()));
+ }
+
+ int numSubstitutedNames = in.readInt();
+ Collection<String> substituted = new ArrayList<String>(numSubstitutedNames);
+ for (int i = 0; i < numSubstitutedNames; i++) {
+ substituted.add(readString(in));
+ }
+
+ return new ModuleWiring(revision, capabilities, requirements, providedWires, requiredWires, substituted);
+ }
+
+ private static void writeGenericInfo(String namespace, Map<String, ?> attributes, Map<String, String> directives, DataOutputStream out) throws IOException {
+ writeString(namespace, out);
+ writeMap(attributes, out);
+ writeMap(directives, out);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void readGenericInfo(boolean isCapability, DataInputStream in, ModuleRevisionBuilder builder) throws IOException {
+ String namespace = readString(in);
+ Map<String, Object> attributes = readMap(in);
+ Map<String, ?> directives = readMap(in);
+ if (isCapability) {
+ builder.addCapability(namespace, (Map<String, String>) directives, attributes);
+ } else {
+ builder.addRequirement(namespace, (Map<String, String>) directives, attributes);
+ }
+
+ }
+
+ private static void writeMap(Map<String, ?> source, DataOutputStream out) throws IOException {
+ if (source == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(source.size());
+ Iterator<String> iter = source.keySet().iterator();
+ while (iter.hasNext()) {
+ String key = iter.next();
+ Object value = source.get(key);
+ writeString(key, out);
+ if (value instanceof String) {
+ out.writeByte(VALUE_STRING);
+ writeString((String) value, out);
+ } else if (value instanceof String[]) {
+ out.writeByte(VALUE_STRING_ARRAY);
+ writeStringArray(out, (String[]) value);
+ } else if (value instanceof Boolean) {
+ out.writeByte(VAlUE_BOOLEAN);
+ out.writeBoolean(((Boolean) value).booleanValue());
+ } else if (value instanceof Integer) {
+ out.writeByte(VALUE_INTEGER);
+ out.writeInt(((Integer) value).intValue());
+ } else if (value instanceof Long) {
+ out.writeByte(VALUE_LONG);
+ out.writeLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ out.writeByte(VALUE_DOUBLE);
+ out.writeDouble(((Double) value).doubleValue());
+ } else if (value instanceof Version) {
+ out.writeByte(VALUE_VERSION);
+ writeVersion((Version) value, out);
+ } else if (value instanceof URI) {
+ out.writeByte(VALUE_URI);
+ writeString(value.toString(), out);
+ } else if (value instanceof List) {
+ out.writeByte(VALUE_LIST);
+ writeList(out, (List<?>) value);
+ }
+ }
+ }
+ }
+
+ private static Map<String, Object> readMap(DataInputStream in) throws IOException {
+ int count = in.readInt();
+ HashMap<String, Object> result = new HashMap<String, Object>(count);
+ for (int i = 0; i < count; i++) {
+ String key = readString(in);
+ Object value = null;
+ byte type = in.readByte();
+ if (type == VALUE_STRING)
+ value = readString(in);
+ else if (type == VALUE_STRING_ARRAY)
+ value = readStringArray(in);
+ else if (type == VAlUE_BOOLEAN)
+ value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
+ else if (type == VALUE_INTEGER)
+ value = new Integer(in.readInt());
+ else if (type == VALUE_LONG)
+ value = new Long(in.readLong());
+ else if (type == VALUE_DOUBLE)
+ value = new Double(in.readDouble());
+ else if (type == VALUE_VERSION)
+ value = readVersion(in);
+ else if (type == VALUE_URI)
+ try {
+ value = new URI(readString(in));
+ } catch (URISyntaxException e) {
+ value = null;
+ }
+ else if (type == VALUE_LIST)
+ value = readList(in);
+
+ result.put(key, value);
+ }
+ return result;
+ }
+
+ private static void writeStringArray(DataOutputStream out, String[] value) throws IOException {
+ if (value == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(value.length);
+ for (int i = 0; i < value.length; i++)
+ writeString(value[i], out);
+ }
+
+ }
+
+ private static String[] readStringArray(DataInputStream in) throws IOException {
+ int count = in.readInt();
+ if (count == 0)
+ return null;
+ String[] result = new String[count];
+ for (int i = 0; i < count; i++)
+ result[i] = readString(in);
+ return result;
+ }
+
+ private static void writeList(DataOutputStream out, List<?> list) throws IOException {
+ if (list.isEmpty()) {
+ out.writeInt(0);
+ return;
+ }
+ byte type = getListType(list);
+ if (type < 0) {
+ out.writeInt(0);
+ return; // don't understand the list type
+ }
+ out.writeInt(list.size());
+ out.writeByte(type);
+ for (Object value : list) {
+ switch (type) {
+ case VALUE_STRING :
+ writeString((String) value, out);
+ break;
+ case VALUE_INTEGER :
+ out.writeInt(((Integer) value).intValue());
+ break;
+ case VALUE_LONG :
+ out.writeLong(((Long) value).longValue());
+ break;
+ case VALUE_DOUBLE :
+ out.writeDouble(((Double) value).doubleValue());
+ break;
+ case VALUE_VERSION :
+ writeVersion((Version) value, out);
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ private static byte getListType(List<?> list) {
+ if (list.size() == 0)
+ return -1;
+ Object type = list.get(0);
+ if (type instanceof String)
+ return VALUE_STRING;
+ if (type instanceof Integer)
+ return VALUE_INTEGER;
+ if (type instanceof Long)
+ return VALUE_LONG;
+ if (type instanceof Double)
+ return VALUE_DOUBLE;
+ if (type instanceof Version)
+ return VALUE_VERSION;
+ return -2;
+ }
+
+ private static List<?> readList(DataInputStream in) throws IOException {
+
+ int size = in.readInt();
+ if (size == 0)
+ return new ArrayList<Object>(0);
+ byte listType = in.readByte();
+ List<Object> list = new ArrayList<Object>(size);
+ for (int i = 0; i < size; i++) {
+ switch (listType) {
+ case VALUE_STRING :
+ list.add(readString(in));
+ break;
+ case VALUE_INTEGER :
+ list.add(new Integer(in.readInt()));
+ break;
+ case VALUE_LONG :
+ list.add(new Long(in.readLong()));
+ break;
+ case VALUE_DOUBLE :
+ list.add(new Double(in.readDouble()));
+ break;
+ case VALUE_VERSION :
+ list.add(readVersion(in));
+ break;
+ default :
+ throw new IOException("Invalid type: " + listType); //$NON-NLS-1$
+ }
+ }
+ return list;
+ }
+
+ private static void writeVersion(Version version, DataOutputStream out) throws IOException {
+ if (version == null || version.equals(Version.emptyVersion)) {
+ out.writeByte(NULL);
+ return;
+ }
+ out.writeByte(OBJECT);
+ out.writeInt(version.getMajor());
+ out.writeInt(version.getMinor());
+ out.writeInt(version.getMicro());
+ writeQualifier(version.getQualifier(), out);
+ }
+
+ private static void writeQualifier(String string, DataOutputStream out) throws IOException {
+ if (string != null && string.length() == 0)
+ string = null;
+ writeString(string, out);
+ }
+
+ private static Version readVersion(DataInputStream in) throws IOException {
+ byte tag = in.readByte();
+ if (tag == NULL)
+ return Version.emptyVersion;
+ int majorComponent = in.readInt();
+ int minorComponent = in.readInt();
+ int serviceComponent = in.readInt();
+ String qualifierComponent = readString(in);
+ return (Version) ObjectPool.intern(new Version(majorComponent, minorComponent, serviceComponent, qualifierComponent));
+ }
+
+ private static void writeString(String string, DataOutputStream out) throws IOException {
+ if (string == null)
+ out.writeByte(NULL);
+ else {
+ byte[] data = string.getBytes(UTF_8);
+
+ if (data.length > 65535) {
+ out.writeByte(LONG_STRING);
+ out.writeInt(data.length);
+ out.write(data);
+ } else {
+ out.writeByte(OBJECT);
+ out.writeUTF(string);
+ }
+ }
+ }
+
+ static private String readString(DataInputStream in) throws IOException {
+ byte type = in.readByte();
+ if (type == NULL)
+ return null;
+
+ if (type == LONG_STRING) {
+ int length = in.readInt();
+ byte[] data = new byte[length];
+ in.readFully(data);
+ String string = new String(data, UTF_8);
+
+ return (String) ObjectPool.intern(string);
+ }
+
+ return (String) ObjectPool.intern(in.readUTF());
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleLoader.java
new file mode 100644
index 000000000..bdd2e8176
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleLoader.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @since 3.10
+ */
+public interface ModuleLoader {
+ /**
+ *
+ * @param path
+ * @param filePattern
+ * @param options
+ * @return TODO
+ * @see ModuleWiring#findEntries(String, String, int)
+ */
+ public List<URL> findEntries(String path, String filePattern, int options);
+
+ /**
+ *
+ * @param path
+ * @param filePattern
+ * @param options
+ * @return TODO
+ * @see ModuleWiring#listResources(String, String, int)
+ */
+ public Collection<String> listResources(String path, String filePattern, int options);
+
+ /**
+ *
+ * @return TODO
+ */
+ public ClassLoader getClassLoader();
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java
new file mode 100644
index 000000000..ba22797d4
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import org.eclipse.osgi.internal.framework.FilterImpl;
+
+import java.util.*;
+import org.eclipse.osgi.internal.container.Capabilities;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.*;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.resource.Namespace;
+
+/**
+ * An implementation of {@link BundleRequirement}. This requirement implements
+ * the matches method according to the OSGi specification which includes
+ * implementing the mandatory directive for the osgi.wiring.* namespaces.
+ * @since 3.10
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ModuleRequirement implements BundleRequirement {
+ private final String namespace;
+ private final Map<String, String> directives;
+ private final Map<String, Object> attributes;
+ private final ModuleRevision revision;
+
+ ModuleRequirement(String namespace, Map<String, String> directives, Map<String, Object> attributes, ModuleRevision revision) {
+ this.namespace = namespace;
+ this.directives = Collections.unmodifiableMap(directives);
+ this.attributes = Collections.unmodifiableMap(attributes);
+ this.revision = revision;
+ }
+
+ @Override
+ public ModuleRevision getRevision() {
+ return revision;
+ }
+
+ @Override
+ public boolean matches(BundleCapability capability) {
+ if (!namespace.equals(capability.getNamespace()))
+ return false;
+ String filterSpec = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+ FilterImpl f = null;
+ if (filterSpec != null) {
+ try {
+ f = FilterImpl.newInstance(filterSpec);
+ } catch (InvalidSyntaxException e) {
+ return false;
+ }
+ }
+ boolean matchMandatory = PackageNamespace.PACKAGE_NAMESPACE.equals(namespace) || BundleNamespace.BUNDLE_NAMESPACE.equals(namespace) || HostNamespace.HOST_NAMESPACE.equals(namespace);
+ return Capabilities.matches(f, capability, matchMandatory);
+ }
+
+ @Override
+ public String getNamespace() {
+ return namespace;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public ModuleRevision getResource() {
+ return revision;
+ }
+
+ public String toString() {
+ return namespace + ModuleRevision.toString(attributes, false) + ModuleRevision.toString(directives, true);
+ }
+
+ private static final String PACKAGENAME_FILTER_COMPONENT = PackageNamespace.PACKAGE_NAMESPACE + "=";
+
+ DynamicModuleRequirement getDynamicPackageRequirement(ModuleRevision host, String dynamicPkgName) {
+ if (!PackageNamespace.PACKAGE_NAMESPACE.equals(namespace)) {
+ return null;
+ }
+ if (!PackageNamespace.RESOLUTION_DYNAMIC.equals(directives.get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
+ // not dynamic
+ return null;
+ }
+ String dynamicFilter = directives.get(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE);
+ // TODO we make some assumptions here on the format of the filter string
+ int packageNameBegin = dynamicFilter.indexOf(PACKAGENAME_FILTER_COMPONENT);
+ if (packageNameBegin == -1) {
+ // not much we can do
+ return null;
+ }
+ packageNameBegin += PACKAGENAME_FILTER_COMPONENT.length();
+ int packageNameEnd = dynamicFilter.indexOf(')', packageNameBegin);
+ if (packageNameEnd == -1) {
+ // not much we can do
+ return null;
+ }
+ String filterPackageName = dynamicFilter.substring(packageNameBegin, packageNameEnd);
+ String specificPackageFilter = null;
+ if ("*".equals(filterPackageName)) {
+ // matches all
+ specificPackageFilter = dynamicFilter.replace(PACKAGENAME_FILTER_COMPONENT + filterPackageName, PACKAGENAME_FILTER_COMPONENT + dynamicPkgName);
+ } else if (filterPackageName.endsWith(".*")) {
+ if (dynamicPkgName.startsWith(filterPackageName.substring(0, filterPackageName.length() - 1))) {
+ specificPackageFilter = dynamicFilter.replace(PACKAGENAME_FILTER_COMPONENT + filterPackageName, PACKAGENAME_FILTER_COMPONENT + dynamicPkgName);
+ }
+ } else if (dynamicPkgName.equals(filterPackageName)) {
+ specificPackageFilter = dynamicFilter;
+ }
+
+ if (specificPackageFilter != null) {
+ Map<String, String> dynamicDirectives = new HashMap<String, String>(directives);
+ dynamicDirectives.put(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE, specificPackageFilter);
+ return new DynamicModuleRequirement(host, dynamicDirectives);
+ }
+ return null;
+ }
+
+ class DynamicModuleRequirement extends ModuleRequirement {
+
+ DynamicModuleRequirement(ModuleRevision host, Map<String, String> directives) {
+ super(ModuleRequirement.this.getNamespace(), directives, ModuleRequirement.this.getAttributes(), host);
+ }
+
+ ModuleRequirement getOriginal() {
+ return ModuleRequirement.this;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
new file mode 100644
index 000000000..78ba471c4
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
@@ -0,0 +1,853 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.security.Permission;
+import java.util.*;
+import org.apache.felix.resolver.ResolverImpl;
+import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement;
+import org.eclipse.osgi.internal.container.Converters;
+import org.osgi.framework.*;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.namespace.*;
+import org.osgi.framework.wiring.*;
+import org.osgi.resource.*;
+import org.osgi.service.resolver.*;
+
+/**
+ * The module resolver handles calls to the {@link Resolver} service for resolving modules
+ * in a module {@link ModuleContainer container}.
+ */
+final class ModuleResolver {
+ private static final Collection<String> NON_PAYLOAD_CAPABILITIES = Arrays.asList(IdentityNamespace.IDENTITY_NAMESPACE);
+ private static final Collection<String> NON_PAYLOAD_REQUIREMENTS = Arrays.asList(HostNamespace.HOST_NAMESPACE, ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
+
+ final ThreadLocal<Boolean> threadResolving = new ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return Boolean.FALSE;
+ }
+ };
+ final ModuleContainerAdaptor adaptor;
+ final Resolver resolver;
+
+ /**
+ * Constructs the module resolver with the specified resolver hook factory
+ * and resolver.
+ * @param adaptor the container adaptor
+ */
+ ModuleResolver(ModuleContainerAdaptor adaptor) {
+ this.adaptor = adaptor;
+ this.resolver = adaptor.getResolver();
+ }
+
+ /**
+ * Attempts to resolve all unresolved modules installed in the specified module database.
+ * returns a delta containing the new wirings or modified wirings that should be
+ * merged into the specified moduleDatabase.
+ * <p>
+ * This method only does read operations on the database no wirings are modified
+ * directly by this method. The returned wirings need to be merged into
+ * the database.
+ * @param triggers the triggers that caused the resolver operation to occur
+ * @param triggersMandatory true if the triggers must be resolved by the resolve process
+ * @param unresolved a snapshot of unresolved revisions
+ * @param wiringCopy the wirings snapshot of the currently resolved revisions
+ * @param moduleDatabase the module database.
+ * @return a delta container the new wirings or modified wirings that should be
+ * merged into the moduleDatabase
+ * @throws ResolutionException
+ */
+ Map<ModuleRevision, ModuleWiring> resolveDelta(Collection<ModuleRevision> triggers, boolean triggersMandatory, Collection<ModuleRevision> unresolved, Map<ModuleRevision, ModuleWiring> wiringCopy, ModuleDatabase moduleDatabase) throws ResolutionException {
+ ResolveProcess resolveProcess = new ResolveProcess(unresolved, triggers, triggersMandatory, wiringCopy, moduleDatabase);
+ Map<Resource, List<Wire>> result = resolveProcess.resolve();
+ return generateDelta(result, wiringCopy);
+ }
+
+ Map<ModuleRevision, ModuleWiring> resolveDynamicDelta(DynamicModuleRequirement dynamicReq, Collection<ModuleRevision> unresolved, Map<ModuleRevision, ModuleWiring> wiringCopy, ModuleDatabase moduleDatabase) throws ResolutionException {
+ ResolveProcess resolveProcess = new ResolveProcess(unresolved, dynamicReq, wiringCopy, moduleDatabase);
+ Map<Resource, List<Wire>> result = resolveProcess.resolve();
+ return generateDelta(result, wiringCopy);
+ }
+
+ private static Map<ModuleRevision, ModuleWiring> generateDelta(Map<Resource, List<Wire>> result, Map<ModuleRevision, ModuleWiring> wiringCopy) {
+ Map<ModuleRevision, Map<ModuleCapability, List<ModuleWire>>> provided = new HashMap<ModuleRevision, Map<ModuleCapability, List<ModuleWire>>>();
+ Map<ModuleRevision, List<ModuleWire>> required = new HashMap<ModuleRevision, List<ModuleWire>>();
+ // First populate the list of provided and required wires for revision
+ // This is done this way to share the wire object between both the provider and requirer
+ for (Map.Entry<Resource, List<Wire>> resultEntry : result.entrySet()) {
+ ModuleRevision revision = (ModuleRevision) resultEntry.getKey();
+ List<ModuleWire> requiredWires = new ArrayList<ModuleWire>(resultEntry.getValue().size());
+ for (Wire wire : resultEntry.getValue()) {
+ ModuleWire moduleWire = new ModuleWire((ModuleCapability) wire.getCapability(), (ModuleRevision) wire.getProvider(), (ModuleRequirement) wire.getRequirement(), (ModuleRevision) wire.getRequirer());
+ requiredWires.add(moduleWire);
+ Map<ModuleCapability, List<ModuleWire>> providedWiresMap = provided.get(moduleWire.getProvider());
+ if (providedWiresMap == null) {
+ providedWiresMap = new HashMap<ModuleCapability, List<ModuleWire>>();
+ provided.put(moduleWire.getProvider(), providedWiresMap);
+ }
+ List<ModuleWire> providedWires = providedWiresMap.get(moduleWire.getCapability());
+ if (providedWires == null) {
+ providedWires = new ArrayList<ModuleWire>();
+ providedWiresMap.put(moduleWire.getCapability(), providedWires);
+ }
+ providedWires.add(moduleWire);
+ }
+ required.put(revision, requiredWires);
+ }
+
+ Map<ModuleRevision, ModuleWiring> delta = new HashMap<ModuleRevision, ModuleWiring>();
+ // now create the ModuleWiring for the newly resolved revisions
+ for (ModuleRevision revision : required.keySet()) {
+ ModuleWiring existingWiring = wiringCopy.get(revision);
+ if (existingWiring == null) {
+ delta.put(revision, createNewWiring(revision, provided, required));
+ } else {
+ // this is to handle dynamic imports
+ delta.put(revision, createWiringDelta(revision, existingWiring, provided.get(revision), required.get(revision)));
+ }
+ }
+ // Also need to create the wiring deltas for already resolved bundles
+ // This should only include updating provided wires and
+ // for fragments it may include new hosts
+ for (ModuleRevision revision : provided.keySet()) {
+ ModuleWiring existingWiring = wiringCopy.get(revision);
+ if (existingWiring != null && !delta.containsKey(revision)) {
+ delta.put(revision, createWiringDelta(revision, existingWiring, provided.get(revision), required.get(revision)));
+ }
+ }
+ return delta;
+ }
+
+ private static ModuleWiring createNewWiring(ModuleRevision revision, Map<ModuleRevision, Map<ModuleCapability, List<ModuleWire>>> provided, Map<ModuleRevision, List<ModuleWire>> required) {
+ Map<ModuleCapability, List<ModuleWire>> providedWireMap = provided.get(revision);
+ if (providedWireMap == null)
+ providedWireMap = Collections.emptyMap();
+ List<ModuleWire> requiredWires = required.get(revision);
+ if (requiredWires == null)
+ requiredWires = Collections.emptyList();
+
+ List<ModuleCapability> capabilities = new ArrayList<ModuleCapability>(revision.getModuleCapabilities(null));
+ ListIterator<ModuleCapability> iCapabilities = capabilities.listIterator(capabilities.size());
+ List<ModuleRequirement> requirements = new ArrayList<ModuleRequirement>(revision.getModuleRequirements(null));
+ ListIterator<ModuleRequirement> iRequirements = requirements.listIterator(requirements.size());
+
+ // if revision is a fragment remove payload requirements and capabilities
+ if ((BundleRevision.TYPE_FRAGMENT & revision.getTypes()) != 0) {
+ removePayloadContent(iCapabilities, iRequirements);
+ } else {
+ // add fragment capabilities and requirements
+ List<ModuleCapability> hostCapabilities = revision.getModuleCapabilities(HostNamespace.HOST_NAMESPACE);
+ ModuleCapability hostCapability = hostCapabilities.isEmpty() ? null : hostCapabilities.get(0);
+ if (hostCapability != null) {
+ addPayloadContent(providedWireMap.get(hostCapability), iCapabilities, iRequirements);
+ }
+ }
+
+ removeNonEffectiveCapabilities(iCapabilities);
+ removeNonEffectiveRequirements(iRequirements, requiredWires);
+ Collection<String> substituted = removeSubstitutedCapabilities(iCapabilities, requiredWires);
+
+ List<ModuleWire> providedWires = new ArrayList<ModuleWire>();
+ addProvidedWires(providedWireMap, providedWires, capabilities);
+
+ filterCapabilityPermissions(capabilities);
+ return new ModuleWiring(revision, capabilities, requirements, providedWires, requiredWires, substituted);
+ }
+
+ private static void removePayloadContent(ListIterator<ModuleCapability> iCapabilities, ListIterator<ModuleRequirement> iRequirements) {
+ rewind(iCapabilities);
+ while (iCapabilities.hasNext()) {
+ if (!NON_PAYLOAD_CAPABILITIES.contains(iCapabilities.next().getNamespace())) {
+ iCapabilities.remove();
+ }
+ }
+
+ rewind(iRequirements);
+ while (iRequirements.hasNext()) {
+ if (!NON_PAYLOAD_REQUIREMENTS.contains(iRequirements.next().getNamespace())) {
+ iRequirements.remove();
+ }
+ }
+ }
+
+ private static Collection<String> removeSubstitutedCapabilities(ListIterator<ModuleCapability> iCapabilities, List<ModuleWire> requiredWires) {
+ Collection<String> substituted = null;
+ for (ModuleWire moduleWire : requiredWires) {
+ if (!PackageNamespace.PACKAGE_NAMESPACE.equals(moduleWire.getCapability().getNamespace()))
+ continue;
+ String packageName = (String) moduleWire.getCapability().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ rewind(iCapabilities);
+ while (iCapabilities.hasNext()) {
+ ModuleCapability capability = iCapabilities.next();
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(capability.getNamespace())) {
+ if (packageName.equals(capability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))) {
+ // found a package capability with the same name as a package that got imported
+ // this indicates a substitution
+ iCapabilities.remove();
+ if (substituted == null) {
+ substituted = new ArrayList<String>();
+ }
+ substituted.add(packageName);
+ if (!substituted.contains(packageName)) {
+ substituted.add(packageName);
+ }
+ }
+ }
+ }
+ }
+ return substituted == null ? Collections.<String> emptyList() : substituted;
+ }
+
+ private static void removeNonEffectiveRequirements(ListIterator<ModuleRequirement> iRequirements, List<ModuleWire> requiredWires) {
+ rewind(iRequirements);
+ while (iRequirements.hasNext()) {
+ ModuleRequirement requirement = iRequirements.next();
+ // check the effective directive;
+ Object effective = requirement.getDirectives().get(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
+ if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) {
+ iRequirements.remove();
+ } else {
+ // check the resolution directive
+ Object resolution = requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ if (Namespace.RESOLUTION_OPTIONAL.equals(resolution)) {
+ boolean found = false;
+ // need to check the wires to see if the optional requirement is resolved
+ wires: for (ModuleWire wire : requiredWires) {
+ if (wire.getRequirement().equals(requirement)) {
+ found = true;
+ break wires;
+ }
+ }
+ if (!found) {
+ // optional requirement is not resolved
+ iRequirements.remove();
+ }
+ }
+ }
+ }
+ }
+
+ static void removeNonEffectiveCapabilities(ListIterator<ModuleCapability> iCapabilities) {
+ rewind(iCapabilities);
+ while (iCapabilities.hasNext()) {
+ Object effective = iCapabilities.next().getDirectives().get(Namespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
+ if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective))
+ iCapabilities.remove();
+ }
+ }
+
+ private static void addPayloadContent(List<ModuleWire> hostWires, ListIterator<ModuleCapability> iCapabilities, ListIterator<ModuleRequirement> iRequirements) {
+ if (hostWires == null)
+ return;
+ for (ModuleWire hostWire : hostWires) {
+ // add fragment capabilities
+ String currentNamespace = null;
+ List<ModuleCapability> fragmentCapabilities = hostWire.getRequirer().getModuleCapabilities(null);
+ for (ModuleCapability fragmentCapability : fragmentCapabilities) {
+ if (NON_PAYLOAD_CAPABILITIES.contains(fragmentCapability.getNamespace())) {
+ continue; // don't include, not a payload capability
+ }
+ if (!fragmentCapability.getNamespace().equals(currentNamespace)) {
+ currentNamespace = fragmentCapability.getNamespace();
+ fastForward(iCapabilities);
+ while (iCapabilities.hasPrevious()) {
+ if (iCapabilities.previous().getNamespace().equals(currentNamespace)) {
+ iCapabilities.next(); // put position after the last one
+ break;
+ }
+ }
+ }
+ iCapabilities.add(fragmentCapability);
+ }
+ // add fragment requirements
+ currentNamespace = null;
+ List<ModuleRequirement> fragmentRequriements = hostWire.getRequirer().getModuleRequirements(null);
+ for (ModuleRequirement fragmentRequirement : fragmentRequriements) {
+ if (NON_PAYLOAD_REQUIREMENTS.contains(fragmentRequirement.getNamespace())) {
+ continue; // don't inlcude, not a payload requirement
+ }
+ if (!fragmentRequirement.getNamespace().equals(currentNamespace)) {
+ currentNamespace = fragmentRequirement.getNamespace();
+ fastForward(iRequirements);
+ while (iRequirements.hasPrevious()) {
+ if (iRequirements.previous().getNamespace().equals(currentNamespace)) {
+ iRequirements.next(); // put position after the last one
+ break;
+ }
+ }
+ }
+ iRequirements.add(fragmentRequirement);
+ }
+ }
+ }
+
+ private static void addProvidedWires(Map<ModuleCapability, List<ModuleWire>> toAdd, List<ModuleWire> existing, final List<ModuleCapability> orderedCapabilities) {
+ if (toAdd == null)
+ return;
+ int originalSize = existing.size();
+ for (ModuleCapability capability : orderedCapabilities) {
+ List<ModuleWire> newWires = toAdd.get(capability);
+ if (newWires != null) {
+ existing.addAll(newWires);
+ }
+ }
+ if (originalSize != 0) {
+ Collections.sort(existing, new Comparator<ModuleWire>() {
+ @Override
+ public int compare(ModuleWire w1, ModuleWire w2) {
+ int index1 = orderedCapabilities.indexOf(w1.getCapability());
+ int index2 = orderedCapabilities.indexOf(w2.getCapability());
+ return index1 - index2;
+ }
+ });
+ }
+ }
+
+ private static void addRequiredWires(List<ModuleWire> toAdd, List<ModuleWire> existing, final List<ModuleRequirement> orderedRequirements) {
+ if (toAdd == null)
+ return;
+ int originalSize = existing.size();
+ existing.addAll(toAdd);
+ if (originalSize != 0) {
+ Collections.sort(existing, new Comparator<ModuleWire>() {
+ @Override
+ public int compare(ModuleWire w1, ModuleWire w2) {
+ int index1 = orderedRequirements.indexOf(w1.getRequirement());
+ int index2 = orderedRequirements.indexOf(w2.getRequirement());
+ return index1 - index2;
+ }
+ });
+ }
+ }
+
+ private static void fastForward(ListIterator<?> listIterator) {
+ while (listIterator.hasNext())
+ listIterator.next();
+ }
+
+ static void rewind(ListIterator<?> listIterator) {
+ while (listIterator.hasPrevious())
+ listIterator.previous();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ModuleWiring createWiringDelta(ModuleRevision revision, ModuleWiring existingWiring, Map<ModuleCapability, List<ModuleWire>> providedWireMap, List<ModuleWire> requiredWires) {
+ // Create a ModuleWiring that only contains the new ordered list of provided wires
+ List<ModuleWire> existingProvidedWires = existingWiring.getProvidedModuleWires(null);
+ List<ModuleCapability> existingCapabilities = existingWiring.getModuleCapabilities(null);
+ addProvidedWires(providedWireMap, existingProvidedWires, existingCapabilities);
+
+ // Also need to include any new required wires that may have be added for fragment hosts
+ // Also will be needed for dynamic imports
+ List<ModuleWire> existingRequiredWires = existingWiring.getRequiredModuleWires(null);
+ List<ModuleRequirement> existingRequirements = existingWiring.getModuleRequirements(null);
+ addRequiredWires(requiredWires, existingRequiredWires, existingRequirements);
+
+ // add newly resolved fragment capabilities and requirements
+ if (providedWireMap != null) {
+ List<ModuleCapability> hostCapabilities = revision.getModuleCapabilities(HostNamespace.HOST_NAMESPACE);
+ ModuleCapability hostCapability = hostCapabilities.isEmpty() ? null : hostCapabilities.get(0);
+ List<ModuleWire> newHostWires = hostCapability == null ? null : providedWireMap.get(hostCapability);
+ if (newHostWires != null) {
+ addPayloadContent(newHostWires, existingCapabilities.listIterator(), existingRequirements.listIterator());
+ }
+ }
+
+ filterCapabilityPermissions(existingCapabilities);
+ return new ModuleWiring(revision, existingCapabilities, existingRequirements, existingProvidedWires, existingRequiredWires, Collections.EMPTY_LIST);
+ }
+
+ private static void filterCapabilityPermissions(List<ModuleCapability> capabilities) {
+ if (System.getSecurityManager() == null) {
+ return;
+ }
+ for (Iterator<ModuleCapability> iCapabilities = capabilities.iterator(); iCapabilities.hasNext();) {
+ ModuleCapability capability = iCapabilities.next();
+ Permission permission = getProvidePermission(capability);
+ Bundle provider = capability.getRevision().getBundle();
+ if (provider != null && !provider.hasPermission(permission)) {
+ iCapabilities.remove();
+ }
+ }
+ }
+
+ static boolean isSingleton(ModuleRevision revision) {
+ List<Capability> identities = revision.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ if (identities.isEmpty())
+ return false;
+ return "true".equals(identities.get(0).getDirectives().get(IdentityNamespace.CAPABILITY_SINGLETON_DIRECTIVE)); //$NON-NLS-1$
+ }
+
+ static Version getVersion(Capability c) {
+ String versionAttr = null;
+ String namespace = c.getNamespace();
+ if (IdentityNamespace.IDENTITY_NAMESPACE.equals(namespace)) {
+ versionAttr = IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+ } else if (PackageNamespace.PACKAGE_NAMESPACE.equals(namespace)) {
+ versionAttr = PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+ } else if (BundleNamespace.BUNDLE_NAMESPACE.equals(namespace)) {
+ versionAttr = BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE;
+ } else if (HostNamespace.HOST_NAMESPACE.equals(namespace)) {
+ versionAttr = HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE;
+ } else {
+ // Just default to version attribute
+ versionAttr = IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+ }
+ Object version = c.getAttributes().get(versionAttr);
+ return version instanceof Version ? (Version) version : Version.emptyVersion;
+ }
+
+ static Permission getRequirePermission(BundleCapability candidate) {
+ String name = candidate.getNamespace();
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(name)) {
+ return new PackagePermission(getPermisionName(candidate), candidate.getRevision().getBundle(), PackagePermission.IMPORT);
+ }
+ if (HostNamespace.HOST_NAMESPACE.equals(name)) {
+ return new BundlePermission(getPermisionName(candidate), BundlePermission.FRAGMENT);
+ }
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(name)) {
+ return new BundlePermission(getPermisionName(candidate), BundlePermission.REQUIRE);
+ }
+ return new CapabilityPermission(name, candidate.getAttributes(), candidate.getRevision().getBundle(), CapabilityPermission.REQUIRE);
+ }
+
+ static Permission getProvidePermission(BundleCapability candidate) {
+ String name = candidate.getNamespace();
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(name)) {
+ return new PackagePermission(getPermisionName(candidate), PackagePermission.EXPORTONLY);
+ }
+ if (HostNamespace.HOST_NAMESPACE.equals(name)) {
+ return new BundlePermission(getPermisionName(candidate), BundlePermission.HOST);
+ }
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(name)) {
+ return new BundlePermission(getPermisionName(candidate), BundlePermission.PROVIDE);
+ }
+ return new CapabilityPermission(name, CapabilityPermission.PROVIDE);
+ }
+
+ private static String getPermisionName(BundleCapability candidate) {
+ Object name = candidate.getAttributes().get(candidate.getNamespace());
+ if (name instanceof String) {
+ return (String) name;
+ }
+ if (name instanceof Collection) {
+ Collection<?> names = (Collection<?>) name;
+ return names.isEmpty() ? "unknown" : names.iterator().next().toString(); //$NON-NLS-1$
+ }
+ return "unknown"; //$NON-NLS-1$
+ }
+
+ class ResolveProcess extends ResolveContext implements Comparator<Capability> {
+ private final Collection<ModuleRevision> unresolved;
+ private final Collection<ModuleRevision> disabled;
+ private final Collection<ModuleRevision> triggers;
+ private final Collection<ModuleRevision> optionals;
+ private final boolean triggersMandatory;
+ private final ModuleDatabase moduleDatabase;
+ private final Map<ModuleRevision, ModuleWiring> wirings;
+ private final DynamicModuleRequirement dynamicReq;
+ private volatile ResolverHook hook = null;
+ private volatile Map<String, Collection<ModuleRevision>> byName = null;
+
+ ResolveProcess(Collection<ModuleRevision> unresolved, Collection<ModuleRevision> triggers, boolean triggersMandatory, Map<ModuleRevision, ModuleWiring> wirings, ModuleDatabase moduleDatabase) {
+ this.unresolved = unresolved;
+ this.disabled = new HashSet<ModuleRevision>(unresolved);
+ this.triggers = triggers;
+ this.triggersMandatory = triggersMandatory;
+ this.optionals = new ArrayList<ModuleRevision>(unresolved);
+ if (this.triggersMandatory) {
+ this.optionals.removeAll(triggers);
+ }
+ this.wirings = wirings;
+ this.moduleDatabase = moduleDatabase;
+ this.dynamicReq = null;
+ }
+
+ ResolveProcess(Collection<ModuleRevision> unresolved, DynamicModuleRequirement dynamicReq, Map<ModuleRevision, ModuleWiring> wirings, ModuleDatabase moduleDatabase) {
+ this.unresolved = unresolved;
+ this.disabled = new HashSet<ModuleRevision>(unresolved);
+ ModuleRevision revision = dynamicReq.getRevision();
+ this.triggers = new ArrayList<ModuleRevision>(1);
+ this.triggers.add(revision);
+ this.triggersMandatory = false;
+ this.optionals = new ArrayList<ModuleRevision>(unresolved);
+ this.wirings = wirings;
+ this.moduleDatabase = moduleDatabase;
+ this.dynamicReq = dynamicReq;
+ }
+
+ @Override
+ public List<Capability> findProviders(Requirement requirement) {
+ List<ModuleCapability> candidates = moduleDatabase.findCapabilities((ModuleRequirement) requirement);
+ return filterProviders(requirement, candidates);
+ }
+
+ private List<Capability> filterProviders(Requirement requirement, List<ModuleCapability> candidates) {
+ ListIterator<ModuleCapability> iCandidates = candidates.listIterator();
+ filterDisabled(iCandidates);
+ removeNonEffectiveCapabilities(iCandidates);
+ removeSubstituted(iCandidates);
+ filterPermissions((BundleRequirement) requirement, iCandidates);
+ hook.filterMatches((BundleRequirement) requirement, Converters.asListBundleCapability(candidates));
+ Collections.sort(candidates, this);
+ return Converters.asListCapability(candidates);
+ }
+
+ private void filterPermissions(BundleRequirement requirement, ListIterator<ModuleCapability> iCandidates) {
+ rewind(iCandidates);
+ if (System.getSecurityManager() == null || !iCandidates.hasNext()) {
+ return;
+ }
+
+ candidates: while (iCandidates.hasNext()) {
+ ModuleCapability candidate = iCandidates.next();
+ // TODO this is a hack for when a bundle imports and exports the same package
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace())) {
+ if (requirement.getRevision().equals(candidate.getRevision())) {
+ continue candidates;
+ }
+ }
+ Permission requirePermission = getRequirePermission(candidate);
+ Permission providePermission = getProvidePermission(candidate);
+ if (!requirement.getRevision().getBundle().hasPermission(requirePermission) || !candidate.getRevision().getBundle().hasPermission(providePermission)) {
+ iCandidates.remove();
+ }
+ }
+ }
+
+ private void filterDisabled(ListIterator<ModuleCapability> iCandidates) {
+ rewind(iCandidates);
+ while (iCandidates.hasNext()) {
+ if (disabled.contains(iCandidates.next().getResource()))
+ iCandidates.remove();
+ }
+ }
+
+ private void removeSubstituted(ListIterator<ModuleCapability> iCapabilities) {
+ rewind(iCapabilities);
+ while (iCapabilities.hasNext()) {
+ ModuleCapability capability = iCapabilities.next();
+ ModuleWiring wiring = wirings.get(capability.getRevision());
+ if (wiring != null && wiring.isSubtituted(capability)) {
+ iCapabilities.remove();
+ }
+ }
+ }
+
+ @Override
+ public int insertHostedCapability(List<Capability> capabilities, HostedCapability hostedCapability) {
+ int index = Collections.binarySearch(capabilities, hostedCapability, this);
+ if (index < 0)
+ index = -index - 1;
+ capabilities.add(index, hostedCapability);
+ return index;
+ }
+
+ @Override
+ public boolean isEffective(Requirement requirement) {
+ String effective = requirement.getDirectives().get(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
+ return effective == null || Namespace.EFFECTIVE_RESOLVE.equals(effective);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Map<Resource, Wiring> getWirings() {
+ Map<?, ?> raw = wirings;
+ return Collections.unmodifiableMap((Map<Resource, Wiring>) raw);
+ }
+
+ @Override
+ public Collection<Resource> getMandatoryResources() {
+ if (triggersMandatory) {
+ return Converters.asCollectionResource(triggers);
+ }
+ return super.getMandatoryResources();
+ }
+
+ @Override
+ public Collection<Resource> getOptionalResources() {
+ return Converters.asCollectionResource(optionals);
+ }
+
+ Map<Resource, List<Wire>> resolve() throws ResolutionException {
+ if (threadResolving.get().booleanValue()) {
+ throw new IllegalStateException("Detected a recursive resolve operation.");
+ }
+ threadResolving.set(Boolean.TRUE);
+ try {
+ try {
+ hook = adaptor.getResolverHookFactory().begin(Converters.asListBundleRevision((List<? extends BundleRevision>) triggers));
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof BundleException) {
+ BundleException be = (BundleException) e.getCause();
+ if (be.getType() == BundleException.REJECTED_BY_HOOK) {
+ throw new ResolutionException(be);
+ }
+ }
+ throw e;
+ }
+ try {
+ filterResolvable();
+ selectSingletons();
+ Map<Resource, List<Wire>> extensionWirings = resolveFrameworkExtensions();
+ if (!extensionWirings.isEmpty()) {
+ return extensionWirings;
+ }
+
+ // remove disabled from optional and triggers to prevent the resolver from resolving them
+ optionals.removeAll(disabled);
+ if (triggers.removeAll(disabled) && triggersMandatory) {
+ throw new ResolutionException("Could not resolve mandatory modules because another singleton was selected or the module was disabled: " + disabled);
+ }
+ if (dynamicReq != null) {
+ return resolveDynamic();
+ }
+ return resolver.resolve(this);
+ } finally {
+ hook.end();
+ }
+ } finally {
+ threadResolving.set(Boolean.FALSE);
+ }
+ }
+
+ private Map<Resource, List<Wire>> resolveFrameworkExtensions() {
+ // special handling only if explicitly asked to resolve an extension as mandatory.
+ ModuleRevision extension = triggersMandatory && triggers.size() == 1 ? triggers.iterator().next() : null;
+ if (extension == null) {
+ return Collections.emptyMap();
+ }
+
+ // Need the system module wiring to attach to.
+ Module systemModule = moduleDatabase.getModule(0);
+ ModuleRevision systemRevision = systemModule == null ? null : systemModule.getCurrentRevision();
+ ModuleWiring systemWiring = systemRevision == null ? null : wirings.get(systemRevision);
+ if (systemWiring == null) {
+ return Collections.emptyMap();
+ }
+
+ // Check all the non-payload requirements are met and a proper host is found
+ Map<Resource, List<Wire>> result = new HashMap<Resource, List<Wire>>(0);
+ if (!disabled.contains(extension)) {
+ List<Wire> nonPayloadWires = new ArrayList<Wire>(0);
+ boolean foundHost = false;
+ boolean payLoadRequirements = false;
+ for (ModuleRequirement requirement : extension.getModuleRequirements(null)) {
+ if (NON_PAYLOAD_REQUIREMENTS.contains(requirement.getNamespace())) {
+ List<ModuleCapability> matching = moduleDatabase.findCapabilities(requirement);
+ for (ModuleCapability candidate : matching) {
+ if (candidate.getRevision().getRevisions().getModule().getId().longValue() == 0) {
+ foundHost |= HostNamespace.HOST_NAMESPACE.equals(requirement.getNamespace());
+ nonPayloadWires.add(new ModuleWire(candidate, candidate.getRevision(), requirement, extension));
+ }
+ }
+ } else {
+ // oh oh! somehow a payload requirement got into the mix
+ payLoadRequirements |= true;
+ }
+
+ }
+ if (foundHost && !payLoadRequirements) {
+ result.put(extension, nonPayloadWires);
+ }
+ }
+ return result;
+ }
+
+ private Map<Resource, List<Wire>> resolveDynamic() throws ResolutionException {
+ if (!(resolver instanceof ResolverImpl)) {
+ throw new ResolutionException("Dynamic import resolution not supported by the resolver: " + resolver.getClass());
+ }
+ List<Capability> dynamicMatches = filterProviders(dynamicReq.getOriginal(), moduleDatabase.findCapabilities(dynamicReq));
+ Collection<Resource> ondemandFragments = Converters.asCollectionResource(moduleDatabase.getFragmentRevisions());
+
+ return ((ResolverImpl) resolver).resolve(this, dynamicReq.getRevision(), dynamicReq.getOriginal(), dynamicMatches, ondemandFragments);
+
+ }
+
+ private void filterResolvable() {
+ Collection<ModuleRevision> enabledCandidates = new ArrayList<ModuleRevision>(unresolved);
+ hook.filterResolvable(Converters.asListBundleRevision((List<? extends BundleRevision>) enabledCandidates));
+ disabled.removeAll(enabledCandidates);
+ }
+
+ private void selectSingletons() {
+ Map<String, Collection<ModuleRevision>> selectedSingletons = new HashMap<String, Collection<ModuleRevision>>();
+ for (ModuleRevision revision : unresolved) {
+ if (!isSingleton(revision) || disabled.contains(revision))
+ continue;
+ String bsn = revision.getSymbolicName();
+ Collection<ModuleRevision> selected = selectedSingletons.get(bsn);
+ if (selected != null)
+ continue; // already processed the bsn
+ selected = new ArrayList<ModuleRevision>(1);
+ selectedSingletons.put(bsn, selected);
+
+ Collection<ModuleRevision> sameBSN = getRevisions(bsn);
+ if (sameBSN.size() < 2) {
+ selected.add(revision);
+ continue;
+ }
+ // prime selected with resolved singleton bundles
+ for (ModuleRevision singleton : sameBSN) {
+ if (isSingleton(singleton) && wirings.containsKey(singleton))
+ selected.add(singleton);
+ }
+ // get the collision map for the BSN
+ Map<ModuleRevision, Collection<ModuleRevision>> collisionMap = getCollisionMap(sameBSN);
+ // process the collision map
+ for (ModuleRevision singleton : sameBSN) {
+ if (selected.contains(singleton))
+ continue; // no need to process resolved bundles
+ Collection<ModuleRevision> collisions = collisionMap.get(singleton);
+ if (collisions == null || disabled.contains(singleton))
+ continue; // not a singleton or not resolvable
+ Collection<ModuleRevision> pickOneToResolve = new ArrayList<ModuleRevision>();
+ for (ModuleRevision collision : collisions) {
+ if (selected.contains(collision)) {
+ // Must fail since there is already a selected bundle which is a collision of the singleton bundle
+ disabled.add(singleton);
+ // TODO add resolver diagnostics here
+ //state.addResolverError(singleton.getBundleDescription(), ResolverError.SINGLETON_SELECTION, collision.getBundleDescription().toString(), null);
+ break;
+ }
+ if (!pickOneToResolve.contains(collision))
+ pickOneToResolve.add(collision);
+ }
+ // need to make sure the bundle does not collide from the POV of another entry
+ for (Map.Entry<ModuleRevision, Collection<ModuleRevision>> collisionEntry : collisionMap.entrySet()) {
+ if (collisionEntry.getKey() != singleton && collisionEntry.getValue().contains(singleton)) {
+ if (selected.contains(collisionEntry.getKey())) {
+ // Must fail since there is already a selected bundle for which the singleton bundle is a collision
+ disabled.add(singleton);
+ // TODO add resolver diagnostics here
+ // state.addResolverError(singleton.getBundleDescription(), ResolverError.SINGLETON_SELECTION, collisionEntry.getKey().getBundleDescription().toString(), null);
+ break;
+ }
+ if (!pickOneToResolve.contains(collisionEntry.getKey()))
+ pickOneToResolve.add(collisionEntry.getKey());
+ }
+ }
+ if (!disabled.contains(singleton)) {
+ pickOneToResolve.add(singleton);
+ selected.add(pickOneToResolve(pickOneToResolve));
+ }
+ }
+ }
+ }
+
+ private Collection<ModuleRevision> getRevisions(String name) {
+ Map<String, Collection<ModuleRevision>> current = byName;
+ if (current == null) {
+ // generate the map using unresolved collection and wiring snap shot
+ // this is to avoid interacting with the module database
+ Set<ModuleRevision> revisions = new HashSet<ModuleRevision>();
+ revisions.addAll(unresolved);
+ revisions.addAll(wirings.keySet());
+ current = new HashMap<String, Collection<ModuleRevision>>();
+ for (ModuleRevision revision : revisions) {
+ Collection<ModuleRevision> sameName = current.get(revision.getSymbolicName());
+ if (sameName == null) {
+ sameName = new ArrayList<ModuleRevision>();
+ current.put(revision.getSymbolicName(), sameName);
+ }
+ sameName.add(revision);
+ }
+ byName = current;
+ }
+ Collection<ModuleRevision> result = current.get(name);
+ if (result == null) {
+ return Collections.emptyList();
+ }
+ return result;
+ }
+
+ private ModuleRevision pickOneToResolve(Collection<ModuleRevision> pickOneToResolve) {
+ ModuleRevision selectedVersion = null;
+ for (ModuleRevision singleton : pickOneToResolve) {
+ if (selectedVersion == null)
+ selectedVersion = singleton;
+ boolean higherVersion = selectedVersion.getVersion().compareTo(singleton.getVersion()) < 0;
+ if (higherVersion)
+ selectedVersion = singleton;
+ }
+
+ for (ModuleRevision singleton : pickOneToResolve) {
+ if (singleton != selectedVersion) {
+ disabled.add(singleton);
+ // TODO add resolver diagnostic here.
+ // state.addResolverError(singleton.getBundleDescription(), ResolverError.SINGLETON_SELECTION, selectedVersion.getBundleDescription().toString(), null);
+ }
+ }
+ return selectedVersion;
+ }
+
+ private Map<ModuleRevision, Collection<ModuleRevision>> getCollisionMap(Collection<ModuleRevision> sameBSN) {
+ Map<ModuleRevision, Collection<ModuleRevision>> result = new HashMap<ModuleRevision, Collection<ModuleRevision>>();
+ for (ModuleRevision singleton : sameBSN) {
+ if (!isSingleton(singleton) || disabled.contains(singleton))
+ continue; // ignore non-singleton and non-resolvable
+ List<BundleCapability> capabilities = new ArrayList<BundleCapability>(sameBSN.size() - 1);
+ for (ModuleRevision collision : sameBSN) {
+ if (collision == singleton || !isSingleton(collision) || disabled.contains(collision))
+ continue; // Ignore the bundle we are checking and non-singletons and non-resolvable
+ capabilities.add(getIdentity(collision));
+ }
+ hook.filterSingletonCollisions(getIdentity(singleton), capabilities);
+ Collection<ModuleRevision> collisionCandidates = new ArrayList<ModuleRevision>(capabilities.size());
+ for (BundleCapability identity : capabilities) {
+ collisionCandidates.add((ModuleRevision) identity.getRevision());
+ }
+ result.put(singleton, collisionCandidates);
+ }
+ return result;
+ }
+
+ private BundleCapability getIdentity(ModuleRevision bundle) {
+ List<BundleCapability> identities = bundle.getDeclaredCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ return identities.isEmpty() ? null : identities.get(0);
+ }
+
+ @Override
+ public int compare(Capability c1, Capability c2) {
+ // TODO Ideally this policy should be handled by the ModuleDatabase.
+ // To do that the wirings would have to be provided since the wirings may
+ // be a subset of the current wirings provided by the ModuleDatabase
+ boolean resolved1 = wirings.get(c1.getResource()) != null;
+ boolean resolved2 = wirings.get(c2.getResource()) != null;
+ if (resolved1 != resolved2)
+ return resolved1 ? -1 : 1;
+
+ Version v1 = getVersion(c1);
+ Version v2 = getVersion(c2);
+ int versionCompare = -(v1.compareTo(v2));
+ if (versionCompare != 0)
+ return versionCompare;
+
+ // We assume all resources here come from us and are ModuleRevision objects
+ ModuleRevision m1 = (ModuleRevision) c1.getResource();
+ ModuleRevision m2 = (ModuleRevision) c2.getResource();
+ Long id1 = m1.getRevisions().getModule().getId();
+ Long id2 = m2.getRevisions().getModule().getId();
+
+ if (id1.equals(id2) && !m1.equals(m2)) {
+ // sort based on revision ordering
+ List<ModuleRevision> revisions = m1.getRevisions().getModuleRevisions();
+ int index1 = revisions.indexOf(m1);
+ int index2 = revisions.indexOf(m2);
+ // we want to sort the indexes from highest to lowest
+ return index2 - index1;
+ }
+ return id1.compareTo(id2);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevision.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevision.java
new file mode 100644
index 000000000..6426dec1b
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevision.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.util.*;
+import java.util.Map.Entry;
+import org.eclipse.osgi.container.ModuleRevisionBuilder.GenericInfo;
+import org.eclipse.osgi.internal.container.Converters;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.*;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+
+/**
+ * An implementation of {@link BundleRevision}.
+ * @since 3.10
+ */
+public final class ModuleRevision implements BundleRevision {
+ private final String symbolicName;
+ private final Version version;
+ private final int types;
+ private final List<ModuleCapability> capabilities;
+ private final List<ModuleRequirement> requirements;
+ private final ModuleRevisions revisions;
+ private final Object revisionInfo;
+
+ ModuleRevision(String symbolicName, Version version, int types, List<GenericInfo> capabilityInfos, List<GenericInfo> requirementInfos, ModuleRevisions revisions, Object revisionInfo) {
+ this.symbolicName = symbolicName;
+ this.version = version;
+ this.types = types;
+ this.capabilities = createCapabilities(capabilityInfos);
+ this.requirements = createRequirements(requirementInfos);
+ this.revisions = revisions;
+ this.revisionInfo = revisionInfo;
+ }
+
+ private List<ModuleCapability> createCapabilities(List<GenericInfo> capabilityInfos) {
+ if (capabilityInfos == null || capabilityInfos.isEmpty())
+ return Collections.emptyList();
+ List<ModuleCapability> result = new ArrayList<ModuleCapability>(capabilityInfos.size());
+ for (GenericInfo info : capabilityInfos) {
+ result.add(new ModuleCapability(info.namespace, info.directives, info.attributes, this));
+ }
+ return result;
+ }
+
+ private List<ModuleRequirement> createRequirements(List<GenericInfo> requirementInfos) {
+ if (requirementInfos == null || requirementInfos.isEmpty())
+ return Collections.emptyList();
+ List<ModuleRequirement> result = new ArrayList<ModuleRequirement>(requirementInfos.size());
+ for (GenericInfo info : requirementInfos) {
+ result.add(new ModuleRequirement(info.namespace, info.directives, info.attributes, this));
+ }
+ return result;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return revisions.getBundle();
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return symbolicName;
+ }
+
+ @Override
+ public Version getVersion() {
+ return version;
+ }
+
+ @Override
+ public List<BundleCapability> getDeclaredCapabilities(String namespace) {
+ return Converters.asListBundleCapability(getModuleCapabilities(namespace));
+ }
+
+ @Override
+ public List<BundleRequirement> getDeclaredRequirements(String namespace) {
+ return Converters.asListBundleRequirement(getModuleRequirements(namespace));
+ }
+
+ /**
+ * Returns the capabilities declared by this revision
+ * @param namespace The namespace of the declared capabilities to return or
+ * {@code null} to return the declared capabilities from all namespaces.
+ * @return An unmodifiable list containing the declared capabilities.
+ */
+ public List<ModuleCapability> getModuleCapabilities(String namespace) {
+ if (namespace == null)
+ return Collections.unmodifiableList(capabilities);
+ List<ModuleCapability> result = new ArrayList<ModuleCapability>();
+ for (ModuleCapability capability : capabilities) {
+ if (namespace.equals(capability.getNamespace())) {
+ result.add(capability);
+ }
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ /**
+ * Returns the requirements declared by this revision
+ * @param namespace The namespace of the declared requirements to return or
+ * {@code null} to return the declared requirements from all namespaces.
+ * @return An unmodifiable list containing the declared requirements.
+ */
+ public List<ModuleRequirement> getModuleRequirements(String namespace) {
+ if (namespace == null)
+ return Collections.unmodifiableList(requirements);
+ List<ModuleRequirement> result = new ArrayList<ModuleRequirement>();
+ for (ModuleRequirement requirement : requirements) {
+ if (namespace.equals(requirement.getNamespace())) {
+ result.add(requirement);
+ }
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public int getTypes() {
+ return types;
+ }
+
+ @Override
+ public ModuleWiring getWiring() {
+ return revisions.getContainer().getWiring(this);
+ }
+
+ @Override
+ public List<Capability> getCapabilities(String namespace) {
+ return Converters.asListCapability(getDeclaredCapabilities(namespace));
+ }
+
+ @Override
+ public List<Requirement> getRequirements(String namespace) {
+ return Converters.asListRequirement(getDeclaredRequirements(namespace));
+ }
+
+ /**
+ * Returns the {@link ModuleRevisions revisions} for this revision.
+ * @return the {@link ModuleRevisions revisions} for this revision.
+ */
+ public ModuleRevisions getRevisions() {
+ return revisions;
+ }
+
+ /**
+ * Returns the revision info for this revision. The revision info is
+ * assigned when a revision is created to install a module or update module
+ * @return the revision info for this revision, may be {@code null}.
+ */
+ public Object getRevisionInfo() {
+ return revisionInfo;
+ }
+
+ boolean isCurrent() {
+ return !revisions.isUninstalled() && this.equals(revisions.getCurrentRevision());
+ }
+
+ @Override
+ public String toString() {
+ List<ModuleCapability> identities = getModuleCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ if (identities.isEmpty())
+ return super.toString();
+ return identities.get(0).toString();
+ }
+
+ static <V> String toString(Map<String, V> map, boolean directives) {
+ if (map.size() == 0)
+ return ""; //$NON-NLS-1$
+ String assignment = directives ? ":=" : "="; //$NON-NLS-1$ //$NON-NLS-2$
+ Set<Entry<String, V>> set = map.entrySet();
+ StringBuffer sb = new StringBuffer();
+ for (Entry<String, V> entry : set) {
+ sb.append("; "); //$NON-NLS-1$
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ if (value instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<Object> list = (List<Object>) value;
+ if (list.size() == 0)
+ continue;
+ Object component = list.get(0);
+ String className = component.getClass().getName();
+ String type = className.substring(className.lastIndexOf('.') + 1);
+ sb.append(key).append(':').append("List<").append(type).append(">").append(assignment).append('"'); //$NON-NLS-1$ //$NON-NLS-2$
+ for (Object object : list)
+ sb.append(object).append(',');
+ sb.setLength(sb.length() - 1);
+ sb.append('"');
+ } else {
+ String type = ""; //$NON-NLS-1$
+ if (!(value instanceof String)) {
+ String className = value.getClass().getName();
+ type = ":" + className.substring(className.lastIndexOf('.') + 1); //$NON-NLS-1$
+ }
+ sb.append(key).append(type).append(assignment).append('"').append(value).append('"');
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java
new file mode 100644
index 000000000..165d73b26
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.security.AllPermission;
+import java.util.*;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+import org.osgi.framework.*;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.resource.Namespace;
+
+/**
+ * A builder for creating module {@link ModuleRevision} objects. A builder can only be used by
+ * the module {@link ModuleContainer container} to build revisions when
+ * {@link ModuleContainer#install(Module, String, ModuleRevisionBuilder, Object)
+ * installing} or {@link ModuleContainer#update(Module, ModuleRevisionBuilder, Object) updating} a module.
+ * <p>
+ * The builder provides the instructions to the container for creating a {@link ModuleRevision}.
+ * They are not thread-safe; in the absence of external synchronization, they do not support concurrent access by multiple threads.
+ * @since 3.10
+ */
+public final class ModuleRevisionBuilder {
+ /**
+ * Provides information about a capability or requirement
+ */
+ public static class GenericInfo {
+ final String namespace;
+ final Map<String, String> directives;
+ final Map<String, Object> attributes;
+
+ GenericInfo(String namespace, Map<String, String> directives, Map<String, Object> attributes) {
+ this.namespace = namespace;
+ this.directives = directives;
+ this.attributes = attributes;
+ }
+
+ /**
+ * Returns the namespace of this generic info
+ * @return the namespace
+ */
+ public String getNamespace() {
+ return namespace;
+ }
+
+ /**
+ * Returns the directives of this generic info
+ * @return the directives
+ */
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ /**
+ * Returns the attributes of this generic info
+ * @return the attributes
+ */
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+ }
+
+ private String symbolicName = null;
+ private Version version = Version.emptyVersion;
+ private int types = 0;
+ private final List<GenericInfo> capabilityInfos = new ArrayList<GenericInfo>();
+ private final List<GenericInfo> requirementInfos = new ArrayList<GenericInfo>();
+
+ /**
+ * Constructs a new module builder
+ */
+ public ModuleRevisionBuilder() {
+ // nothing
+ }
+
+ /**
+ * Sets the symbolic name for the builder
+ * @param symbolicName the symbolic name
+ */
+ public void setSymbolicName(String symbolicName) {
+ this.symbolicName = symbolicName;
+ }
+
+ /**
+ * Sets the module version for the builder.
+ * @param version the version
+ */
+ public void setVersion(Version version) {
+ this.version = version;
+ }
+
+ /**
+ * Sets the module types for the builder.
+ * @param types the module types
+ */
+ public void setTypes(int types) {
+ this.types = types;
+ }
+
+ /**
+ * Adds a capability to this builder using the specified namespace, directives and attributes
+ * @param namespace the namespace of the capability
+ * @param directives the directives of the capability
+ * @param attributes the attributes of the capability
+ */
+ public void addCapability(String namespace, Map<String, String> directives, Map<String, Object> attributes) {
+ addGenericInfo(capabilityInfos, namespace, directives, attributes);
+ }
+
+ /**
+ * Returns a snapshot of the capabilities for this builder
+ * @return the capabilities
+ */
+ public List<GenericInfo> getCapabilities() {
+ return new ArrayList<GenericInfo>(capabilityInfos);
+ }
+
+ /**
+ * Adds a requirement to this builder using the specified namespace, directives and attributes
+ * @param namespace the namespace of the requirement
+ * @param directives the directives of the requirement
+ * @param attributes the attributes of the requirement
+ */
+ public void addRequirement(String namespace, Map<String, String> directives, Map<String, Object> attributes) {
+ addGenericInfo(requirementInfos, namespace, directives, attributes);
+ }
+
+ /**
+ * Returns a snapshot of the requirements for this builder
+ * @return the requirements
+ */
+ public List<GenericInfo> getRequirements() {
+ return new ArrayList<GenericInfo>(requirementInfos);
+ }
+
+ /**
+ * Returns the symbolic name for this builder.
+ * @return the symbolic name for this builder.
+ */
+ public String getSymbolicName() {
+ return symbolicName;
+ }
+
+ /**
+ * Returns the module version for this builder.
+ * @return the module version for this builder.
+ */
+ public Version getVersion() {
+ return version;
+ }
+
+ /**
+ * Returns the module type for this builder.
+ * @return the module type for this builder.
+ */
+ public int getTypes() {
+ return types;
+ }
+
+ /**
+ * Used by the container to build a new revision for a module.
+ * This builder is used to build a new {@link Module#getCurrentRevision() current}
+ * revision for the specified module.
+ * @param module the module to build a new revision for
+ * @param revisionInfo the revision info for the new revision, may be {@code null}
+ * @return the new new {@link Module#getCurrentRevision() current} revision.
+ */
+ ModuleRevision addRevision(Module module, Object revisionInfo) {
+ Collection<?> systemNames = Collections.emptyList();
+ Module systemModule = module.getContainer().getModule(0);
+ if (systemModule != null) {
+ ModuleRevision systemRevision = systemModule.getCurrentRevision();
+ List<ModuleCapability> hostCapabilities = systemRevision.getModuleCapabilities(HostNamespace.HOST_NAMESPACE);
+ for (ModuleCapability hostCapability : hostCapabilities) {
+ Object hostNames = hostCapability.getAttributes().get(HostNamespace.HOST_NAMESPACE);
+ if (hostNames instanceof Collection) {
+ systemNames = (Collection<?>) hostNames;
+ } else if (hostNames instanceof String) {
+ systemNames = Arrays.asList(hostNames);
+ }
+ }
+ }
+ ModuleRevisions revisions = module.getRevisions();
+ ModuleRevision revision = new ModuleRevision(symbolicName, version, types, capabilityInfos, requirementInfos, revisions, revisionInfo);
+ revisions.addRevision(revision);
+ module.getContainer().getAdaptor().associateRevision(revision, revisionInfo);
+
+ try {
+ List<ModuleRequirement> hostRequirements = revision.getModuleRequirements(HostNamespace.HOST_NAMESPACE);
+ for (ModuleRequirement hostRequirement : hostRequirements) {
+ FilterImpl f = null;
+ String filterSpec = hostRequirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+ if (filterSpec != null) {
+ try {
+ f = FilterImpl.newInstance(filterSpec);
+ String hostName = f.getPrimaryKeyValue(HostNamespace.HOST_NAMESPACE);
+ if (hostName != null) {
+ if (systemNames.contains(hostName)) {
+ Bundle b = module.getBundle();
+ if (b != null && !b.hasPermission(new AllPermission())) {
+ SecurityException se = new SecurityException("Must have AllPermission granted to install an extension bundle"); //$NON-NLS-1$
+ // TODO this is such a hack: making the cause a bundle exception so we can throw the right one later
+ BundleException be = new BundleException(se.getMessage(), BundleException.SECURITY_ERROR, se);
+ se.initCause(be);
+ throw se;
+ }
+ module.getContainer().checkAdminPermission(module.getBundle(), AdminPermission.EXTENSIONLIFECYCLE);
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ continue;
+ }
+ }
+ }
+ module.getContainer().checkAdminPermission(module.getBundle(), AdminPermission.LIFECYCLE);
+ } catch (SecurityException e) {
+ revisions.removeRevision(revision);
+ throw e;
+ }
+ return revision;
+ }
+
+ private static void addGenericInfo(List<GenericInfo> infos, String namespace, Map<String, String> directives, Map<String, Object> attributes) {
+ if (infos == null) {
+ infos = new ArrayList<GenericInfo>();
+ }
+ infos.add(new GenericInfo(namespace, copyUnmodifiableMap(directives), copyUnmodifiableMap(attributes)));
+ }
+
+ private static <K, V> Map<K, V> copyUnmodifiableMap(Map<K, V> map) {
+ return Collections.unmodifiableMap(new HashMap<K, V>(map));
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisions.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisions.java
new file mode 100644
index 000000000..061cc98de
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisions.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleRevisions;
+
+/**
+ * An implementation of {@link BundleRevisions} which represent a
+ * {@link Module} installed in a {@link ModuleContainer container}.
+ * The ModuleRevisions provides a bridge between the revisions, the
+ * module and the container they are associated with. The
+ * ModuleRevisions holds the information about the installation of
+ * a module in a container such as the module id and location.
+ * @since 3.10
+ */
+public final class ModuleRevisions implements BundleRevisions {
+ private final Object monitor = new Object();
+ private final Module module;
+ private final ModuleContainer container;
+ /* @GuardedBy("monitor") */
+ private final List<ModuleRevision> revisions = new ArrayList<ModuleRevision>(1);
+ /* @GuardedBy("monitor") */
+ private boolean uninstalled = false;
+ /* @GuardedBy("monitor") */
+ private ModuleRevision uninstalledCurrent;
+
+ ModuleRevisions(Module module, ModuleContainer container) {
+ this.module = module;
+ this.container = container;
+ }
+
+ public Module getModule() {
+ return module;
+ }
+
+ ModuleContainer getContainer() {
+ return container;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return module.getBundle();
+ }
+
+ @Override
+ public List<BundleRevision> getRevisions() {
+ synchronized (monitor) {
+ return new ArrayList<BundleRevision>(revisions);
+ }
+ }
+
+ public List<ModuleRevision> getModuleRevisions() {
+ synchronized (monitor) {
+ return new ArrayList<ModuleRevision>(revisions);
+ }
+ }
+
+ /**
+ * Returns the current {@link ModuleRevision revision} associated with this revisions.
+ *
+ * @return the current {@link ModuleRevision revision} associated with this revisions
+ * or {@code null} if the current revision does not exist.
+ */
+ ModuleRevision getCurrentRevision() {
+ synchronized (monitor) {
+ if (uninstalled) {
+ return uninstalledCurrent;
+ }
+ if (revisions.isEmpty()) {
+ return null;
+ }
+ return revisions.get(0);
+ }
+ }
+
+ ModuleRevision addRevision(ModuleRevision revision) {
+ synchronized (monitor) {
+ revisions.add(0, revision);
+ }
+ return revision;
+ }
+
+ boolean removeRevision(ModuleRevision revision) {
+ try {
+ synchronized (monitor) {
+ return revisions.remove(revision);
+ }
+ } finally {
+ module.cleanup(revision);
+ }
+ }
+
+ boolean isUninstalled() {
+ synchronized (monitor) {
+ return uninstalled;
+ }
+ }
+
+ void uninstall() {
+ synchronized (monitor) {
+ uninstalled = true;
+ // save off the current revision
+ if (revisions.isEmpty()) {
+ throw new IllegalStateException("Revisions is empty on uninstall!");
+ }
+ uninstalledCurrent = revisions.get(0);
+ }
+ }
+
+ public String toString() {
+ return "moduleID=" + module.getId(); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWire.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWire.java
new file mode 100644
index 000000000..624ff576c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWire.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import org.osgi.framework.wiring.BundleWire;
+
+/**
+ * An implementation of {@link BundleWire}.
+ * @since 3.10
+ */
+public final class ModuleWire implements BundleWire {
+ private final ModuleCapability capability;
+ private final ModuleRevision hostingProvider;
+ private final ModuleRequirement requirement;
+ private final ModuleRevision hostingRequirer;
+ // indicates that the wire points to valid wirings
+ // technically this should be a separate flag for requirer vs provider but that seems like overkill
+ private volatile boolean isValid = true;
+
+ ModuleWire(ModuleCapability capability, ModuleRevision hostingProvider, ModuleRequirement requirement, ModuleRevision hostingRequirer) {
+ super();
+ this.capability = capability;
+ this.hostingProvider = hostingProvider;
+ this.requirement = requirement;
+ this.hostingRequirer = hostingRequirer;
+ }
+
+ @Override
+ public ModuleCapability getCapability() {
+ return capability;
+ }
+
+ @Override
+ public ModuleRequirement getRequirement() {
+ return requirement;
+ }
+
+ @Override
+ public ModuleWiring getProviderWiring() {
+ if (!isValid) {
+ return null;
+ }
+ return hostingProvider.getWiring();
+ }
+
+ @Override
+ public ModuleWiring getRequirerWiring() {
+ if (!isValid) {
+ return null;
+ }
+ return hostingRequirer.getWiring();
+ }
+
+ @Override
+ public ModuleRevision getProvider() {
+ return hostingProvider;
+ }
+
+ @Override
+ public ModuleRevision getRequirer() {
+ return hostingRequirer;
+ }
+
+ public String toString() {
+ return getRequirement() + " -> " + getCapability(); //$NON-NLS-1$
+ }
+
+ void invalidate() {
+ this.isValid = false;
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java
new file mode 100644
index 000000000..b36fcfb0a
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.net.URL;
+import java.util.*;
+import org.eclipse.osgi.container.ModuleRevisionBuilder.GenericInfo;
+import org.eclipse.osgi.internal.container.Converters;
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.*;
+import org.osgi.resource.*;
+
+/**
+ * An implementation of {@link BundleWiring}.
+ * @since 3.10
+ */
+public final class ModuleWiring implements BundleWiring {
+ private static final RuntimePermission GET_CLASSLOADER_PERM = new RuntimePermission("getClassLoader"); //$NON-NLS-1$
+ private static final String DYNAMICALLY_ADDED_IMPORT_DIRECTIVE = "x.dynamically.added"; //$NON-NLS-1$
+ private final ModuleRevision revision;
+ private volatile List<ModuleCapability> capabilities;
+ private volatile List<ModuleRequirement> requirements;
+ private final Collection<String> substitutedPkgNames;
+ private final Object monitor = new Object();
+ private ModuleLoader loader = null;
+ private volatile List<ModuleWire> providedWires;
+ private volatile List<ModuleWire> requiredWires;
+ private volatile boolean isValid = true;
+
+ ModuleWiring(ModuleRevision revision, List<ModuleCapability> capabilities, List<ModuleRequirement> requirements, List<ModuleWire> providedWires, List<ModuleWire> requiredWires, Collection<String> substitutedPkgNames) {
+ super();
+ this.revision = revision;
+ this.capabilities = capabilities;
+ this.requirements = requirements;
+ this.providedWires = providedWires;
+ this.requiredWires = requiredWires;
+ this.substitutedPkgNames = substitutedPkgNames;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return revision.getBundle();
+ }
+
+ @Override
+ public boolean isCurrent() {
+ return isValid && revision.isCurrent();
+ }
+
+ @Override
+ public boolean isInUse() {
+ return isCurrent() || !providedWires.isEmpty() || isFragmentInUse();
+ }
+
+ private boolean isFragmentInUse() {
+ // A fragment is considered in use if it has any required host wires
+ if ((BundleRevision.TYPE_FRAGMENT & revision.getTypes()) != 0) {
+ List<ModuleWire> hostWires = getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ // hostWires may be null if the fragment wiring is no longer valid
+ return hostWires == null ? false : !hostWires.isEmpty();
+ }
+ return false;
+ }
+
+ /**
+ * Returns the same result as {@link #getCapabilities(String)} except
+ * uses type ModuleCapability.
+ * @param namespace the namespace
+ * @return the capabilities
+ * @see #getCapabilities(String)
+ */
+ public List<ModuleCapability> getModuleCapabilities(String namespace) {
+ return getModuleCapabilities(namespace, capabilities);
+ }
+
+ private List<ModuleCapability> getModuleCapabilities(String namespace, List<ModuleCapability> allCapabilities) {
+ if (!isValid)
+ return null;
+ if (namespace == null)
+ return new ArrayList<ModuleCapability>(allCapabilities);
+ List<ModuleCapability> result = new ArrayList<ModuleCapability>();
+ for (ModuleCapability capability : allCapabilities) {
+ if (namespace.equals(capability.getNamespace())) {
+ result.add(capability);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the same result as {@link #getRequirements(String)} except
+ * uses type ModuleRequirement.
+ * @param namespace the namespace
+ * @return the requirements
+ * @see #getRequirements(String)
+ */
+ public List<ModuleRequirement> getModuleRequirements(String namespace) {
+ return getModuleRequirements(namespace, requirements);
+ }
+
+ List<ModuleRequirement> getPersistentRequirements() {
+ List<ModuleRequirement> persistentRequriements = getModuleRequirements(null);
+ if (persistentRequriements == null) {
+ return null;
+ }
+ for (Iterator<ModuleRequirement> iRequirements = persistentRequriements.iterator(); iRequirements.hasNext();) {
+ ModuleRequirement requirement = iRequirements.next();
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace())) {
+ if ("true".equals(requirement.getDirectives().get(DYNAMICALLY_ADDED_IMPORT_DIRECTIVE))) { //$NON-NLS-1$
+ iRequirements.remove();
+ }
+ }
+ }
+ return persistentRequriements;
+ }
+
+ private List<ModuleRequirement> getModuleRequirements(String namespace, List<ModuleRequirement> allRequirements) {
+ if (!isValid)
+ return null;
+ if (namespace == null)
+ return new ArrayList<ModuleRequirement>(allRequirements);
+ List<ModuleRequirement> result = new ArrayList<ModuleRequirement>();
+ for (ModuleRequirement requirement : allRequirements) {
+ if (namespace.equals(requirement.getNamespace())) {
+ result.add(requirement);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List<BundleCapability> getCapabilities(String namespace) {
+ return Converters.asListBundleCapability(getModuleCapabilities(namespace));
+
+ }
+
+ @Override
+ public List<BundleRequirement> getRequirements(String namespace) {
+ return Converters.asListBundleRequirement(getModuleRequirements(namespace));
+ }
+
+ /**
+ * Returns the same result as {@link #getProvidedWires(String)} except
+ * uses type ModuleWire.
+ * @param namespace the namespace
+ * @return the wires
+ * @see #getProvidedWires(String)
+ */
+ public List<ModuleWire> getProvidedModuleWires(String namespace) {
+ return getWires(namespace, providedWires);
+ }
+
+ List<ModuleWire> getPersistentProvidedWires() {
+ return getPersistentWires(providedWires);
+ }
+
+ /**
+ * Returns the same result as {@link #getRequiredWires(String)} except
+ * uses type ModuleWire.
+ * @param namespace the namespace
+ * @return the wires
+ * @see #getRequiredWires(String)
+ */
+ public List<ModuleWire> getRequiredModuleWires(String namespace) {
+ return getWires(namespace, requiredWires);
+ }
+
+ List<ModuleWire> getPersistentRequiredWires() {
+ return getPersistentWires(requiredWires);
+ }
+
+ private List<ModuleWire> getPersistentWires(List<ModuleWire> allWires) {
+ List<ModuleWire> persistentWires = getWires(null, allWires);
+ if (persistentWires == null) {
+ return null;
+ }
+ for (Iterator<ModuleWire> iWires = persistentWires.iterator(); iWires.hasNext();) {
+ ModuleWire wire = iWires.next();
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(wire.getRequirement().getNamespace())) {
+ if ("true".equals(wire.getRequirement().getDirectives().get(DYNAMICALLY_ADDED_IMPORT_DIRECTIVE))) { //$NON-NLS-1$
+ iWires.remove();
+ }
+ }
+ }
+ return persistentWires;
+ }
+
+ @Override
+ public List<BundleWire> getProvidedWires(String namespace) {
+ return Converters.asListBundleWire(getWires(namespace, providedWires));
+ }
+
+ @Override
+ public List<BundleWire> getRequiredWires(String namespace) {
+ return Converters.asListBundleWire(getWires(namespace, requiredWires));
+ }
+
+ private List<ModuleWire> getWires(String namespace, List<ModuleWire> allWires) {
+ if (!isValid)
+ return null;
+ if (namespace == null)
+ return new ArrayList<ModuleWire>(allWires);
+ List<ModuleWire> result = new ArrayList<ModuleWire>();
+ for (ModuleWire moduleWire : allWires) {
+ if (namespace.equals(moduleWire.getCapability().getNamespace())) {
+ result.add(moduleWire);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public ModuleRevision getRevision() {
+ return revision;
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(GET_CLASSLOADER_PERM);
+ }
+
+ ModuleLoader current = getModuleLoader();
+ if (current == null) {
+ // must not be valid
+ return null;
+ }
+ return current.getClassLoader();
+ }
+
+ /**
+ * Returns the module loader for this wiring. If the module
+ * loader does not exist yet then one will be created
+ * @return the module loader for this wiring.
+ */
+ public ModuleLoader getModuleLoader() {
+ synchronized (monitor) {
+ if (!isValid) {
+ return null;
+ }
+ if (loader == null) {
+ loader = revision.getRevisions().getContainer().adaptor.createModuleLoader(this);
+ }
+ return loader;
+ }
+
+ }
+
+ @Override
+ public List<URL> findEntries(String path, String filePattern, int options) {
+ if (!hasResourcePermission())
+ return Collections.emptyList();
+ ModuleLoader current = getModuleLoader();
+ if (current == null) {
+ // must not be valid
+ return null;
+ }
+ return current.findEntries(path, filePattern, options);
+ }
+
+ @Override
+ public Collection<String> listResources(String path, String filePattern, int options) {
+ if (!hasResourcePermission())
+ return Collections.emptyList();
+ ModuleLoader current = getModuleLoader();
+ if (current == null) {
+ // must not be valid
+ return null;
+ }
+ return current.listResources(path, filePattern, options);
+ }
+
+ @Override
+ public List<Capability> getResourceCapabilities(String namespace) {
+ return Converters.asListCapability(getCapabilities(namespace));
+ }
+
+ @Override
+ public List<Requirement> getResourceRequirements(String namespace) {
+ return Converters.asListRequirement(getRequirements(namespace));
+ }
+
+ @Override
+ public List<Wire> getProvidedResourceWires(String namespace) {
+ return Converters.asListWire(getWires(namespace, providedWires));
+ }
+
+ @Override
+ public List<Wire> getRequiredResourceWires(String namespace) {
+ return Converters.asListWire(getWires(namespace, requiredWires));
+ }
+
+ @Override
+ public ModuleRevision getResource() {
+ return revision;
+ }
+
+ void setProvidedWires(List<ModuleWire> providedWires) {
+ this.providedWires = providedWires;
+ }
+
+ void setRequiredWires(List<ModuleWire> requiredWires) {
+ this.requiredWires = requiredWires;
+ }
+
+ void setCapabilities(List<ModuleCapability> capabilities) {
+ this.capabilities = capabilities;
+ }
+
+ void invalidate() {
+ ModuleLoader current;
+ synchronized (monitor) {
+ this.isValid = false;
+ current = loader;
+ loader = null;
+ }
+ revision.getRevisions().getContainer().getAdaptor().invalidateWiring(this, current);
+ }
+
+ void validate() {
+ synchronized (monitor) {
+ this.isValid = true;
+ }
+ }
+
+ boolean isSubtituted(ModuleCapability capability) {
+ if (!PackageNamespace.PACKAGE_NAMESPACE.equals(capability.getNamespace())) {
+ return false;
+ }
+ return substitutedPkgNames.contains(capability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
+ }
+
+ public boolean isSubstitutedPackage(String packageName) {
+ return substitutedPkgNames.contains(packageName);
+ }
+
+ /**
+ * Returns an unmodifiable collection of package names for
+ * package capabilities that have been substituted.
+ * @return the substituted package names
+ */
+ public Collection<String> getSubstitutedNames() {
+ return Collections.unmodifiableCollection(substitutedPkgNames);
+ }
+
+ private boolean hasResourcePermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkPermission(new AdminPermission(getBundle(), AdminPermission.RESOURCE));
+ } catch (SecurityException e) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void addDynamicImports(ModuleRevisionBuilder builder) {
+ List<GenericInfo> newImports = builder.getRequirements();
+ List<ModuleRequirement> newRequirements = new ArrayList<ModuleRequirement>();
+ for (GenericInfo info : newImports) {
+ if (!PackageNamespace.PACKAGE_NAMESPACE.equals(info.getNamespace())) {
+ throw new IllegalArgumentException("Invalid namespace for package imports: " + info.getNamespace()); //$NON-NLS-1$
+ }
+ Map<String, Object> attributes = new HashMap<String, Object>(info.getAttributes());
+ Map<String, String> directives = new HashMap<String, String>(info.getDirectives());
+ directives.put(DYNAMICALLY_ADDED_IMPORT_DIRECTIVE, "true"); //$NON-NLS-1$
+ directives.put(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, PackageNamespace.RESOLUTION_DYNAMIC);
+ newRequirements.add(new ModuleRequirement(info.getNamespace(), directives, attributes, revision));
+ }
+ ModuleDatabase moduleDatabase = revision.getRevisions().getContainer().moduleDatabase;
+ moduleDatabase.lockWrite();
+ try {
+ List<ModuleRequirement> updatedRequirements = new ArrayList<ModuleRequirement>(requirements);
+ updatedRequirements.addAll(newRequirements);
+ requirements = updatedRequirements;
+ } finally {
+ moduleDatabase.unlockWrite();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/SystemModule.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/SystemModule.java
new file mode 100644
index 000000000..4f8f7b561
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/SystemModule.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import org.eclipse.osgi.container.ModuleContainer.ContainerStartLevel;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
+import org.osgi.framework.*;
+import org.osgi.service.resolver.ResolutionException;
+
+/**
+ * @since 3.10
+ */
+public abstract class SystemModule extends Module {
+ private final Map<Thread, ContainerEvent> forStop = new HashMap<Thread, ContainerEvent>(2);
+
+ public SystemModule(ModuleContainer container) {
+ super(new Long(0), Constants.SYSTEM_BUNDLE_LOCATION, container, EnumSet.of(Settings.AUTO_START, Settings.USE_ACTIVATION_POLICY), new Integer(0));
+ }
+
+ public final void init() throws BundleException {
+ getRevisions().getContainer().checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
+ lockStateChange(ModuleEvent.STARTED);
+ try {
+ checkValid();
+ if (ACTIVE_SET.contains(getState()))
+ return;
+ getRevisions().getContainer().open();
+ if (getState().equals(State.INSTALLED)) {
+ try {
+ getRevisions().getContainer().resolve(Arrays.asList((Module) this), true);
+ } catch (ResolutionException e) {
+ if (e.getCause() instanceof BundleException) {
+ throw (BundleException) e.getCause();
+ }
+ throw new BundleException("Could not resolve module.", BundleException.RESOLVE_ERROR, e);
+ }
+ }
+ if (getState().equals(State.INSTALLED)) {
+ throw new BundleException("Could not resolve module.", BundleException.RESOLVE_ERROR);
+ }
+ setState(State.STARTING);
+ publishEvent(ModuleEvent.STARTING);
+ try {
+ initWorker();
+ } catch (Throwable t) {
+ setState(State.STOPPING);
+ publishEvent(ModuleEvent.STOPPING);
+ setState(State.RESOLVED);
+ publishEvent(ModuleEvent.STOPPED);
+ getRevisions().getContainer().close();
+ if (t instanceof BundleException) {
+ throw (BundleException) t;
+ }
+ throw new BundleException("Error initializing container.", BundleException.ACTIVATOR_ERROR, t);
+ }
+ } finally {
+ unlockStateChange(ModuleEvent.STARTED);
+ }
+ }
+
+ public ContainerEvent waitForStop(long timeout) throws InterruptedException {
+ final boolean waitForEver = timeout == 0;
+ final long start = System.currentTimeMillis();
+ final Thread current = Thread.currentThread();
+ long timeLeft = timeout;
+ ContainerEvent event = null;
+ boolean stateLocked;
+ if (timeout == 0) {
+ stateChangeLock.lockInterruptibly();
+ stateLocked = true;
+ } else {
+ stateLocked = stateChangeLock.tryLock(timeLeft, TimeUnit.MILLISECONDS);
+ }
+ timeLeft = waitForEver ? 0 : start + timeout - System.currentTimeMillis();
+ if (stateLocked) {
+ synchronized (forStop) {
+ try {
+ if (!Module.ACTIVE_SET.contains(getState())) {
+ return ContainerEvent.STOPPED;
+ }
+ event = forStop.remove(current);
+ if (event == null) {
+ forStop.put(current, null);
+ }
+ } finally {
+ stateChangeLock.unlock();
+ }
+ if (event == null) {
+ do {
+ forStop.wait(timeLeft);
+ event = forStop.remove(current);
+ if (!waitForEver) {
+ timeLeft = start + timeout - System.currentTimeMillis();
+ if (timeLeft == 0) {
+ timeLeft = -1;
+ }
+ }
+ } while (event == null && timeLeft >= 0);
+ }
+ }
+ }
+ return event == null ? ContainerEvent.STOPPED_TIMEOUT : event;
+ }
+
+ private void notifyWaitForStop(ContainerEvent event) {
+ synchronized (forStop) {
+ Collection<Thread> waiting = new ArrayList<Thread>(forStop.keySet());
+ for (Thread t : waiting) {
+ forStop.put(t, event);
+ }
+ forStop.notifyAll();
+ }
+ }
+
+ /**
+ * @throws BundleException
+ */
+ protected void initWorker() throws BundleException {
+ // Do nothing
+ }
+
+ @Override
+ public void start(StartOptions... options) throws BundleException {
+ // make sure to init if needed
+ init();
+ // Always transient
+ super.start(StartOptions.TRANSIENT, StartOptions.USE_ACTIVATION_POLICY);
+ getRevisions().getContainer().adaptor.publishContainerEvent(ContainerEvent.STARTED, this, null);
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ public void stop(StopOptions... options) throws BundleException {
+ ContainerEvent containerEvent = ContainerEvent.STOPPED_TIMEOUT;
+ // Need to lock the state change lock with no state to prevent
+ // other threads from starting the framework while we are shutting down
+ try {
+ if (stateChangeLock.tryLock(10, TimeUnit.SECONDS)) {
+ try {
+ try {
+ // Always transient
+ super.stop(StopOptions.TRANSIENT);
+ } catch (BundleException e) {
+ getRevisions().getContainer().adaptor.publishContainerEvent(ContainerEvent.ERROR, this, e);
+ // must continue on
+ }
+ if (holdsTransitionEventLock(ModuleEvent.UPDATED)) {
+ containerEvent = ContainerEvent.STOPPED_UPDATE;
+ } else if (holdsTransitionEventLock(ModuleEvent.UNRESOLVED)) {
+ containerEvent = ContainerEvent.STOPPED_REFRESH;
+ } else {
+ containerEvent = ContainerEvent.STOPPED;
+ }
+ getRevisions().getContainer().adaptor.publishContainerEvent(containerEvent, this, null);
+ getRevisions().getContainer().close();
+ } finally {
+ stateChangeLock.unlock();
+ }
+ } else {
+ throw new BundleException("Could not lock the system bundle state for shutdown.");
+ }
+ } catch (InterruptedException e) {
+ getRevisions().getContainer().adaptor.publishContainerEvent(ContainerEvent.ERROR, this, e);
+ }
+ notifyWaitForStop(containerEvent);
+ }
+
+ public void update() throws BundleException {
+ getContainer().checkAdminPermission(getBundle(), AdminPermission.LIFECYCLE);
+ State previousState;
+ lockStateChange(ModuleEvent.UPDATED);
+ try {
+ previousState = getState();
+ stop();
+ } finally {
+ unlockStateChange(ModuleEvent.UPDATED);
+ }
+ // would publish an updated event here but the listener services are down
+ switch (previousState) {
+ case STARTING :
+ init();
+ break;
+ case ACTIVE :
+ start();
+ default :
+ break;
+ }
+ }
+
+ @Override
+ protected void startWorker() throws BundleException {
+ super.startWorker();
+ ((ContainerStartLevel) getRevisions().getContainer().getFrameworkStartLevel()).doContainerStartLevel(this, ContainerStartLevel.USE_BEGINNING_START_LEVEL);
+ }
+
+ @Override
+ protected void stopWorker() throws BundleException {
+ super.stopWorker();
+ ((ContainerStartLevel) getRevisions().getContainer().getFrameworkStartLevel()).doContainerStartLevel(this, 0);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java
new file mode 100644
index 000000000..4f604a97e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java
@@ -0,0 +1,837 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container.builders;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import org.eclipse.osgi.container.ModuleRevisionBuilder;
+import org.eclipse.osgi.container.namespaces.*;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.framework.internal.core.Tokenizer;
+import org.eclipse.osgi.internal.framework.*;
+import org.eclipse.osgi.util.ManifestElement;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.*;
+import org.osgi.framework.namespace.*;
+import org.osgi.framework.wiring.BundleRevision;
+
+/**
+ * @since 3.10
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class OSGiManifestBuilderFactory {
+ private static final String ATTR_TYPE_STRING = "string"; //$NON-NLS-1$
+ private static final String ATTR_TYPE_VERSION = "version"; //$NON-NLS-1$
+ private static final String ATTR_TYPE_URI = "uri"; //$NON-NLS-1$
+ private static final String ATTR_TYPE_LONG = "long"; //$NON-NLS-1$
+ private static final String ATTR_TYPE_DOUBLE = "double"; //$NON-NLS-1$
+ private static final String ATTR_TYPE_SET = "set"; //$NON-NLS-1$
+ private static final String ATTR_TYPE_LIST = "List"; //$NON-NLS-1$
+ private static final String[] DEFINED_OSGI_VALIDATE_HEADERS = {Constants.IMPORT_PACKAGE, Constants.DYNAMICIMPORT_PACKAGE, Constants.EXPORT_PACKAGE, Constants.FRAGMENT_HOST, Constants.BUNDLE_SYMBOLICNAME, Constants.REQUIRE_BUNDLE};
+
+ public static ModuleRevisionBuilder createBuilder(Map<String, String> manifest) throws BundleException {
+ return createBuilder(manifest, null, null, null);
+ }
+
+ public static ModuleRevisionBuilder createBuilder(Map<String, String> manifest, String symbolicNameAlias, String extraExports, String extraCapabilities) throws BundleException {
+ ModuleRevisionBuilder builder = new ModuleRevisionBuilder();
+
+ int manifestVersion = getManifestVersion(manifest);
+ if (manifestVersion >= 2) {
+ validateHeaders(manifest);
+ }
+
+ Object symbolicName = getSymbolicNameAndVersion(builder, manifest, symbolicNameAlias, manifestVersion);
+
+ Collection<Map<String, Object>> exportedPackages = new ArrayList<Map<String, Object>>();
+ getPackageExports(builder, ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, manifest.get(Constants.EXPORT_PACKAGE)), symbolicName, exportedPackages);
+ if (extraExports != null) {
+ getPackageExports(builder, ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, extraExports), symbolicName, exportedPackages);
+ }
+ getPackageImports(builder, manifest, exportedPackages, manifestVersion);
+
+ getRequireBundle(builder, ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, manifest.get(Constants.REQUIRE_BUNDLE)));
+
+ getProvideCapabilities(builder, ManifestElement.parseHeader(Constants.PROVIDE_CAPABILITY, manifest.get(Constants.PROVIDE_CAPABILITY)));
+ if (extraCapabilities != null) {
+ getProvideCapabilities(builder, ManifestElement.parseHeader(Constants.PROVIDE_CAPABILITY, extraCapabilities));
+ }
+ getRequireCapabilities(builder, ManifestElement.parseHeader(Constants.REQUIRE_CAPABILITY, manifest.get(Constants.REQUIRE_CAPABILITY)));
+
+ addRequireEclipsePlatform(builder, manifest);
+
+ getEquinoxDataCapability(builder, manifest);
+
+ getFragmentHost(builder, ManifestElement.parseHeader(Constants.FRAGMENT_HOST, manifest.get(Constants.FRAGMENT_HOST)));
+
+ convertBREEs(builder, manifest);
+
+ getNativeCode(builder, manifest);
+ return builder;
+ }
+
+ private static void validateHeaders(Map<String, String> manifest) throws BundleException {
+ for (int i = 0; i < DEFINED_OSGI_VALIDATE_HEADERS.length; i++) {
+ String header = manifest.get(DEFINED_OSGI_VALIDATE_HEADERS[i]);
+ if (header != null) {
+ ManifestElement[] elements = ManifestElement.parseHeader(DEFINED_OSGI_VALIDATE_HEADERS[i], header);
+ checkForDuplicateDirectivesAttributes(DEFINED_OSGI_VALIDATE_HEADERS[i], elements);
+ if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.IMPORT_PACKAGE)
+ checkImportExportSyntax(DEFINED_OSGI_VALIDATE_HEADERS[i], elements, false, false);
+ if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.DYNAMICIMPORT_PACKAGE)
+ checkImportExportSyntax(DEFINED_OSGI_VALIDATE_HEADERS[i], elements, false, true);
+ if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.EXPORT_PACKAGE)
+ checkImportExportSyntax(DEFINED_OSGI_VALIDATE_HEADERS[i], elements, true, false);
+ if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.FRAGMENT_HOST)
+ checkExtensionBundle(DEFINED_OSGI_VALIDATE_HEADERS[i], elements, manifest);
+ } else if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.BUNDLE_SYMBOLICNAME) {
+ throw new BundleException(Constants.BUNDLE_SYMBOLICNAME + " header is required.", BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ }
+ }
+
+ private static void checkImportExportSyntax(String headerKey, ManifestElement[] elements, boolean export, boolean dynamic) throws BundleException {
+ if (elements == null)
+ return;
+ int length = elements.length;
+ Set<String> packages = new HashSet<String>(length);
+ for (int i = 0; i < length; i++) {
+ // check for duplicate imports
+ String[] packageNames = elements[i].getValueComponents();
+ for (int j = 0; j < packageNames.length; j++) {
+ if (!export && !dynamic && packages.contains(packageNames[j])) {
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[i].toString());
+ throw new BundleException(message + " : " + NLS.bind(Msg.HEADER_PACKAGE_DUPLICATES, packageNames[j]), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ // check for java.*
+ if (packageNames[j].startsWith("java.")) { //$NON-NLS-1$
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[i].toString());
+ throw new BundleException(message + " : " + NLS.bind(Msg.HEADER_PACKAGE_JAVA, packageNames[j]), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ packages.add(packageNames[j]);
+ }
+ // check for version/specification version mismatch
+ String version = elements[i].getAttribute(Constants.VERSION_ATTRIBUTE);
+ if (version != null) {
+ String specVersion = elements[i].getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if (specVersion != null && !specVersion.equals(version))
+ throw new BundleException(NLS.bind(Msg.HEADER_VERSION_ERROR, Constants.VERSION_ATTRIBUTE, Constants.PACKAGE_SPECIFICATION_VERSION), BundleException.MANIFEST_ERROR);
+ }
+ // check for bundle-symbolic-name and bundle-verion attibures
+ // (failure)
+ if (export) {
+ if (elements[i].getAttribute(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE) != null) {
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[i].toString());
+ throw new BundleException(message + " : " + NLS.bind(Msg.HEADER_EXPORT_ATTR_ERROR, Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, Constants.EXPORT_PACKAGE), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ if (elements[i].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE) != null) {
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[i].toString());
+ throw new BundleException(NLS.bind(message + " : " + Msg.HEADER_EXPORT_ATTR_ERROR, Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.EXPORT_PACKAGE), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ private static void checkForDuplicateDirectivesAttributes(String headerKey, ManifestElement[] elements) throws BundleException {
+ // check for duplicate directives
+ for (int i = 0; i < elements.length; i++) {
+ Enumeration<String> directiveKeys = elements[i].getDirectiveKeys();
+ if (directiveKeys != null) {
+ while (directiveKeys.hasMoreElements()) {
+ String key = directiveKeys.nextElement();
+ String[] directives = elements[i].getDirectives(key);
+ if (directives.length > 1) {
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[i].toString());
+ throw new BundleException(NLS.bind(message + " : " + Msg.HEADER_DIRECTIVE_DUPLICATES, key), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ }
+ }
+ Enumeration<String> attrKeys = elements[i].getKeys();
+ if (attrKeys != null) {
+ while (attrKeys.hasMoreElements()) {
+ String key = attrKeys.nextElement();
+ String[] attrs = elements[i].getAttributes(key);
+ if (attrs.length > 1) {
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[i].toString());
+ throw new BundleException(message + " : " + NLS.bind(Msg.HEADER_ATTRIBUTE_DUPLICATES, key), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+
+ private static void checkExtensionBundle(String headerKey, ManifestElement[] elements, Map<String, String> manifest) throws BundleException {
+ if (elements.length == 0)
+ return;
+ String hostName = elements[0].getValue();
+ // XXX: The extension bundle check is done against system.bundle and org.eclipse.osgi
+ if (!hostName.equals(Constants.SYSTEM_BUNDLE_SYMBOLICNAME) && !hostName.equals(EquinoxContainer.NAME)) {
+ if (elements[0].getDirective(Constants.EXTENSION_DIRECTIVE) != null) {
+ String message = NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, headerKey, elements[0].toString());
+ throw new BundleException(message + " : " + NLS.bind(Msg.HEADER_EXTENSION_ERROR, hostName), BundleException.MANIFEST_ERROR); //$NON-NLS-1$
+ }
+ } else {
+ if (manifest.get(Constants.IMPORT_PACKAGE) != null)
+ throw new BundleException("Extension bundles cannot import packages.", BundleException.MANIFEST_ERROR);
+ if (manifest.get(Constants.REQUIRE_BUNDLE) != null)
+ throw new BundleException("Extension bundles cannot require bundles.", BundleException.MANIFEST_ERROR);
+ if (manifest.get(Constants.REQUIRE_CAPABILITY) != null)
+ throw new BundleException("Extension bundles cannot require bundles.", BundleException.MANIFEST_ERROR);
+ if (manifest.get(Constants.BUNDLE_NATIVECODE) != null)
+ throw new BundleException("Extension bundles cannot have native code.", BundleException.MANIFEST_ERROR);
+
+ }
+ }
+
+ private static int getManifestVersion(Map<String, String> manifest) {
+ String manifestVersionHeader = manifest.get(Constants.BUNDLE_MANIFESTVERSION);
+ return manifestVersionHeader == null ? 1 : Integer.parseInt(manifestVersionHeader);
+ }
+
+ private static Object getSymbolicNameAndVersion(ModuleRevisionBuilder builder, Map<String, String> manifest, String symbolicNameAlias, int manifestVersion) throws BundleException {
+ boolean isFragment = manifest.get(Constants.FRAGMENT_HOST) != null;
+ builder.setTypes(isFragment ? BundleRevision.TYPE_FRAGMENT : 0);
+ String version = manifest.get(Constants.BUNDLE_VERSION);
+ try {
+ builder.setVersion((version != null) ? Version.parseVersion(version) : Version.emptyVersion);
+ } catch (IllegalArgumentException ex) {
+ if (manifestVersion >= 2) {
+ String message = NLS.bind("Invalid Manifest header \"{0}\": {1}", Constants.BUNDLE_VERSION, version);
+ throw new BundleException(message, BundleException.MANIFEST_ERROR, ex);
+ }
+ // prior to R4 the Bundle-Version header was not interpreted by the Framework;
+ // must not fail for old R3 style bundles
+ }
+
+ Object symbolicName = null;
+ String symbolicNameHeader = manifest.get(Constants.BUNDLE_SYMBOLICNAME);
+ if (symbolicNameHeader != null) {
+ ManifestElement[] symbolicNameElements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, symbolicNameHeader);
+ if (symbolicNameElements.length > 0) {
+ ManifestElement bsnElement = symbolicNameElements[0];
+ builder.setSymbolicName(bsnElement.getValue());
+ if (symbolicNameAlias != null) {
+ List<String> result = new ArrayList<String>();
+ result.add(builder.getSymbolicName());
+ result.add(symbolicNameAlias);
+ symbolicName = result;
+ } else {
+ symbolicName = builder.getSymbolicName();
+ }
+ Map<String, String> directives = getDirectives(bsnElement);
+ directives.remove(BundleNamespace.CAPABILITY_USES_DIRECTIVE);
+ directives.remove(BundleNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
+ Map<String, Object> attributes = getAttributes(bsnElement);
+ if (!isFragment) {
+ // create the bundle namespace
+ Map<String, Object> bundleAttributes = new HashMap<String, Object>(attributes);
+ bundleAttributes.put(BundleNamespace.BUNDLE_NAMESPACE, symbolicName);
+ bundleAttributes.put(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, builder.getVersion());
+ builder.addCapability(BundleNamespace.BUNDLE_NAMESPACE, directives, bundleAttributes);
+
+ // create the host namespace
+ // only if the directive is not never
+ if (!HostNamespace.FRAGMENT_ATTACHMENT_NEVER.equals(directives.get(HostNamespace.CAPABILITY_FRAGMENT_ATTACHMENT_DIRECTIVE))) {
+ Map<String, Object> hostAttributes = new HashMap<String, Object>(attributes);
+ hostAttributes.put(HostNamespace.HOST_NAMESPACE, symbolicName);
+ hostAttributes.put(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, builder.getVersion());
+ builder.addCapability(HostNamespace.HOST_NAMESPACE, directives, hostAttributes);
+ }
+ }
+ // every bundle that has a symbolic name gets an identity;
+ // never use the symbolic name alias for the identity namespace
+ Map<String, Object> identityAttributes = new HashMap<String, Object>(attributes);
+ identityAttributes.put(IdentityNamespace.IDENTITY_NAMESPACE, builder.getSymbolicName());
+ identityAttributes.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, builder.getVersion());
+ identityAttributes.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, isFragment ? IdentityNamespace.TYPE_FRAGMENT : IdentityNamespace.TYPE_BUNDLE);
+ builder.addCapability(IdentityNamespace.IDENTITY_NAMESPACE, directives, identityAttributes);
+ }
+ }
+
+ return symbolicName == null ? symbolicNameAlias : symbolicName;
+ }
+
+ private static void getPackageExports(ModuleRevisionBuilder builder, ManifestElement[] exportElements, Object symbolicName, Collection<Map<String, Object>> exportedPackages) {
+ if (exportElements == null)
+ return;
+ for (ManifestElement exportElement : exportElements) {
+ String[] packageNames = exportElement.getValueComponents();
+ Map<String, Object> attributes = getAttributes(exportElement);
+ Map<String, String> directives = getDirectives(exportElement);
+ directives.remove(PackageNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
+ String versionAttr = (String) attributes.remove(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ @SuppressWarnings("deprecation")
+ String specVersionAttr = (String) attributes.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ Version version = versionAttr == null ? (specVersionAttr == null ? Version.parseVersion(specVersionAttr) : Version.emptyVersion) : Version.parseVersion(versionAttr);
+ attributes.put(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+ if (symbolicName != null) {
+ attributes.put(PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE, symbolicName);
+ }
+ attributes.put(PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, builder.getVersion());
+ for (String packageName : packageNames) {
+ Map<String, Object> packageAttrs = new HashMap<String, Object>(attributes);
+ packageAttrs.put(PackageNamespace.PACKAGE_NAMESPACE, packageName);
+ builder.addCapability(PackageNamespace.PACKAGE_NAMESPACE, directives, packageAttrs);
+ exportedPackages.add(packageAttrs);
+ }
+ }
+ }
+
+ private static void getPackageImports(ModuleRevisionBuilder builder, Map<String, String> manifest, Collection<Map<String, Object>> exportedPackages, int manifestVersion) throws BundleException {
+ Collection<String> importPackageNames = new ArrayList<String>();
+ ManifestElement[] importElements = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, manifest.get(Constants.IMPORT_PACKAGE));
+ ManifestElement[] dynamicImportElements = ManifestElement.parseHeader(Constants.DYNAMICIMPORT_PACKAGE, manifest.get(Constants.DYNAMICIMPORT_PACKAGE));
+ addPackageImports(builder, importElements, importPackageNames, false);
+ addPackageImports(builder, dynamicImportElements, importPackageNames, true);
+ if (manifestVersion < 2)
+ addImplicitImports(builder, exportedPackages, importPackageNames);
+ }
+
+ private static void addPackageImports(ModuleRevisionBuilder builder, ManifestElement[] importElements, Collection<String> importPackageNames, boolean dynamic) {
+ if (importElements == null)
+ return;
+ for (ManifestElement importElement : importElements) {
+ String[] packageNames = importElement.getValueComponents();
+ Map<String, Object> attributes = getAttributes(importElement);
+ Map<String, String> directives = getDirectives(importElement);
+ directives.remove(PackageNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
+ directives.remove(PackageNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE);
+ if (dynamic) {
+ directives.put(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, PackageNamespace.RESOLUTION_DYNAMIC);
+ }
+ String versionRangeAttr = (String) attributes.remove(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ @SuppressWarnings("deprecation")
+ String specVersionRangeAttr = (String) attributes.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ VersionRange versionRange = versionRangeAttr == null ? (specVersionRangeAttr == null ? null : new VersionRange(specVersionRangeAttr)) : new VersionRange(versionRangeAttr);
+ String bundleVersionRangeAttr = (String) attributes.remove(PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ VersionRange bundleVersionRange = bundleVersionRangeAttr == null ? null : new VersionRange(bundleVersionRangeAttr);
+ for (String packageName : packageNames) {
+ if (dynamic && importPackageNames.contains(packageName))
+ continue; // already importing this package, don't add a dynamic import for it
+ importPackageNames.add(packageName);
+
+ // fill in the filter directive based on the attributes
+ Map<String, String> packageDirectives = new HashMap<String, String>(directives);
+ StringBuilder filter = new StringBuilder();
+ filter.append('(').append(PackageNamespace.PACKAGE_NAMESPACE).append('=').append(packageName).append(')');
+ int size = filter.length();
+ for (Map.Entry<String, Object> attribute : attributes.entrySet())
+ filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
+ if (versionRange != null)
+ filter.append(versionRange.toFilterString(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ if (bundleVersionRange != null)
+ filter.append(bundleVersionRange.toFilterString(PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ if (size != filter.length())
+ // need to add (&...)
+ filter.insert(0, "(&").append(')'); //$NON-NLS-1$
+ packageDirectives.put(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+
+ // fill in cardinality for dynamic wild cards
+ if (dynamic && packageName.indexOf('*') >= 0)
+ packageDirectives.put(PackageNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE, PackageNamespace.CARDINALITY_MULTIPLE);
+
+ builder.addRequirement(PackageNamespace.PACKAGE_NAMESPACE, packageDirectives, new HashMap<String, Object>(0));
+ }
+ }
+ }
+
+ private static void addImplicitImports(ModuleRevisionBuilder builder, Collection<Map<String, Object>> exportedPackages, Collection<String> importPackageNames) {
+ for (Map<String, Object> exportAttributes : exportedPackages) {
+ String packageName = (String) exportAttributes.get(PackageNamespace.PACKAGE_NAMESPACE);
+ if (importPackageNames.contains(packageName))
+ continue;
+ importPackageNames.add(packageName);
+ Version packageVersion = (Version) exportAttributes.get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ StringBuilder filter = new StringBuilder();
+ filter.append("(&(").append(PackageNamespace.PACKAGE_NAMESPACE).append('=').append(packageName).append(')'); //$NON-NLS-1$
+ filter.append('(').append(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE).append(">=").append(packageVersion).append("))"); //$NON-NLS-1$//$NON-NLS-2$
+ Map<String, String> directives = new HashMap<String, String>(1);
+ directives.put(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+ builder.addRequirement(PackageNamespace.PACKAGE_NAMESPACE, directives, new HashMap<String, Object>(0));
+ }
+ }
+
+ private static Map<String, String> getDirectives(ManifestElement element) {
+ Map<String, String> directives = new HashMap<String, String>();
+ Enumeration<String> keys = element.getDirectiveKeys();
+ if (keys == null)
+ return directives;
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ directives.put(key, element.getDirective(key));
+ }
+ return directives;
+ }
+
+ private static void getRequireBundle(ModuleRevisionBuilder builder, ManifestElement[] requireBundles) {
+ if (requireBundles == null)
+ return;
+ for (ManifestElement requireElement : requireBundles) {
+ String[] bundleNames = requireElement.getValueComponents();
+ Map<String, Object> attributes = getAttributes(requireElement);
+ Map<String, String> directives = getDirectives(requireElement);
+ directives.remove(BundleNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE);
+ directives.remove(BundleNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
+ String versionRangeAttr = (String) attributes.remove(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ VersionRange versionRange = versionRangeAttr == null ? null : new VersionRange(versionRangeAttr);
+ for (String bundleName : bundleNames) {
+ // fill in the filter directive based on the attributes
+ Map<String, String> bundleDirectives = new HashMap<String, String>(directives);
+ StringBuilder filter = new StringBuilder();
+ filter.append('(').append(BundleNamespace.BUNDLE_NAMESPACE).append('=').append(bundleName).append(')');
+ int size = filter.length();
+ for (Map.Entry<String, Object> attribute : attributes.entrySet())
+ filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
+ if (versionRange != null)
+ filter.append(versionRange.toFilterString(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ if (size != filter.length())
+ // need to add (&...)
+ filter.insert(0, "(&").append(')'); //$NON-NLS-1$
+ bundleDirectives.put(BundleNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+ builder.addRequirement(BundleNamespace.BUNDLE_NAMESPACE, bundleDirectives, new HashMap<String, Object>(0));
+ }
+ }
+ }
+
+ private static void getFragmentHost(ModuleRevisionBuilder builder, ManifestElement[] fragmentHosts) {
+ if (fragmentHosts == null || fragmentHosts.length == 0)
+ return;
+
+ ManifestElement fragmentHost = fragmentHosts[0];
+ String hostName = fragmentHost.getValue();
+ Map<String, Object> attributes = getAttributes(fragmentHost);
+ Map<String, String> directives = getDirectives(fragmentHost);
+ directives.remove(HostNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE);
+ directives.remove(HostNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
+
+ String versionRangeAttr = (String) attributes.remove(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ VersionRange versionRange = versionRangeAttr == null ? null : new VersionRange(versionRangeAttr);
+
+ // fill in the filter directive based on the attributes
+ StringBuilder filter = new StringBuilder();
+ filter.append('(').append(HostNamespace.HOST_NAMESPACE).append('=').append(hostName).append(')');
+ int size = filter.length();
+ for (Map.Entry<String, Object> attribute : attributes.entrySet())
+ filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
+ if (versionRange != null)
+ filter.append(versionRange.toFilterString(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ if (size != filter.length())
+ // need to add (&...)
+ filter.insert(0, "(&").append(')'); //$NON-NLS-1$
+ directives.put(BundleNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+ builder.addRequirement(HostNamespace.HOST_NAMESPACE, directives, new HashMap<String, Object>(0));
+ }
+
+ private static void getProvideCapabilities(ModuleRevisionBuilder builder, ManifestElement[] provideElements) throws BundleException {
+ if (provideElements == null)
+ return;
+ for (ManifestElement provideElement : provideElements) {
+ String[] namespaces = provideElement.getValueComponents();
+ Map<String, Object> attributes = getAttributes(provideElement);
+ Map<String, String> directives = getDirectives(provideElement);
+ for (String namespace : namespaces) {
+ if (IdentityNamespace.IDENTITY_NAMESPACE.equals(namespace))
+ throw new BundleException("A bundle is not allowed to define a capability in the " + IdentityNamespace.IDENTITY_NAMESPACE + " name space."); //$NON-NLS-1$ //$NON-NLS-2$
+ builder.addCapability(namespace, directives, attributes);
+ }
+ }
+ }
+
+ private static void getRequireCapabilities(ModuleRevisionBuilder builder, ManifestElement[] requireElements) {
+ if (requireElements == null)
+ return;
+ for (ManifestElement requireElement : requireElements) {
+ String[] namespaces = requireElement.getValueComponents();
+ Map<String, Object> attributes = getAttributes(requireElement);
+ Map<String, String> directives = getDirectives(requireElement);
+ for (String namespace : namespaces) {
+ builder.addRequirement(namespace, directives, attributes);
+ }
+ }
+ }
+
+ private static void addRequireEclipsePlatform(ModuleRevisionBuilder builder, Map<String, String> manifest) {
+ String platformFilter = manifest.get(EclipsePlatformNamespace.ECLIPSE_PLATFORM_FILTER_HEADER);
+ if (platformFilter == null) {
+ return;
+ }
+ // only support one
+ HashMap<String, String> directives = new HashMap<String, String>();
+ directives.put(EclipsePlatformNamespace.REQUIREMENT_FILTER_DIRECTIVE, platformFilter);
+ builder.addRequirement(EclipsePlatformNamespace.ECLIPSE_PLATFORM_NAMESPACE, directives, Collections.<String, Object> emptyMap());
+ }
+
+ private static void getEquinoxDataCapability(ModuleRevisionBuilder builder, Map<String, String> manifest) throws BundleException {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+
+ // Get the activation policy attributes
+ ManifestElement[] policyElements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, manifest.get(Constants.BUNDLE_ACTIVATIONPOLICY));
+ if (policyElements != null) {
+ ManifestElement policy = policyElements[0];
+ String policyName = policy.getValue();
+ if (EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY_LAZY.equals(policyName)) {
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY, policyName);
+ String includeSpec = policy.getDirective(Constants.INCLUDE_DIRECTIVE);
+ if (includeSpec != null) {
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_LAZY_INCLUDE_ATTRIBUTE, convertValueWithNoWhitespace("List<String>", includeSpec)); //$NON-NLS-1$
+ }
+ String excludeSpec = policy.getDirective(Constants.EXCLUDE_DIRECTIVE);
+ if (excludeSpec != null) {
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_LAZY_EXCLUDE_ATTRIBUTE, convertValueWithNoWhitespace("List<String>", excludeSpec)); //$NON-NLS-1$
+ }
+ }
+ } else {
+ policyElements = ManifestElement.parseHeader(EquinoxModuleDataNamespace.LAZYSTART_HEADER, manifest.get(EquinoxModuleDataNamespace.LAZYSTART_HEADER));
+ if (policyElements == null) {
+ policyElements = ManifestElement.parseHeader(EquinoxModuleDataNamespace.AUTOSTART_HEADER, manifest.get(EquinoxModuleDataNamespace.AUTOSTART_HEADER));
+ }
+ if (policyElements != null) {
+ ManifestElement policy = policyElements[0];
+ String excludeSpec = policy.getDirective(Constants.EXCLUDE_DIRECTIVE);
+ if ("true".equals(policy.getValue())) { //$NON-NLS-1$
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY, EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY_LAZY);
+ if (excludeSpec != null) {
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_LAZY_EXCLUDE_ATTRIBUTE, convertValueWithNoWhitespace("List<String>", excludeSpec)); //$NON-NLS-1$
+ }
+ } else {
+ // NOTICE - the exclude list gets converted to an include list when the header is not true
+ if (excludeSpec != null) {
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY, EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY_LAZY);
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_LAZY_INCLUDE_ATTRIBUTE, convertValueWithNoWhitespace("List<String>", excludeSpec)); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ // Get the activator
+ String activator = manifest.get(Constants.BUNDLE_ACTIVATOR);
+ if (activator != null) {
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATOR, activator);
+ }
+
+ // Get the class path
+ ManifestElement[] classpathElements = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, manifest.get(Constants.BUNDLE_CLASSPATH));
+ if (classpathElements != null) {
+ List<String> classpath = new ArrayList<String>();
+ for (ManifestElement element : classpathElements) {
+ String[] components = element.getValueComponents();
+ for (String component : components) {
+ classpath.add(component);
+ }
+ }
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_CLASSPATH, classpath);
+ }
+
+ // Get the buddy policy list
+ ManifestElement[] buddyPolicies = ManifestElement.parseHeader(EquinoxModuleDataNamespace.BUDDY_POLICY_HEADER, manifest.get(EquinoxModuleDataNamespace.BUDDY_POLICY_HEADER));
+ if (buddyPolicies != null) {
+ List<String> policies = new ArrayList<String>();
+ for (ManifestElement element : buddyPolicies) {
+ for (String component : element.getValueComponents()) {
+ policies.add(component);
+ }
+ }
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_BUDDY_POLICY, policies);
+ }
+
+ // Get the registered buddy list
+ ManifestElement[] registeredBuddies = ManifestElement.parseHeader(EquinoxModuleDataNamespace.REGISTERED_BUDDY_HEADER, manifest.get(EquinoxModuleDataNamespace.REGISTERED_BUDDY_HEADER));
+ if (registeredBuddies != null) {
+ List<String> buddies = new ArrayList<String>();
+ for (ManifestElement element : registeredBuddies) {
+ for (String component : element.getValueComponents()) {
+ buddies.add(component);
+ }
+ }
+ attributes.put(EquinoxModuleDataNamespace.CAPABILITY_BUDDY_REGISTERED, buddies);
+ }
+
+ // only create the capability if the attributes is not empty
+ if (!attributes.isEmpty()) {
+ Map<String, String> directives = Collections.singletonMap(EquinoxModuleDataNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE, EquinoxModuleDataNamespace.EFFECTIVE_INFORMATION);
+ builder.addCapability(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE, directives, attributes);
+ }
+ }
+
+ private static Map<String, Object> getAttributes(ManifestElement element) {
+ Enumeration<String> keys = element.getKeys();
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ if (keys == null)
+ return attributes;
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ String value = element.getAttribute(key);
+ int colonIndex = key.indexOf(':');
+ String type = ATTR_TYPE_STRING;
+ if (colonIndex > 0) {
+ type = key.substring(colonIndex + 1).trim();
+ key = key.substring(0, colonIndex).trim();
+ }
+ attributes.put(key, convertValue(type, value));
+ }
+ return attributes;
+ }
+
+ private static Object convertValueWithNoWhitespace(String type, String value) {
+ value = value.replaceAll("\\s", ""); //$NON-NLS-1$//$NON-NLS-2$
+ return convertValue(type, value);
+ }
+
+ private static Object convertValue(String type, String value) {
+
+ if (ATTR_TYPE_STRING.equalsIgnoreCase(type))
+ return value;
+
+ String trimmed = value.trim();
+ if (ATTR_TYPE_DOUBLE.equalsIgnoreCase(type))
+ return new Double(trimmed);
+ else if (ATTR_TYPE_LONG.equalsIgnoreCase(type))
+ return new Long(trimmed);
+ else if (ATTR_TYPE_URI.equalsIgnoreCase(type))
+ try {
+ return new URI(trimmed);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ else if (ATTR_TYPE_VERSION.equalsIgnoreCase(type))
+ return new Version(trimmed);
+ else if (ATTR_TYPE_SET.equalsIgnoreCase(type))
+ return ManifestElement.getArrayFromList(trimmed, ","); //$NON-NLS-1$
+
+ // assume list type, anything else will throw an exception
+ Tokenizer listTokenizer = new Tokenizer(type);
+ String listType = listTokenizer.getToken("<"); //$NON-NLS-1$
+ if (!ATTR_TYPE_LIST.equalsIgnoreCase(listType))
+ throw new RuntimeException("Unsupported type: " + type); //$NON-NLS-1$
+ char c = listTokenizer.getChar();
+ String componentType = ATTR_TYPE_STRING;
+ if (c == '<') {
+ componentType = listTokenizer.getToken(">"); //$NON-NLS-1$
+ if (listTokenizer.getChar() != '>')
+ throw new RuntimeException("Invalid type, missing ending '>' : " + type); //$NON-NLS-1$
+ }
+ List<String> tokens = new Tokenizer(value).getEscapedTokens(","); //$NON-NLS-1$
+ List<Object> components = new ArrayList<Object>();
+ for (String component : tokens) {
+ components.add(convertValue(componentType, component));
+ }
+ return components;
+ }
+
+ private static void convertBREEs(ModuleRevisionBuilder builder, Map<String, String> manifest) throws BundleException {
+ @SuppressWarnings("deprecation")
+ String[] brees = ManifestElement.getArrayFromList(manifest.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT));
+ if (brees == null || brees.length == 0)
+ return;
+ List<String> breeFilters = new ArrayList<String>();
+ for (String bree : brees)
+ breeFilters.add(createOSGiEERequirementFilter(bree));
+ String filterSpec;
+ if (breeFilters.size() == 1) {
+ filterSpec = breeFilters.get(0);
+ } else {
+ StringBuffer filterBuf = new StringBuffer("(|"); //$NON-NLS-1$
+ for (String breeFilter : breeFilters) {
+ filterBuf.append(breeFilter);
+ }
+ filterSpec = filterBuf.append(")").toString(); //$NON-NLS-1$
+ }
+
+ Map<String, String> directives = new HashMap<String, String>(1);
+ directives.put(ExecutionEnvironmentNamespace.REQUIREMENT_FILTER_DIRECTIVE, filterSpec);
+ builder.addRequirement(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, directives, new HashMap<String, Object>(0));
+ }
+
+ private static String createOSGiEERequirementFilter(String bree) throws BundleException {
+ String[] nameVersion = getOSGiEENameVersion(bree);
+ String eeName = nameVersion[0];
+ String v = nameVersion[1];
+ String filterSpec;
+ if (v == null)
+ filterSpec = "(osgi.ee=" + eeName + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ else
+ filterSpec = "(&(osgi.ee=" + eeName + ")(version=" + v + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ try {
+ // do a sanity check
+ FilterImpl.newInstance(filterSpec);
+ } catch (InvalidSyntaxException e) {
+ filterSpec = "(osgi.ee=" + bree + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ try {
+ // do another sanity check
+ FilterImpl.newInstance(filterSpec);
+ } catch (InvalidSyntaxException e1) {
+ throw new BundleException("Error converting required execution environment.", e1); //$NON-NLS-1$
+ }
+ }
+ return filterSpec;
+ }
+
+ private static String[] getOSGiEENameVersion(String bree) {
+ String ee1 = null;
+ String ee2 = null;
+ String v1 = null;
+ String v2 = null;
+ int separator = bree.indexOf('/');
+ if (separator <= 0 || separator == bree.length() - 1) {
+ ee1 = bree;
+ } else {
+ ee1 = bree.substring(0, separator);
+ ee2 = bree.substring(separator + 1);
+ }
+ int v1idx = ee1.indexOf('-');
+ if (v1idx > 0 && v1idx < ee1.length() - 1) {
+ // check for > 0 to avoid EEs starting with -
+ // check for < len - 1 to avoid ending with -
+ try {
+ v1 = ee1.substring(v1idx + 1);
+ // sanity check version format
+ Version.parseVersion(v1);
+ ee1 = ee1.substring(0, v1idx);
+ } catch (IllegalArgumentException e) {
+ v1 = null;
+ }
+ }
+
+ int v2idx = ee2 == null ? -1 : ee2.indexOf('-');
+ if (v2idx > 0 && v2idx < ee2.length() - 1) {
+ // check for > 0 to avoid EEs starting with -
+ // check for < len - 1 to avoid ending with -
+ try {
+ v2 = ee2.substring(v2idx + 1);
+ Version.parseVersion(v2);
+ ee2 = ee2.substring(0, v2idx);
+ } catch (IllegalArgumentException e) {
+ v2 = null;
+ }
+ }
+
+ if (v1 == null)
+ v1 = v2;
+ if (v1 != null && v2 != null && !v1.equals(v2)) {
+ ee1 = bree;
+ ee2 = null;
+ v1 = null;
+ v2 = null;
+ }
+ if ("J2SE".equals(ee1)) //$NON-NLS-1$
+ ee1 = "JavaSE"; //$NON-NLS-1$
+ if ("J2SE".equals(ee2)) //$NON-NLS-1$
+ ee2 = "JavaSE"; //$NON-NLS-1$
+
+ String eeName = ee1 + (ee2 == null ? "" : '/' + ee2); //$NON-NLS-1$
+
+ return new String[] {eeName, v1};
+ }
+
+ private static void getNativeCode(ModuleRevisionBuilder builder, Map<String, String> manifest) throws BundleException {
+ ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_NATIVECODE, manifest.get(Constants.BUNDLE_NATIVECODE));
+ if (elements == null) {
+ return;
+ }
+
+ boolean optional = elements.length > 0 && elements[elements.length - 1].getValue().equals("*"); //$NON-NLS-1$
+
+ List<String> allSelectionFilters = new ArrayList<String>(0);
+ AliasMapper aliasMapper = new AliasMapper();
+ StringBuilder allFilters = new StringBuilder();
+ allFilters.append("(|"); //$NON-NLS-1$
+ for (ManifestElement nativeCode : elements) {
+ List<String> nativePaths = new ArrayList<String>(Arrays.asList(nativeCode.getValueComponents()));
+ StringBuilder filter = new StringBuilder();
+
+ filter.append("(&"); //$NON-NLS-1$
+ addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_OSNAME, aliasMapper);
+ addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_PROCESSOR, aliasMapper);
+ addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_OSVERSION, aliasMapper);
+ addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_LANGUAGE, aliasMapper);
+ filter.append(')');
+
+ allFilters.append(filter.toString());
+ Map<String, String> directives = new HashMap<String, String>(3);
+ directives.put(EquinoxNativeCodeNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+ directives.put(EquinoxNativeCodeNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, EquinoxNativeCodeNamespace.RESOLUTION_OPTIONAL);
+ String selectionFilter = nativeCode.getAttribute(Constants.SELECTION_FILTER_ATTRIBUTE);
+ if (selectionFilter != null) {
+ allSelectionFilters.add(selectionFilter);
+ directives.put(EquinoxNativeCodeNamespace.REQUIREMENT_SELECTION_FILTER_DIRECTIVE, selectionFilter);
+ }
+
+ Map<String, Object> attributes = new HashMap<String, Object>(2);
+ attributes.put(EquinoxNativeCodeNamespace.REQUIREMENT_NATIVE_PATHS_ATTRIBUTE, nativePaths);
+ builder.addRequirement(EquinoxNativeCodeNamespace.EQUINOX_NATIVECODE_NAMESPACE, directives, attributes);
+ }
+ allFilters.append(')');
+
+ if (!optional) {
+ Map<String, String> directives = new HashMap<String, String>(2);
+ directives.put(EquinoxNativeCodeNamespace.REQUIREMENT_FILTER_DIRECTIVE, allFilters.toString());
+ if (!allSelectionFilters.isEmpty()) {
+ StringBuilder selectionFilter = new StringBuilder();
+ selectionFilter.append("(|"); //$NON-NLS-1$
+ for (String filter : allSelectionFilters) {
+ selectionFilter.append(filter);
+ }
+ selectionFilter.append(")"); //$NON-NLS-1$
+ directives.put(EquinoxNativeCodeNamespace.REQUIREMENT_SELECTION_FILTER_DIRECTIVE, selectionFilter.toString());
+ }
+ builder.addRequirement(EquinoxNativeCodeNamespace.EQUINOX_NATIVECODE_NAMESPACE, directives, Collections.<String, Object> emptyMap());
+ }
+ }
+
+ private static void addToNativeCodeFilter(StringBuilder filter, ManifestElement nativeCode, String attribute, AliasMapper aliasMapper) {
+ String[] attrValues = nativeCode.getAttributes(attribute);
+ Collection<String> attrAliases = new HashSet<String>(1);
+ if (attrValues != null) {
+ for (String attrValue : attrValues) {
+ Object aliasedName = null;
+ if (Constants.BUNDLE_NATIVECODE_OSNAME.equals(attribute)) {
+ aliasedName = aliasMapper.aliasOSName(attrValue);
+ } else if (Constants.BUNDLE_NATIVECODE_PROCESSOR.equals(attribute)) {
+ aliasedName = aliasMapper.aliasProcessor(attrValue);
+ }
+
+ if (aliasedName == null) {
+ attrAliases.add(attrValue);
+ } else if (aliasedName instanceof String) {
+ attrAliases.add(aliasedName.toString().toLowerCase());
+ } else {
+ for (Iterator<?> iAliases = ((Collection<?>) aliasedName).iterator(); iAliases.hasNext();) {
+ attrAliases.add(iAliases.next().toString().toLowerCase());
+ }
+ }
+ }
+ }
+ String filterAttribute = attribute;
+ if (Constants.BUNDLE_NATIVECODE_OSNAME.equals(attribute)) {
+ filterAttribute = EquinoxNativeCodeNamespace.CAPABILITY_OS_NAME_ATTRIBUTE;
+ } else if (Constants.BUNDLE_NATIVECODE_PROCESSOR.equals(attribute)) {
+ filterAttribute = EquinoxNativeCodeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE;
+ } else if (Constants.BUNDLE_NATIVECODE_LANGUAGE.equals(attribute)) {
+ filterAttribute = EquinoxNativeCodeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE;
+ } else if (Constants.BUNDLE_NATIVECODE_OSVERSION.equals(attribute)) {
+ filterAttribute = EquinoxNativeCodeNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE;
+ }
+ if (attrAliases.size() > 1) {
+ filter.append("(|"); //$NON-NLS-1$
+ }
+ for (String attrAlias : attrAliases) {
+ if (EquinoxNativeCodeNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE.equals(attribute)) {
+ filter.append(new VersionRange(attrAlias).toFilterString(attribute));
+ } else {
+ filter.append('(').append(filterAttribute).append('=').append(attrAlias).append(')');
+ }
+ }
+ if (attrAliases.size() > 1) {
+ filter.append(')');
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EclipsePlatformNamespace.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EclipsePlatformNamespace.java
new file mode 100644
index 000000000..be3c7ff03
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EclipsePlatformNamespace.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container.namespaces;
+
+import org.osgi.resource.Namespace;
+
+/**
+ * Eclipse Platform and Requirement Namespace.
+ *
+ * <p>
+ * This class defines the names for the attributes and directives for this
+ * namespace. All unspecified capability attributes are of type {@code String}
+ * and are used as arbitrary matching attributes for the capability. The values
+ * associated with the specified directive and attribute keys are of type
+ * {@code String}, unless otherwise indicated.
+ *
+ * @Immutable
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @since 3.10
+ */
+public class EclipsePlatformNamespace extends Namespace {
+
+ /**
+ * Namespace name for the eclipse platform. Unlike typical name spaces
+ * this namespace is not intended to be used as an attribute.
+ */
+ public static final String ECLIPSE_PLATFORM_NAMESPACE = "eclipse.platform";
+
+ /**
+ * Manifest header identifying the eclipse platform for the
+ * bundle. The framework may run this bundle if filter
+ * specified by this header matches the running eclipse platform.
+ */
+ public static final String ECLIPSE_PLATFORM_FILTER_HEADER = "Eclipse-PlatformFilter";
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxModuleDataNamespace.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxModuleDataNamespace.java
new file mode 100644
index 000000000..9901a1727
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxModuleDataNamespace.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container.namespaces;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Namespace;
+
+/**
+ * Equinox module data capability namespace. This namespace is used
+ * to store immutable data about a module revision. This includes the following
+ * <ul>
+ * <li>The activation policy as specified by the {@link Constants#BUNDLE_ACTIVATIONPOLICY}
+ * Bundle-ActivationPolicy} header.</li>
+ * <li>The activator as specified by the {@link Constants#BUNDLE_ACTIVATOR Bundle-Activator}
+ * header.</li>
+ * <li>The class path as specified by the {@link Constants#BUNDLE_CLASSPATH Bundle-ClassPath}
+ * header.</li>
+ * <li>The bundle class loading policy.
+ * </ul>
+ * Activation
+ * policy capability is provided for informational purposes and
+ * should not be considered as effective by the resolver.
+ * <p>
+ * For bundles, the attributes of this capability are extracted
+ * from the Bundle-ActivationPolicy header. The directives
+ * {@link Constants#EXCLUDE_DIRECTIVE} and {@link Constants#INCLUDE_DIRECTIVE}
+ * are converted to attributes of type {@code List<String>}.
+ *
+ * <p>
+ * This class defines the names for the attributes and directives for this
+ * namespace. Capabilities in this namespace are not intended to be used to
+ * match requirements and should not be considered as effective by a resolver.
+ *
+ * @Immutable
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @since 3.10
+ */
+public class EquinoxModuleDataNamespace extends Namespace {
+ /**
+ * The Equinox specific header for specifying a list of buddy policies.
+ */
+ public final static String BUDDY_POLICY_HEADER = "Eclipse-BuddyPolicy"; //$NON-NLS-1$
+
+ /**
+ * The Equinox specific header for specifying a list of symbolic names to register as a buddy with.
+ */
+ public final static String REGISTERED_BUDDY_HEADER = "Eclipse-RegisterBuddy"; //$NON-NLS-1$
+
+ /**
+ * The Equinox specific header for specifying the lazy start policy
+ */
+ public static final String LAZYSTART_HEADER = "Eclipse-LazyStart"; //$NON-NLS-1$
+
+ /**
+ * The Equinox specific header for specifying the lazy start policy
+ * @deprecated use {@link #LAZYSTART_HEADER}
+ */
+ public static final String AUTOSTART_HEADER = "Eclipse-AutoStart"; //$NON-NLS-1$
+
+ /**
+ * Namespace name for equinox module data. Unlike typical name spaces
+ * this namespace is not intended to be used as an attribute.
+ */
+ public static final String MODULE_DATA_NAMESPACE = "equinox.module.data"; //$NON-NLS-1$
+
+ /**
+ * The directive value identifying a {@link #CAPABILITY_EFFECTIVE_DIRECTIVE
+ * capability} that is effective for information purposes. Capabilities
+ * in this namespace must have an effective directive value of information.
+ *
+ * @see #CAPABILITY_EFFECTIVE_DIRECTIVE
+ */
+ public final static String EFFECTIVE_INFORMATION = "information"; //$NON-NLS-1$
+
+ /**
+ * The capability attribute contains the {@link Constants#BUNDLE_ACTIVATIONPOLICY
+ * activation policy} for the providing module revision. The value of this
+ * attribute must be of type {@code String}. When not specified then
+ * the module revision uses an eager activation policy.
+ */
+ public final static String CAPABILITY_ACTIVATION_POLICY = "activation.policy"; //$NON-NLS-1$
+
+ /**
+ * An activation policy name indicating the lazy activation policy
+ * is used.
+ */
+ public final static String CAPABILITY_ACTIVATION_POLICY_LAZY = "lazy"; //$NON-NLS-1$
+
+ /**
+ * When the {@link #CAPABILITY_ACTIVATION_POLICY_LAZY lazy} policy is used this
+ * attribute contains the package names that must
+ * trigger the activation when a class is loaded of these packages.
+ * If the attribute is not defined then the default is all package names.
+ * The value of this attribute must be of type {@code List<String>}.
+ */
+ public final static String CAPABILITY_LAZY_INCLUDE_ATTRIBUTE = "lazy.include"; //$NON-NLS-1$
+
+ /**
+ * When the {@link #CAPABILITY_ACTIVATION_POLICY_LAZY lazy} policy is used this
+ * attribute contains the package names that must not
+ * trigger the activation when a class is loaded of these packages.
+ * If the attribute is not defined then the default is no package names.
+ * The value of this attribute must be of type {@code List<String>}.
+ */
+ public final static String CAPABILITY_LAZY_EXCLUDE_ATTRIBUTE = "lazy.exclude"; //$NON-NLS-1$
+
+ /**
+ * The capability attribute contains the {@link Constants#BUNDLE_ACTIVATOR activator}
+ * for the providing module revision. The value of this attribute must be of type
+ * {@code String}. When not specified then the module revision has no activator.
+ */
+ public final static String CAPABILITY_ACTIVATOR = "activator"; //$NON-NLS-1$
+
+ /**
+ * The capability attribute contains the {@link Constants#BUNDLE_CLASSPATH class path}
+ * for the providing module revision. The value of this attribute must be of type
+ * {@code List<String>}. When not specified the module revision uses the default
+ * class path of '.'.
+ */
+ public final static String CAPABILITY_CLASSPATH = "classpath"; //$NON-NLS-1$
+
+ /**
+ * The capability attribute contains the list buddy loading policies
+ * for the providing module revision as specified in the Eclipse-BuddyPolicy header.
+ * The value of this attribute must be of type
+ * {@code List<String>}.
+ */
+ public final static String CAPABILITY_BUDDY_POLICY = "buddy.policy"; //$NON-NLS-1$
+
+ /**
+ * The capability attribute contains the list of symbolic names the
+ * providing module revision is a registered buddy of as specified by
+ * the Eclipse-BuddyPolicy header. The value of this attribute must be of type
+ * {@code List<String>}.
+ */
+ public final static String CAPABILITY_BUDDY_REGISTERED = "buddy.registered"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeCodeNamespace.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeCodeNamespace.java
new file mode 100644
index 000000000..45ba96db2
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeCodeNamespace.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.container.namespaces;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Namespace;
+
+/**
+ * Eclipse Platform and Requirement Namespace.
+ *
+ * <p>
+ * This class defines the names for the attributes and directives for this
+ * namespace. All unspecified capability attributes are of type {@code String}
+ * and are used as arbitrary matching attributes for the capability. The values
+ * associated with the specified directive and attribute keys are of type
+ * {@code String}, unless otherwise indicated.
+ *
+ * @Immutable
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @since 3.10
+ */
+public class EquinoxNativeCodeNamespace extends Namespace {
+
+ /**
+ * Namespace name for native code. Unlike typical name spaces
+ * this namespace is not intended to be used as an attribute.
+ */
+ public static final String EQUINOX_NATIVECODE_NAMESPACE = "equinox.native.code"; //$NON-NLS-1$
+
+ /**
+ * Specifies the supported canonical name for the environment OS.
+ * All names are lower case.
+ * The value of this attribute must be of type {@code String}.
+ */
+ public static final String CAPABILITY_OS_NAME_ATTRIBUTE = "osname"; //$NON-NLS-1$
+
+ /**
+ * Specifies the environment OS version.
+ * The value of this attribute must be of type {@code Version}.
+ */
+ public static final String CAPABILITY_OS_VERSION_ATTRIBUTE = "osversion"; //$NON-NLS-1$
+
+ /**
+ * Specifies the canonical name for the environment processor. The value
+ * is lower case.
+ * The value of this attribute must be of type {@code String}.
+ */
+ public static final String CAPABILITY_PROCESSOR_ATTRIBUTE = "processor"; //$NON-NLS-1$
+
+ /**
+ * Specifies the language supported by the environment. The value
+ * of this attribute must be of type {@code String}.
+ */
+ public static final String CAPABILITY_LANGUAGE_ATTRIBUTE = "language"; //$NON-NLS-1$
+
+ /**
+ * Specifies the paths to the native libraries for the native code requirement. If this
+ * attribute is not specified then the requirement is an overall requirement for native
+ * code. Such a requirement is used to or all the other native code requirements together
+ * to determine if the module is resolved or not.
+ * The value of this attribute must be of type {@code List<String>}.
+ */
+ public static final String REQUIREMENT_NATIVE_PATHS_ATTRIBUTE = "native.paths"; //$NON-NLS-1$
+
+ /**
+ * Specifies the arbitrary selection filter for the native code requirement. This filter
+ * is matched against the system properties.
+ * @see Constants#SELECTION_FILTER_ATTRIBUTE
+ */
+ public static final String REQUIREMENT_SELECTION_FILTER_DIRECTIVE = "selection.filter"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/CommandInterpreter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/CommandInterpreter.java
index 627d98180..627d98180 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/CommandInterpreter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/CommandInterpreter.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/CommandProvider.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/CommandProvider.java
index a176cb392..a176cb392 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/CommandProvider.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/CommandProvider.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/ConsoleSession.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/ConsoleSession.java
index 4ad021ca0..4ad021ca0 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/ConsoleSession.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/ConsoleSession.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/package.html
index d140bf5b7..d140bf5b7 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/console/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/console/package.html
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FilePath.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/FilePath.java
index 55dd1d39c..74070549e 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FilePath.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/FilePath.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.adaptor;
+package org.eclipse.osgi.framework.util;
import java.io.File;
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/Headers.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/Headers.java
index 3268b3efc..3268b3efc 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/Headers.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/Headers.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/KeyedElement.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/KeyedElement.java
index a995e5840..a995e5840 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/KeyedElement.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/KeyedElement.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/KeyedHashSet.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/KeyedHashSet.java
index 0fc3f415f..0fc3f415f 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/KeyedHashSet.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/KeyedHashSet.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/ObjectPool.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java
index 45cb44c10..93cb64511 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/util/ObjectPool.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java
@@ -13,25 +13,15 @@ package org.eclipse.osgi.framework.util;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
+import org.eclipse.osgi.internal.debug.Debug;
public class ObjectPool {
private static String OPTION_DEBUG_OBJECTPOOL_ADDS = Debug.ECLIPSE_OSGI + "/debug/objectPool/adds"; //$NON-NLS-1$
private static String OPTION_DEBUG_OBJECTPOOL_DUPS = Debug.ECLIPSE_OSGI + "/debug/objectPool/dups"; //$NON-NLS-1$
- private static final boolean DEBUG_OBJECTPOOL_ADDS;
- private static final boolean DEBUG_OBJECTPOOL_DUPS;
+ // TODO need to set these
+ private static final boolean DEBUG_OBJECTPOOL_ADDS = false;
+ private static final boolean DEBUG_OBJECTPOOL_DUPS = false;
private static Map<Object, WeakReference<Object>> objectCache = new WeakHashMap<Object, WeakReference<Object>>();
- static {
- FrameworkDebugOptions dbgOptions = FrameworkDebugOptions.getDefault();
- if (dbgOptions != null) {
- DEBUG_OBJECTPOOL_ADDS = dbgOptions.getBooleanOption(OPTION_DEBUG_OBJECTPOOL_ADDS, false);
- DEBUG_OBJECTPOOL_DUPS = dbgOptions.getBooleanOption(OPTION_DEBUG_OBJECTPOOL_DUPS, false);
- } else {
- DEBUG_OBJECTPOOL_ADDS = false;
- DEBUG_OBJECTPOOL_DUPS = false;
- }
- }
public static Object intern(Object obj) {
synchronized (objectCache) {
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorMsg.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/AdaptorMsg.java
index 751119b08..751119b08 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorMsg.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/AdaptorMsg.java
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java
index 3ff383ca4..0003d782c 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java
@@ -18,13 +18,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
-import org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorMsg;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.util.Headers;
-import org.eclipse.osgi.framework.util.ObjectPool;
-import org.eclipse.osgi.util.NLS;
+import org.eclipse.osgi.internal.debug.Debug;
import org.osgi.framework.*;
/**
@@ -76,13 +70,6 @@ public class AdaptorUtil {
while ((count = in.read(buffer, 0, buffer.length)) > 0) {
fos.write(buffer, 0, count);
}
- } catch (IOException e) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Unable to read file"); //$NON-NLS-1$
- Debug.printStackTrace(e);
- }
-
- throw e;
} finally {
if (in != null) {
try {
@@ -120,7 +107,7 @@ public class AdaptorUtil {
}
}
}
- if (Debug.DEBUG_GENERAL) {
+ if (Debug.STATIC_DEBUG_GENERAL) {
if (file.isDirectory()) {
Debug.println("rmdir " + file.getPath()); //$NON-NLS-1$
} else {
@@ -130,7 +117,7 @@ public class AdaptorUtil {
boolean success = file.delete();
- if (Debug.DEBUG_GENERAL) {
+ if (Debug.STATIC_DEBUG_GENERAL) {
if (!success) {
Debug.println(" rm failed!!"); //$NON-NLS-1$
}
@@ -157,16 +144,6 @@ public class AdaptorUtil {
}
}
- public static Version loadVersion(DataInputStream in) throws IOException {
- String versionString = readString(in, false);
- try {
- //return Version.parseVersion(versionString);
- return (Version) ObjectPool.intern(Version.parseVersion(versionString));
- } catch (IllegalArgumentException e) {
- return new InvalidVersion(versionString);
- }
- }
-
/**
* Register a service object.
* @param name the service class name
@@ -183,17 +160,6 @@ public class AdaptorUtil {
return context.registerService(name, service, properties);
}
- public static Dictionary<String, String> loadManifestFrom(BaseData bundledata) throws BundleException {
- URL url = bundledata.getEntry(Constants.OSGI_BUNDLE_MANIFEST);
- if (url == null)
- return null;
- try {
- return Headers.parseManifest(url.openStream());
- } catch (IOException e) {
- throw new BundleException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_DATA_ERROR_READING_MANIFEST, bundledata.getLocation()), BundleException.MANIFEST_ERROR, e);
- }
- }
-
public static boolean canWrite(File installDir) {
if (installDir.canWrite() == false)
return false;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/ArrayMap.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/ArrayMap.java
index 4cd862ae5..a172fec89 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/ArrayMap.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/ArrayMap.java
@@ -11,7 +11,6 @@
package org.eclipse.osgi.internal.baseadaptor;
import java.util.*;
-import org.eclipse.osgi.service.resolver.extras.Sortable;
/**
* Simple map when dealing with small amounts of entries.
@@ -20,7 +19,7 @@ import org.eclipse.osgi.service.resolver.extras.Sortable;
* @param <K> The key type
* @param <V> the value type
*/
-public class ArrayMap<K, V> implements Collection<K>, Sortable<K> {
+public class ArrayMap<K, V> implements Collection<K> {
final List<K> keys;
final List<V> values;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/ExternalMessages.properties b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/ExternalMessages.properties
index 13f045f2f..13f045f2f 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/ExternalMessages.properties
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/baseadaptor/ExternalMessages.properties
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Capabilities.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Capabilities.java
new file mode 100644
index 000000000..e5fa25b9c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Capabilities.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.container;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+import org.eclipse.osgi.util.ManifestElement;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.*;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+
+public class Capabilities {
+ public static final Pattern MANDATORY_ATTR = Pattern.compile("\\(([^(=<>]+)\\s*[=<>]\\s*[^)]+\\)");
+
+ static class NamespaceSet {
+ private final String name;
+ private final Map<String, Set<ModuleCapability>> indexes = new HashMap<String, Set<ModuleCapability>>();
+ private final Set<ModuleCapability> all = new HashSet<ModuleCapability>();
+ private final Set<ModuleCapability> nonStringIndexes = new HashSet<ModuleCapability>(0);
+ private final boolean matchMandatory;
+
+ NamespaceSet(String name) {
+ this.name = name;
+ this.matchMandatory = PackageNamespace.PACKAGE_NAMESPACE.equals(name) || BundleNamespace.BUNDLE_NAMESPACE.equals(name) || HostNamespace.HOST_NAMESPACE.equals(name);
+ }
+
+ void addCapability(ModuleCapability capability) {
+ if (!name.equals(capability.getNamespace())) {
+ throw new IllegalArgumentException("Invalid namespace: " + capability.getNamespace() + ": expecting: " + name);
+ }
+ all.add(capability);
+ // by convention we index by the namespace attribute
+ Object index = capability.getAttributes().get(name);
+ if (index == null) {
+ return;
+ }
+ Collection<?> indexCollection = null;
+ if (index instanceof Collection) {
+ indexCollection = (Collection<?>) index;
+ } else if (index.getClass().isArray()) {
+ indexCollection = Arrays.asList((Object[]) index);
+ }
+ if (indexCollection == null) {
+ addIndex(index, capability);
+ } else {
+ for (Object indexKey : indexCollection) {
+ addIndex(indexKey, capability);
+ }
+ }
+ }
+
+ private void addIndex(Object indexKey, ModuleCapability capability) {
+ if (!(indexKey instanceof String)) {
+ nonStringIndexes.add(capability);
+ } else {
+ Set<ModuleCapability> capabilities = indexes.get(indexKey);
+ if (capabilities == null) {
+ capabilities = new HashSet<ModuleCapability>(1);
+ indexes.put((String) indexKey, capabilities);
+ }
+ capabilities.add(capability);
+ }
+ }
+
+ void removeCapability(ModuleCapability capability) {
+ if (!name.equals(capability.getNamespace())) {
+ throw new IllegalArgumentException("Invalid namespace: " + capability.getNamespace() + ": expecting: " + name);
+ }
+ all.remove(capability);
+ // by convention we index by the namespace attribute
+ Object index = capability.getAttributes().get(name);
+ if (index == null) {
+ return;
+ }
+ Collection<?> indexCollection = null;
+ if (index instanceof Collection) {
+ indexCollection = (Collection<?>) index;
+ } else if (index.getClass().isArray()) {
+ indexCollection = Arrays.asList((Object[]) index);
+ }
+ if (indexCollection == null) {
+ removeIndex(index, capability);
+ } else {
+ for (Object indexKey : indexCollection) {
+ removeIndex(indexKey, capability);
+ }
+ }
+ }
+
+ private void removeIndex(Object indexKey, ModuleCapability capability) {
+ if (!(indexKey instanceof String)) {
+ nonStringIndexes.remove(capability);
+ } else {
+ Set<ModuleCapability> capabilities = indexes.get(indexKey);
+ if (capabilities != null) {
+ capabilities.remove(capability);
+ }
+ }
+ }
+
+ List<ModuleCapability> findCapabilities(ModuleRequirement requirement) {
+ if (!name.equals(requirement.getNamespace())) {
+ throw new IllegalArgumentException("Invalid namespace: " + requirement.getNamespace() + ": expecting: " + name);
+ }
+ FilterImpl f = null;
+ String filterSpec = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+ if (filterSpec != null) {
+ try {
+ f = FilterImpl.newInstance(filterSpec);
+ } catch (InvalidSyntaxException e) {
+ return Collections.emptyList();
+ }
+ }
+
+ List<ModuleCapability> result;
+ if (filterSpec == null) {
+ result = match(null, all);
+ } else {
+ String indexKey = f.getPrimaryKeyValue(name);
+ if (indexKey == null) {
+ result = match(f, all);
+ } else {
+ Set<ModuleCapability> indexed = indexes.get(indexKey);
+ if (indexed == null) {
+ result = new ArrayList<ModuleCapability>(0);
+ } else {
+ result = match(f, indexed);
+ }
+ if (!nonStringIndexes.isEmpty()) {
+ List<ModuleCapability> nonStringResult = match(f, nonStringIndexes);
+ for (ModuleCapability capability : nonStringResult) {
+ if (!result.contains(capability)) {
+ result.add(capability);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private List<ModuleCapability> match(FilterImpl f, Set<ModuleCapability> candidates) {
+ List<ModuleCapability> result = new ArrayList<ModuleCapability>(1);
+ for (ModuleCapability candidate : candidates) {
+ if (matches(f, candidate, matchMandatory)) {
+ result.add(candidate);
+ }
+ }
+ return result;
+ }
+ }
+
+ public static boolean matches(FilterImpl f, Capability candidate, boolean matchMandatory) {
+ if (f != null && !f.matches(candidate.getAttributes())) {
+ return false;
+ }
+ if (matchMandatory) {
+ // check for mandatory directive
+ String mandatory = candidate.getDirectives().get(AbstractWiringNamespace.CAPABILITY_MANDATORY_DIRECTIVE);
+ if (mandatory == null) {
+ return true;
+ }
+ if (f == null) {
+ return false;
+ }
+ Matcher matcher = MANDATORY_ATTR.matcher(f.toString());
+ String[] mandatoryAttrs = ManifestElement.getArrayFromList(mandatory, ","); //$NON-NLS-1$
+ boolean allPresent = true;
+ for (String mandatoryAttr : mandatoryAttrs) {
+ matcher.reset();
+ boolean found = false;
+ while (matcher.find()) {
+ int numGroups = matcher.groupCount();
+ for (int i = 1; i <= numGroups; i++) {
+ if (mandatoryAttr.equals(matcher.group(i))) {
+ found = true;
+ }
+ }
+ }
+ allPresent &= found;
+ }
+ return allPresent;
+ }
+ return true;
+ }
+
+ Map<String, NamespaceSet> namespaceSets = new HashMap<String, NamespaceSet>();
+
+ /**
+ * Adds the {@link ModuleRevision#getModuleCapabilities(String) capabilities}
+ * provided by the specified revision to this database. These capabilities must
+ * become available for lookup with the {@link #findCapabilities(ModuleRequirement)}
+ * method.
+ * @param revision the revision which has capabilities to add
+ */
+ public void addCapabilities(ModuleRevision revision) {
+ for (ModuleCapability capability : revision.getModuleCapabilities(null)) {
+ NamespaceSet namespaceSet = namespaceSets.get(capability.getNamespace());
+ if (namespaceSet == null) {
+ namespaceSet = new NamespaceSet(capability.getNamespace());
+ namespaceSets.put(capability.getNamespace(), namespaceSet);
+ }
+ namespaceSet.addCapability(capability);
+ }
+ }
+
+ /**
+ * Removes the {@link ModuleRevision#getModuleCapabilities(String) capabilities}
+ * provided by the specified revision from this database. These capabilities
+ * must no longer be available for lookup with the
+ * {@link #findCapabilities(ModuleRequirement)} method.
+ * @param revision
+ */
+ public void removeCapabilities(ModuleRevision revision) {
+ for (ModuleCapability capability : revision.getModuleCapabilities(null)) {
+ NamespaceSet namespaceSet = namespaceSets.get(capability.getNamespace());
+ if (namespaceSet != null) {
+ namespaceSet.removeCapability(capability);
+ }
+ }
+ }
+
+ /**
+ * Returns a mutable snapshot of capabilities that are candidates for
+ * satisfying the specified requirement.
+ * @param requirement the requirement
+ * @return the candidates for the requirement
+ */
+ public List<ModuleCapability> findCapabilities(ModuleRequirement requirement) {
+ NamespaceSet namespaceSet = namespaceSets.get(requirement.getNamespace());
+ if (namespaceSet == null) {
+ return Collections.emptyList();
+ }
+ return namespaceSet.findCapabilities(requirement);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ComputeNodeOrder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/ComputeNodeOrder.java
index ecc068032..ef2ab02bf 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ComputeNodeOrder.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/ComputeNodeOrder.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.resolver;
+package org.eclipse.osgi.internal.container;
import java.util.*;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Converters.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Converters.java
new file mode 100644
index 000000000..5c2c0fc64
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/Converters.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.container;
+
+import java.util.Collection;
+import java.util.List;
+import org.osgi.framework.wiring.*;
+import org.osgi.resource.*;
+
+public class Converters {
+
+ /**
+ * Coerce the generic type of a list from List<BundleCapability>
+ * to List<Capability>
+ * @param l List to be coerced.
+ * @return l coerced to List<Capability>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<Capability> asListCapability(List<? extends Capability> l) {
+ return (List<Capability>) l;
+ }
+
+ /**
+ * Coerce the generic type of a list from List<BundleRequirement>
+ * to List<Requirement>
+ * @param l List to be coerced.
+ * @return l coerced to List<Requirement>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<Requirement> asListRequirement(List<? extends Requirement> l) {
+ return (List<Requirement>) l;
+ }
+
+ /**
+ * Coerce the generic type of a list from List<? extends BundleCapability>
+ * to List<BundleCapability>
+ * @param l List to be coerced.
+ * @return l coerced to List<BundleCapability>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<BundleCapability> asListBundleCapability(List<? extends BundleCapability> l) {
+ return (List<BundleCapability>) l;
+ }
+
+ /**
+ * Coerce the generic type of a list from List<? extends BundleRequirement>
+ * to List<BundleRequirement>
+ * @param l List to be coerced.
+ * @return l coerced to List<BundleRequirement>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<BundleRequirement> asListBundleRequirement(List<? extends BundleRequirement> l) {
+ return (List<BundleRequirement>) l;
+ }
+
+ /**
+ * Coerce the generic type of a list from List<? extends BundleWire>
+ * to List<BundleWire>
+ * @param l List to be coerced.
+ * @return l coerced to List<BundleWire>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<BundleWire> asListBundleWire(List<? extends BundleWire> l) {
+ return (List<BundleWire>) l;
+ }
+
+ /**
+ * Coerce the generic type of a list from List<? extends BundleWire>
+ * to List<BundleWire>
+ * @param l List to be coerced.
+ * @return l coerced to List<BundleWire>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<Wire> asListWire(List<? extends Wire> l) {
+ return (List<Wire>) l;
+ }
+
+ /**
+ * Coerce the generic type of a list from List<? extends BundleRevision>
+ * to List<BundleRevision>
+ * @param l List to be coerced.
+ * @return l coerced to List<BundleRevision>
+ */
+ @SuppressWarnings("unchecked")
+ public static List<BundleRevision> asListBundleRevision(List<? extends BundleRevision> l) {
+ return (List<BundleRevision>) l;
+ }
+
+ /**
+ * Coerce the generic type of a collection from Collection<? extends Resource>
+ * to Collection<Resource>
+ * @param c List to be coerced.
+ * @return c coerced to Collection<Resource>
+ */
+ @SuppressWarnings("unchecked")
+ public static Collection<Resource> asCollectionResource(Collection<? extends Resource> c) {
+ return (Collection<Resource>) c;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/LockSet.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/LockSet.java
new file mode 100644
index 000000000..806e7fcca
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/LockSet.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.container;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+/*
+ * Implementation note: This class does not pool ReentrantLocks for the objects
+ * that are being locked. This means that if the same object is locked and unlocked
+ * over and over then new ReentrantLocks are created each time. This set should be
+ * used with care. If the same object is going to be locked/unlocked over and over then
+ * consider using a different locking strategy.
+ *
+ * Previous implementations of this class attempted to use a WeakHashMap to cache
+ * the locks, but this proved to be a flawed approach because of the unpredictable
+ * timing of garbage collection, particularly with autoboxed types (e.g. bundle
+ * long ids).
+ */
+public class LockSet<T> {
+ private final Map<T, ReentrantLock> locks = new HashMap<T, ReentrantLock>();
+ private final Object monitor = new Object();
+
+ public boolean tryLock(T t, long time, TimeUnit unit) throws InterruptedException {
+ ReentrantLock lock;
+ synchronized (monitor) {
+ lock = locks.get(t);
+ if (lock == null) {
+ lock = new ReentrantLock();
+ locks.put(t, lock);
+ }
+ }
+ boolean obtained = lock.tryLock(time, unit);
+ if (obtained) {
+ synchronized (monitor) {
+ if (lock.getHoldCount() > 1) {
+ // we don't allow reentrant locks
+ lock.unlock();
+ obtained = false;
+ } else {
+ // must check that another thread did not remove the lock
+ // when unlocking while we were waiting to obtain the lock
+ if (!locks.containsKey(t)) {
+ locks.put(t, lock);
+ }
+ }
+ }
+ }
+ return obtained;
+ }
+
+ public void unlock(T t) {
+ synchronized (monitor) {
+ ReentrantLock lock = locks.get(t);
+ if (lock == null)
+ throw new IllegalStateException("No lock found."); //$NON-NLS-1$
+ if (lock.getHoldCount() == 1) {
+ // We are about to remove the last hold;
+ // Clear out the lock from the map;
+ // This forces a new lock to get created if the same object is locked again;
+ // Must remove before unlocking to avoid removing a lock that may be waiting to
+ // be obtained by another thread in tryLock
+ locks.remove(t);
+ }
+ lock.unlock();
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AliasMapper.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java
index 728745362..ed8cd9e9a 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AliasMapper.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java
@@ -8,11 +8,12 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.framework;
import java.io.*;
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.framework.internal.core.Tokenizer;
+import org.eclipse.osgi.internal.debug.Debug;
/**
* This class maps aliases.
@@ -24,7 +25,7 @@ public class AliasMapper {
// Safe lazy initialization
private static synchronized Map<String, Object> getProcessorAliasTable() {
if (processorAliasTable == null) {
- InputStream in = AliasMapper.class.getResourceAsStream(Constants.OSGI_PROCESSOR_ALIASES);
+ InputStream in = AliasMapper.class.getResourceAsStream("processor.aliases"); //$NON-NLS-1$
if (in != null) {
try {
processorAliasTable = initAliases(in);
@@ -43,7 +44,7 @@ public class AliasMapper {
// Safe lazy initialization
private static synchronized Map<String, Object> getOSNameAliasTable() {
if (osnameAliasTable == null) {
- InputStream in = AliasMapper.class.getResourceAsStream(Constants.OSGI_OSNAME_ALIASES);
+ InputStream in = AliasMapper.class.getResourceAsStream("osname.aliases"); //$NON-NLS-1$
if (in != null) {
try {
osnameAliasTable = initAliases(in);
@@ -146,9 +147,7 @@ public class AliasMapper {
}
}
} catch (IOException e) {
- if (Debug.DEBUG_GENERAL) {
- Debug.printStackTrace(e);
- }
+ Debug.printStackTrace(e);
}
return aliases;
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java
index a6581cd2d..e9987f253 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,19 +9,25 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.framework;
-import java.io.File;
-import java.io.InputStream;
+import java.io.*;
+import java.net.URLConnection;
import java.security.*;
import java.util.*;
-import org.eclipse.osgi.event.BatchBundleListener;
-import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleWiring;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.eventmgr.EventDispatcher;
-import org.eclipse.osgi.internal.profile.Profile;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.serviceregistry.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
+import org.osgi.framework.hooks.bundle.FindHook;
+import org.osgi.resource.Capability;
/**
* Bundle's execution context.
@@ -32,7 +38,7 @@ import org.osgi.framework.*;
*/
public class BundleContextImpl implements BundleContext, EventDispatcher<Object, Object, Object> {
- private static boolean SET_TCCL = "true".equals(FrameworkProperties.getProperty("eclipse.bundle.setTCCL", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ static final String findHookName = FindHook.class.getName();
/** true if the bundle context is still valid */
private volatile boolean valid;
@@ -40,10 +46,11 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
// This slot is accessed directly by the Framework instead of using
// the getBundle() method because the Framework needs access to the bundle
// even when the context is invalid while the close method is being called.
- final BundleHost bundle;
+ final EquinoxBundle bundle;
- /** Internal framework object. */
- final Framework framework;
+ /** Internal equinox container object. */
+ final EquinoxContainer container;
+ final Debug debug;
/** Services that bundle is using. Key is ServiceRegistrationImpl,
Value is ServiceUse */
@@ -62,10 +69,11 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
*
* @param bundle The bundle we are wrapping.
*/
- protected BundleContextImpl(BundleHost bundle) {
+ public BundleContextImpl(EquinoxBundle bundle, EquinoxContainer container) {
this.bundle = bundle;
+ this.container = container;
+ this.debug = container.getConfiguration().getDebug();
valid = true;
- framework = bundle.framework;
synchronized (contextLock) {
servicesInUse = null;
}
@@ -79,10 +87,10 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
protected void close() {
valid = false; /* invalidate context */
- final ServiceRegistry registry = framework.getServiceRegistry();
+ final ServiceRegistry registry = container.getServiceRegistry();
registry.removeAllServiceListeners(this);
- framework.removeAllListeners(this);
+ container.getEventPublisher().removeAllListeners(this);
/* service's registered by the bundle, if any, are unregistered. */
registry.unregisterServices(this);
@@ -109,7 +117,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
sm.checkPropertyAccess(key);
}
- return (framework.getProperty(key));
+ return (container.getConfiguration().getProperty(key));
}
/**
@@ -123,7 +131,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
return getBundleImpl();
}
- public AbstractBundle getBundleImpl() {
+ public EquinoxBundle getBundleImpl() {
return bundle;
}
@@ -133,8 +141,14 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
public Bundle installBundle(String location, InputStream in) throws BundleException {
checkValid();
- //note AdminPermission is checked after bundle is loaded
- return framework.installBundle(location, in, this);
+ try {
+ URLConnection content = container.getStorage().getContentConnection(null, location, in);
+ Generation generation = container.getStorage().install(bundle.getModule(), location, content);
+ return generation.getRevision().getBundle();
+ } catch (IOException e) {
+ throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
+ }
+
}
/**
@@ -145,22 +159,24 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
* if the identifier doesn't match any installed bundle.
*/
public Bundle getBundle(long id) {
- return framework.getBundle(this, id);
+ Module m = container.getStorage().getModuleContainer().getModule(id);
+ if (m == null) {
+ return null;
+ }
+ if (getBundle().getBundleId() != 0) {
+ List<Bundle> bundles = new ArrayList<Bundle>(1);
+ bundles.add(m.getBundle());
+ notifyFindHooks(this, bundles);
+ if (bundles.isEmpty()) {
+ return null;
+ }
+ }
+ return m.getBundle();
}
public Bundle getBundle(String location) {
- return framework.getBundleByLocation(location);
- }
-
- /**
- * Retrieve the bundle that has the given location.
- *
- * @param location The location string of the bundle to retrieve.
- * @return A Bundle object, or <code>null</code>
- * if the location doesn't match any installed bundle.
- */
- public AbstractBundle getBundleByLocation(String location) {
- return (framework.getBundleByLocation(location));
+ Module m = container.getStorage().getModuleContainer().getModule(location);
+ return m == null ? null : m.getBundle();
}
/**
@@ -169,51 +185,63 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
* of the call to getBundles, but the framework is a very dynamic
* environment and bundles can be installed or uninstalled at anytime.
*
- * @return An array of {@link AbstractBundle} objects, one
+ * @return An array of {@link Bundle} objects, one
* object per installed bundle.
*/
public Bundle[] getBundles() {
- return framework.getBundles(this);
+ List<Module> modules = container.getStorage().getModuleContainer().getModules();
+ List<Bundle> bundles = new ArrayList<Bundle>(modules.size());
+ for (Module module : modules) {
+ bundles.add(module.getBundle());
+ }
+ if (getBundle().getBundleId() != 0) {
+ notifyFindHooks(this, bundles);
+ }
+ return bundles.toArray(new Bundle[bundles.size()]);
+ }
+
+ private void notifyFindHooks(final BundleContextImpl context, List<Bundle> allBundles) {
+ final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(allBundles);
+ if (System.getSecurityManager() == null) {
+ notifyFindHooksPriviledged(context, shrinkable);
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ notifyFindHooksPriviledged(context, shrinkable);
+ return null;
+ }
+ });
+ }
+ }
+
+ void notifyFindHooksPriviledged(final BundleContextImpl context, final Collection<Bundle> allBundles) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("notifyBundleFindHooks(" + allBundles + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ container.getServiceRegistry().notifyHooksPrivileged(new HookContext() {
+ public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
+ if (hook instanceof FindHook) {
+ ((FindHook) hook).find(context, allBundles);
+ }
+ }
+
+ public String getHookClassName() {
+ return findHookName;
+ }
+
+ public String getHookMethodName() {
+ return "find"; //$NON-NLS-1$
+ }
+ });
}
- /**
- * Add a service listener with a filter.
- * {@link ServiceListener}s are notified when a service has a lifecycle
- * state change.
- * See {@link #getServiceReferences(String, String) getServiceReferences}
- * for a description of the filter syntax.
- * The listener is added to the context bundle's list of listeners.
- * See {@link #getBundle() getBundle()}
- * for a definition of context bundle.
- *
- * <p>The listener is called if the filter criteria is met.
- * To filter based upon the class of the service, the filter
- * should reference the "objectClass" property.
- * If the filter paramater is <code>null</code>, all services
- * are considered to match the filter.
- * <p>If the Java runtime environment supports permissions, then additional
- * filtering is done.
- * {@link AbstractBundle#hasPermission(Object) Bundle.hasPermission} is called for the
- * bundle which defines the listener to validate that the listener has the
- * {@link ServicePermission} permission to <code>"get"</code> the service
- * using at least one of the named classes the service was registered under.
- *
- * @param listener The service listener to add.
- * @param filter The filter criteria.
- * @exception InvalidSyntaxException If the filter parameter contains
- * an invalid filter string which cannot be parsed.
- * @see ServiceEvent
- * @see ServiceListener
- * @exception java.lang.IllegalStateException
- * If the bundle context has stopped.
- */
public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
- framework.getServiceRegistry().addServiceListener(this, listener, filter);
+ container.getServiceRegistry().addServiceListener(this, listener, filter);
}
/**
@@ -229,7 +257,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
try {
addServiceListener(listener, null);
} catch (InvalidSyntaxException e) {
- if (Debug.DEBUG_GENERAL) {
+ if (debug.DEBUG_GENERAL) {
Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(e);
}
@@ -255,7 +283,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
if (listener == null) {
throw new IllegalArgumentException();
}
- framework.getServiceRegistry().removeServiceListener(this, listener);
+ container.getServiceRegistry().removeServiceListener(this, listener);
}
/**
@@ -278,12 +306,12 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
throw new IllegalArgumentException();
}
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("addBundleListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- framework.addBundleListener(listener, this);
+ container.getEventPublisher().addBundleListener(listener, this);
}
/**
@@ -305,12 +333,12 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
throw new IllegalArgumentException();
}
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("removeBundleListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- framework.removeBundleListener(listener, this);
+ container.getEventPublisher().removeBundleListener(listener, this);
}
/**
@@ -332,12 +360,12 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
throw new IllegalArgumentException();
}
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("addFrameworkListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- framework.addFrameworkListener(listener, this);
+ container.getEventPublisher().addFrameworkListener(listener, this);
}
/**
@@ -359,12 +387,12 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
throw new IllegalArgumentException();
}
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("removeFrameworkListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- framework.removeFrameworkListener(listener, this);
+ container.getEventPublisher().removeFrameworkListener(listener, this);
}
/**
@@ -430,7 +458,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
*/
public ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties) {
checkValid();
- return framework.getServiceRegistry().registerService(this, clazzes, service, properties);
+ return container.getServiceRegistry().registerService(this, clazzes, service, properties);
}
/**
@@ -496,12 +524,12 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
*/
public ServiceReference<?>[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
checkValid();
- return framework.getServiceRegistry().getServiceReferences(this, clazz, filter, false);
+ return container.getServiceRegistry().getServiceReferences(this, clazz, filter, false);
}
public ServiceReference<?>[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
checkValid();
- return framework.getServiceRegistry().getServiceReferences(this, clazz, filter, true);
+ return container.getServiceRegistry().getServiceReferences(this, clazz, filter, true);
}
/**
@@ -527,7 +555,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
public ServiceReference<?> getServiceReference(String clazz) {
checkValid();
- return framework.getServiceRegistry().getServiceReference(this, clazz);
+ return container.getServiceRegistry().getServiceReference(this, clazz);
}
/**
@@ -591,7 +619,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
}
@SuppressWarnings("unchecked")
- S service = (S) framework.getServiceRegistry().getService(this, (ServiceReferenceImpl<S>) reference);
+ S service = (S) container.getServiceRegistry().getService(this, (ServiceReferenceImpl<S>) reference);
return service;
}
@@ -633,7 +661,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
public boolean ungetService(ServiceReference<?> reference) {
checkValid();
- return framework.getServiceRegistry().ungetService(this, (ServiceReferenceImpl<?>) reference);
+ return container.getServiceRegistry().ungetService(this, (ServiceReferenceImpl<?>) reference);
}
/**
@@ -663,7 +691,8 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
public File getDataFile(String filename) {
checkValid();
- return (framework.getDataFile(bundle, filename));
+ Generation generation = (Generation) bundle.getModule().getCurrentRevision().getRevisionInfo();
+ return generation.getBundleInfo().getDataFile(filename);
}
/**
@@ -676,7 +705,14 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
* method failed
*/
protected void start() throws BundleException {
- activator = bundle.loadBundleActivator();
+ try {
+ activator = loadBundleActivator();
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new BundleException("Error loading bundle activator.", BundleException.ACTIVATOR_ERROR, e);
+ }
if (activator != null) {
try {
@@ -691,19 +727,35 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
same activator object when we stop this bundle. */
}
+ private BundleActivator loadBundleActivator() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ ModuleWiring wiring = bundle.getModule().getCurrentRevision().getWiring();
+ if (wiring == null) {
+ return null;
+ }
+
+ BundleLoader loader = (BundleLoader) wiring.getModuleLoader();
+ List<Capability> metadata = wiring.getRevision().getCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ if (metadata.isEmpty()) {
+ return null;
+ }
+
+ String activatorName = (String) metadata.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATOR);
+ if (activatorName == null) {
+ return null;
+ }
+ Class<?> activatorClass = loader.findClass(activatorName);
+ return (BundleActivator) activatorClass.newInstance();
+ }
+
/**
* Calls the start method of a BundleActivator.
* @param bundleActivator that activator to start
*/
- protected void startActivator(final BundleActivator bundleActivator) throws BundleException {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logEnter("BundleContextImpl.startActivator()", null); //$NON-NLS-1$
+ private void startActivator(final BundleActivator bundleActivator) throws BundleException {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
if (bundleActivator != null) {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("BundleContextImpl.startActivator()", "calling " + bundle.getLocation() + " bundle activator"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
// make sure the context class loader is set correctly
Object previousTCCL = setContextFinder();
/* Start the bundle synchronously */
@@ -713,8 +765,6 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
if (previousTCCL != Boolean.FALSE)
Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
}
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("BundleContextImpl.startActivator()", "returned from " + bundle.getLocation() + " bundle activator"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
return null;
}
@@ -724,7 +774,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
t = ((PrivilegedActionException) t).getException();
}
- if (Debug.DEBUG_GENERAL) {
+ if (debug.DEBUG_GENERAL) {
Debug.printStackTrace(t);
}
@@ -732,20 +782,17 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
clazz = bundleActivator.getClass().getName();
throw new BundleException(NLS.bind(Msg.BUNDLE_ACTIVATOR_EXCEPTION, new Object[] {clazz, "start", bundle.getSymbolicName() == null ? "" + bundle.getBundleId() : bundle.getSymbolicName()}), BundleException.ACTIVATOR_ERROR, t); //$NON-NLS-1$ //$NON-NLS-2$
- } finally {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logExit("BundleContextImpl.startActivator()"); //$NON-NLS-1$
}
}
Object setContextFinder() {
- if (!SET_TCCL)
+ if (container.getConfiguration().BUNDLE_SET_TCCL)
return Boolean.FALSE;
Thread currentThread = Thread.currentThread();
ClassLoader previousTCCL = currentThread.getContextClassLoader();
- ClassLoader contextFinder = framework.getContextFinder();
+ ClassLoader contextFinder = container.getContextFinder();
if (previousTCCL != contextFinder) {
- currentThread.setContextClassLoader(framework.getContextFinder());
+ currentThread.setContextClassLoader(container.getContextFinder());
return previousTCCL;
}
return Boolean.FALSE;
@@ -782,7 +829,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
t = ((PrivilegedActionException) t).getException();
}
- if (Debug.DEBUG_GENERAL) {
+ if (debug.DEBUG_GENERAL) {
Debug.printStackTrace(t);
}
@@ -817,36 +864,21 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
public void dispatchEvent(Object originalListener, Object l, int action, Object object) {
// save the bundle ref to a local variable
// to avoid interference from another thread closing this context
- AbstractBundle tmpBundle = bundle;
+ EquinoxBundle tmpBundle = bundle;
Object previousTCCL = setContextFinder();
try {
if (isValid()) /* if context still valid */{
switch (action) {
- case Framework.BUNDLEEVENT :
- case Framework.BUNDLEEVENTSYNC : {
+ case EquinoxEventPublisher.BUNDLEEVENT :
+ case EquinoxEventPublisher.BUNDLEEVENTSYNC : {
BundleListener listener = (BundleListener) l;
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchBundleEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- BundleEvent event = (BundleEvent) object;
- switch (event.getType()) {
- case Framework.BATCHEVENT_BEGIN : {
- if (listener instanceof BatchBundleListener)
- ((BatchBundleListener) listener).batchBegin();
- break;
- }
- case Framework.BATCHEVENT_END : {
- if (listener instanceof BatchBundleListener)
- ((BatchBundleListener) listener).batchEnd();
- break;
- }
- default : {
- listener.bundleChanged((BundleEvent) object);
- }
- }
+ listener.bundleChanged((BundleEvent) object);
break;
}
@@ -854,19 +886,18 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
ServiceEvent event = (ServiceEvent) object;
ServiceListener listener = (ServiceListener) l;
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchServiceEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
listener.serviceChanged(event);
-
break;
}
- case Framework.FRAMEWORKEVENT : {
+ case EquinoxEventPublisher.FRAMEWORKEVENT : {
FrameworkListener listener = (FrameworkListener) l;
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchFrameworkEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -880,21 +911,21 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
}
}
} catch (Throwable t) {
- if (Debug.DEBUG_GENERAL) {
+ if (debug.DEBUG_GENERAL) {
Debug.println("Exception in bottom level event dispatcher: " + t.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(t);
}
// allow the adaptor to handle this unexpected error
- framework.adaptor.handleRuntimeError(t);
+ container.handleRuntimeError(t);
publisherror: {
- if (action == Framework.FRAMEWORKEVENT) {
+ if (action == EquinoxEventPublisher.FRAMEWORKEVENT) {
FrameworkEvent event = (FrameworkEvent) object;
if (event.getType() == FrameworkEvent.ERROR) {
break publisherror; // avoid infinite loop
}
}
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, tmpBundle, t);
+ container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, tmpBundle, t);
}
} finally {
if (previousTCCL != Boolean.FALSE)
@@ -916,7 +947,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
public Filter createFilter(String filter) throws InvalidSyntaxException {
checkValid();
- return FilterImpl.newInstance(filter);
+ return FilterImpl.newInstance(filter, container.getConfiguration().getDebug().DEBUG_FILTER);
}
/**
@@ -941,10 +972,6 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
return valid;
}
- public Framework getFramework() {
- return framework;
- }
-
public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties) {
@SuppressWarnings("unchecked")
ServiceRegistration<S> registration = (ServiceRegistration<S>) registerService(clazz.getName(), service, properties);
@@ -971,4 +998,8 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object,
}
return result;
}
+
+ public EquinoxContainer getContainer() {
+ return container;
+ }
}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ContextFinder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java
index 9ecc15b45..f54936c3a 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ContextFinder.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,14 +8,14 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.framework;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
public class ContextFinder extends ClassLoader implements PrivilegedAction<List<ClassLoader>> {
static final class Finder extends SecurityManager {
@@ -66,7 +66,7 @@ public class ContextFinder extends ClassLoader implements PrivilegedAction<List<
}
}
// stop at the framework classloader or the first bundle classloader
- if (tmp == finderClassLoader || tmp instanceof BundleClassLoader)
+ if (tmp == finderClassLoader || tmp instanceof ModuleClassLoader)
break;
}
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
new file mode 100644
index 000000000..bc8ee2abd
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
@@ -0,0 +1,746 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework;
+
+import java.io.*;
+import java.net.URL;
+import java.security.*;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.*;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.Module.Settings;
+import org.eclipse.osgi.container.Module.StartOptions;
+import org.eclipse.osgi.container.Module.State;
+import org.eclipse.osgi.container.Module.StopOptions;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
+import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
+import org.eclipse.osgi.signedcontent.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.Storage;
+import org.osgi.framework.*;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.wiring.*;
+import org.osgi.service.resolver.ResolutionException;
+
+public class EquinoxBundle implements Bundle, BundleReference {
+
+ static class SystemBundle extends EquinoxBundle implements Framework {
+
+ SystemBundle(ModuleContainer moduleContainer, EquinoxContainer equinoxContainer) {
+ super(moduleContainer, equinoxContainer);
+ }
+
+ @Override
+ public void init() throws BundleException {
+ ((SystemModule) getModule()).init();
+ }
+
+ @Override
+ public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
+ ContainerEvent event = ((SystemModule) getModule()).waitForStop(timeout);
+ return new FrameworkEvent(EquinoxContainerAdaptor.getType(event), this, null);
+ }
+
+ @Override
+ Module createSystemModule(ModuleContainer moduleContainer) {
+ return new EquinoxSystemModule(moduleContainer);
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ public void stop(final int options) throws BundleException {
+ getEquinoxContainer().checkAdminPermission(this, AdminPermission.EXECUTE);
+ ((EquinoxSystemModule) getModule()).asyncStop();
+ }
+
+ @Override
+ public void stop() throws BundleException {
+ stop(0);
+ }
+
+ @Override
+ public void update(InputStream input) throws BundleException {
+ getEquinoxContainer().checkAdminPermission(this, AdminPermission.LIFECYCLE);
+ try {
+ if (input != null)
+ input.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ ((EquinoxSystemModule) getModule()).asyncUpdate();
+ }
+
+ @Override
+ public void update() throws BundleException {
+ update(null);
+ }
+
+ @Override
+ public void uninstall() throws BundleException {
+ getEquinoxContainer().checkAdminPermission(this, AdminPermission.LIFECYCLE);
+ throw new BundleException(Msg.BUNDLE_SYSTEMBUNDLE_UNINSTALL_EXCEPTION, BundleException.INVALID_OPERATION);
+ }
+
+ }
+
+ private final EquinoxContainer equinoxContainer;
+ private final Module module;
+ private final Object monitor = new Object();
+ private BundleContextImpl context;
+
+ class EquinoxSystemModule extends SystemModule {
+ public EquinoxSystemModule(ModuleContainer container) {
+ super(container);
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return EquinoxBundle.this;
+ }
+
+ @Override
+ protected void cleanup(ModuleRevision revision) {
+ // Nothing to do
+ }
+
+ @Override
+ protected void initWorker() throws BundleException {
+ equinoxContainer.getConfiguration().setConfiguration(Constants.FRAMEWORK_UUID, new UniversalUniqueIdentifier().toString());
+ equinoxContainer.init();
+ startWorker0();
+ }
+
+ @Override
+ protected void stopWorker() throws BundleException {
+ super.stopWorker();
+ stopWorker0();
+ equinoxContainer.close();
+ }
+
+ void asyncStop() throws BundleException {
+ lockStateChange(ModuleEvent.STOPPED);
+ try {
+ if (Module.ACTIVE_SET.contains(getState())) {
+ // TODO this still has a chance of a race condition:
+ // multiple threads could get started if stop is called over and over
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ stop();
+ } catch (BundleException e) {
+ // TODO not sure we can even log if this fails
+ e.printStackTrace();
+ }
+ }
+ }, "Framework stop"); //$NON-NLS-1$
+ t.start();
+ }
+ } finally {
+ unlockStateChange(ModuleEvent.STOPPED);
+ }
+ }
+
+ void asyncUpdate() throws BundleException {
+ lockStateChange(ModuleEvent.UPDATED);
+ try {
+ if (Module.ACTIVE_SET.contains(getState())) {
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ update();
+ } catch (BundleException e) {
+ e.printStackTrace();
+ // TODO not sure we can even log if this fails
+ }
+ }
+ }, "Framework update"); //$NON-NLS-1$
+ t.start();
+ }
+ } finally {
+ unlockStateChange(ModuleEvent.UPDATED);
+ }
+ }
+ }
+
+ private class EquinoxModule extends Module {
+
+ @Override
+ protected void startWorker() throws BundleException {
+ startWorker0();
+ }
+
+ @Override
+ protected void stopWorker() throws BundleException {
+ stopWorker0();
+ }
+
+ public EquinoxModule(Long id, String location, ModuleContainer container, EnumSet<Settings> settings, int startlevel) {
+ super(id, location, container, settings, startlevel);
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return EquinoxBundle.this;
+ }
+
+ @Override
+ protected void cleanup(ModuleRevision revision) {
+ Generation generation = (Generation) revision.getRevisionInfo();
+ generation.delete();
+ if (revision.equals(getCurrentRevision())) {
+ // uninstall case
+ generation.getBundleInfo().delete();
+ }
+ }
+ }
+
+ EquinoxBundle(ModuleContainer moduleContainer, EquinoxContainer equinoxContainer) {
+ this.equinoxContainer = equinoxContainer;
+ this.module = createSystemModule(moduleContainer);
+ }
+
+ public EquinoxBundle(Long id, String location, ModuleContainer moduleContainer, EnumSet<Settings> settings, int startlevel, EquinoxContainer equinoxContainer) {
+ this.equinoxContainer = equinoxContainer;
+ this.module = new EquinoxModule(id, location, moduleContainer, settings, startlevel);
+ }
+
+ Module createSystemModule(ModuleContainer moduleContainer) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int compareTo(Bundle bundle) {
+ long idcomp = getBundleId() - bundle.getBundleId();
+ return (idcomp < 0L) ? -1 : ((idcomp > 0L) ? 1 : 0);
+ }
+
+ @Override
+ public int getState() {
+ switch (module.getState()) {
+ case INSTALLED :
+ return Bundle.INSTALLED;
+ case RESOLVED :
+ return Bundle.RESOLVED;
+ case STARTING :
+ case LAZY_STARTING :
+ return Bundle.STARTING;
+ case ACTIVE :
+ return Bundle.ACTIVE;
+ case STOPPING :
+ return Bundle.STOPPING;
+ case UNINSTALLED :
+ return Bundle.UNINSTALLED;
+ default :
+ throw new IllegalStateException("No valid bundle state for module state: " + module.getState()); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public void start(int options) throws BundleException {
+ module.start(getStartOptions(options));
+ }
+
+ private static StartOptions[] getStartOptions(int options) {
+ if (options == 0) {
+ return new StartOptions[0];
+ }
+ Collection<StartOptions> result = new ArrayList<Module.StartOptions>(2);
+ if ((options & Bundle.START_TRANSIENT) != 0) {
+ result.add(StartOptions.TRANSIENT);
+ }
+ if ((options & Bundle.START_ACTIVATION_POLICY) != 0) {
+ result.add(StartOptions.USE_ACTIVATION_POLICY);
+ }
+ return result.toArray(new StartOptions[result.size()]);
+ }
+
+ @Override
+ public void start() throws BundleException {
+ module.start();
+ }
+
+ @Override
+ public void stop(int options) throws BundleException {
+ module.stop(getStopOptions(options));
+ }
+
+ private StopOptions[] getStopOptions(int options) {
+ if ((options & Bundle.STOP_TRANSIENT) == 0) {
+ return new StopOptions[0];
+ }
+ return new StopOptions[] {StopOptions.TRANSIENT};
+ }
+
+ @Override
+ public void stop() throws BundleException {
+ module.stop();
+ }
+
+ @Override
+ public void update(InputStream input) throws BundleException {
+ try {
+ Storage storage = equinoxContainer.getStorage();
+ storage.update(module, storage.getContentConnection(module, null, input));
+ } catch (IOException e) {
+ throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public void update() throws BundleException {
+ update(null);
+ }
+
+ @Override
+ public void uninstall() throws BundleException {
+ Storage storage = equinoxContainer.getStorage();
+ storage.getModuleContainer().uninstall(module);
+ }
+
+ @Override
+ public Dictionary<String, String> getHeaders() {
+ return getHeaders(null);
+ }
+
+ @Override
+ public Dictionary<String, String> getHeaders(String locale) {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.METADATA);
+ Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
+ return current.getHeaders(locale);
+ }
+
+ @Override
+ public long getBundleId() {
+ return module.getId();
+ }
+
+ @Override
+ public String getLocation() {
+ equinoxContainer.checkAdminPermission(getBundle(), AdminPermission.METADATA);
+ return module.getLocation();
+ }
+
+ @Override
+ public ServiceReference<?>[] getRegisteredServices() {
+ checkValid();
+ BundleContextImpl current = getBundleContextImpl();
+ return current == null ? null : equinoxContainer.getServiceRegistry().getRegisteredServices(current);
+ }
+
+ @Override
+ public ServiceReference<?>[] getServicesInUse() {
+ checkValid();
+ BundleContextImpl current = getBundleContextImpl();
+ return current == null ? null : equinoxContainer.getServiceRegistry().getServicesInUse(current);
+ }
+
+ @Override
+ public boolean hasPermission(Object permission) {
+ Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
+ ProtectionDomain domain = current.getDomain();
+ if (domain != null) {
+ if (permission instanceof Permission) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm instanceof EquinoxSecurityManager) {
+ /*
+ * If the FrameworkSecurityManager is active, we need to do checks the "right" way.
+ * We can exploit our knowledge that the security context of FrameworkSecurityManager
+ * is an AccessControlContext to invoke it properly with the ProtectionDomain.
+ */
+ AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] {domain});
+ try {
+ sm.checkPermission((Permission) permission, acc);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ return domain.implies((Permission) permission);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public URL getResource(String name) {
+ try {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
+ } catch (SecurityException e) {
+ return null;
+ }
+ checkValid();
+ if (isFragment()) {
+ return null;
+ }
+
+ try {
+ ModuleClassLoader classLoader = getModuleClassLoader();
+ if (classLoader != null) {
+ return classLoader.getResource(name);
+ }
+ } catch (ResolutionException e) {
+ // ignore
+ }
+
+ return new ClasspathManager((Generation) module.getCurrentRevision().getRevisionInfo(), null).findLocalResource(name);
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return module.getCurrentRevision().getSymbolicName();
+ }
+
+ @Override
+ public Version getVersion() {
+ return module.getCurrentRevision().getVersion();
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ try {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.CLASS);
+ } catch (SecurityException e) {
+ throw new ClassNotFoundException(name, e);
+ }
+ checkValid();
+ try {
+ ModuleClassLoader classLoader = getModuleClassLoader();
+ if (classLoader != null) {
+ return classLoader.loadClass(name);
+ }
+ } catch (ResolutionException e) {
+ throw new ClassNotFoundException(name, e);
+ }
+ throw new ClassNotFoundException("No class loader available for the bundle. The bundle is likely a fragment."); //$NON-NLS-1$
+ }
+
+ private ModuleClassLoader getModuleClassLoader() throws ResolutionException {
+ resolve();
+ return AccessController.doPrivileged(new PrivilegedAction<ModuleClassLoader>() {
+ @Override
+ public ModuleClassLoader run() {
+ ModuleWiring wiring = getModule().getCurrentRevision().getWiring();
+ if (wiring != null) {
+ ModuleLoader moduleLoader = wiring.getModuleLoader();
+ if (moduleLoader instanceof BundleLoader) {
+ return ((BundleLoader) moduleLoader).getModuleClassLoader();
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ try {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
+ } catch (SecurityException e) {
+ return null;
+ }
+ checkValid();
+ if (isFragment()) {
+ return null;
+ }
+
+ try {
+ ModuleClassLoader classLoader = getModuleClassLoader();
+ if (classLoader != null) {
+ Enumeration<URL> result = classLoader.getResources(name);
+ return result.hasMoreElements() ? result : null;
+ }
+ } catch (ResolutionException e) {
+ // ignore
+ }
+
+ return new ClasspathManager((Generation) module.getCurrentRevision().getRevisionInfo(), null).findLocalResources(name);
+ }
+
+ @Override
+ public Enumeration<String> getEntryPaths(String path) {
+ try {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
+ } catch (SecurityException e) {
+ return null;
+ }
+ checkValid();
+ Generation current = (Generation) getModule().getCurrentRevision().getRevisionInfo();
+ return current.getBundleFile().getEntryPaths(path);
+ }
+
+ @Override
+ public URL getEntry(String path) {
+ try {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
+ } catch (SecurityException e) {
+ return null;
+ }
+ checkValid();
+ Generation current = (Generation) getModule().getCurrentRevision().getRevisionInfo();
+ return current.getEntry(path);
+ }
+
+ @Override
+ public long getLastModified() {
+ return module.getLastModified();
+ }
+
+ @Override
+ public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
+ try {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
+ } catch (SecurityException e) {
+ return null;
+ }
+ checkValid();
+ try {
+ resolve();
+ } catch (ResolutionException e) {
+ // ignore
+ }
+ return Storage.findEntries(getGenerations(), path, filePattern, recurse ? BundleWiring.FINDENTRIES_RECURSE : 0);
+ }
+
+ @Override
+ public BundleContext getBundleContext() {
+ equinoxContainer.checkAdminPermission(this, AdminPermission.CONTEXT);
+ return createBundleContext(true);
+ }
+
+ BundleContextImpl createBundleContext(boolean checkPermission) {
+ if (isFragment()) {
+ // fragments cannot have contexts
+ return null;
+ }
+ synchronized (this.monitor) {
+ if (context == null) {
+ // only create the context if we are starting, active or stopping
+ // this is so that SCR can get the context for lazy-start bundles
+ if (Module.ACTIVE_SET.contains(module.getState())) {
+ context = new BundleContextImpl(this, equinoxContainer);
+ }
+ }
+ return context;
+ }
+ }
+
+ private BundleContextImpl getBundleContextImpl() {
+ synchronized (this.monitor) {
+ return context;
+ }
+ }
+
+ @Override
+ public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
+ SignedContentFactory factory = equinoxContainer.getSignedContentFactory();
+ if (factory == null) {
+ return Collections.emptyMap();
+ }
+ try {
+ SignedContent signedContent = factory.getSignedContent(this);
+ SignerInfo[] infos = signedContent.getSignerInfos();
+ if (infos.length == 0)
+ return Collections.emptyMap();
+ Map<X509Certificate, List<X509Certificate>> results = new HashMap<X509Certificate, List<X509Certificate>>(infos.length);
+ for (int i = 0; i < infos.length; i++) {
+ if (signersType == SIGNERS_TRUSTED && !infos[i].isTrusted())
+ continue;
+ Certificate[] certs = infos[i].getCertificateChain();
+ if (certs == null || certs.length == 0)
+ continue;
+ List<X509Certificate> certChain = new ArrayList<X509Certificate>();
+ for (int j = 0; j < certs.length; j++)
+ certChain.add((X509Certificate) certs[j]);
+ results.put((X509Certificate) certs[0], certChain);
+ }
+ return results;
+ } catch (Exception e) {
+ return Collections.emptyMap();
+ }
+ }
+
+ @Override
+ public final <A> A adapt(Class<A> adapterType) {
+ checkAdaptPermission(adapterType);
+ return adapt0(adapterType);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <A> A adapt0(Class<A> adapterType) {
+ if (adapterType.isInstance(this))
+ return (A) this;
+
+ if (AccessControlContext.class.equals(adapterType)) {
+ Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
+ ProtectionDomain domain = current.getDomain();
+ return (A) (domain == null ? null : new AccessControlContext(new ProtectionDomain[] {domain}));
+ }
+
+ if (BundleContext.class.equals(adapterType)) {
+ try {
+ return (A) getBundleContext();
+ } catch (SecurityException e) {
+ return null;
+ }
+ }
+
+ if (BundleRevision.class.equals(adapterType)) {
+ if (module.getState().equals(State.UNINSTALLED)) {
+ return null;
+ }
+ return (A) module.getCurrentRevision();
+ }
+
+ if (BundleRevisions.class.equals(adapterType)) {
+ return (A) module.getRevisions();
+ }
+
+ if (BundleStartLevel.class.equals(adapterType)) {
+ return (A) module;
+ }
+
+ if (BundleWiring.class.equals(adapterType)) {
+ if (module.getState().equals(State.UNINSTALLED)) {
+ return null;
+ }
+ ModuleRevision revision = module.getCurrentRevision();
+ if (revision == null) {
+ return null;
+ }
+ return (A) revision.getWiring();
+ }
+
+ if (getBundleId() == 0) {
+ if (Framework.class.equals(adapterType)) {
+ // TODO
+ }
+
+ if (FrameworkStartLevel.class.equals(adapterType)) {
+ return (A) equinoxContainer.getStorage().getModuleContainer().getFrameworkStartLevel();
+ }
+
+ if (FrameworkWiring.class.equals(adapterType)) {
+ return (A) equinoxContainer.getStorage().getModuleContainer().getFrameworkWiring();
+ }
+ }
+
+ // Equinox extras
+ if (Module.class.equals(adapterType)) {
+ return (A) module;
+ }
+ return null;
+ }
+
+ /**
+ * Check for permission to get a service.
+ */
+ private <A> void checkAdaptPermission(Class<A> adapterType) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ return;
+ }
+ sm.checkPermission(new AdaptPermission(adapterType.getName(), this, AdaptPermission.ADAPT));
+ }
+
+ @Override
+ public File getDataFile(String filename) {
+ checkValid();
+ Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
+ return current.getBundleInfo().getDataFile(filename);
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return this;
+ }
+
+ public Module getModule() {
+ return module;
+ }
+
+ private final void checkValid() {
+ if (module.getState().equals(State.UNINSTALLED))
+ throw new IllegalStateException("Module has been uninstalled."); //$NON-NLS-1$
+ }
+
+ public boolean isFragment() {
+ return (getModule().getCurrentRevision().getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
+ }
+
+ void startWorker0() throws BundleException {
+ BundleContextImpl current = createBundleContext(false);
+ if (current == null) {
+ throw new BundleException("Unable to create bundle context!"); //$NON-NLS-1$
+ }
+ try {
+ current.start();
+ } catch (BundleException e) {
+ current.close();
+ synchronized (EquinoxBundle.this.monitor) {
+ context = null;
+ }
+ throw e;
+ }
+ }
+
+ void stopWorker0() throws BundleException {
+ BundleContextImpl current = getBundleContextImpl();
+ if (current != null) {
+ try {
+ current.stop();
+ } finally {
+ current.close();
+ }
+ synchronized (EquinoxBundle.this.monitor) {
+ context = null;
+ }
+ }
+ }
+
+ void resolve() throws ResolutionException {
+ if (!Module.RESOLVED_SET.contains(module.getState())) {
+ module.getContainer().resolve(Arrays.asList(module), true);
+ }
+ }
+
+ List<Generation> getGenerations() {
+ List<Generation> result = new ArrayList<Generation>();
+ ModuleRevision current = getModule().getCurrentRevision();
+ result.add((Generation) current.getRevisionInfo());
+ ModuleWiring wiring = current.getWiring();
+ if (wiring != null) {
+ for (ModuleWire hostWire : wiring.getProvidedModuleWires(HostNamespace.HOST_NAMESPACE)) {
+ result.add((Generation) hostWire.getRequirer().getRevisionInfo());
+ }
+ }
+ return result;
+ }
+
+ EquinoxContainer getEquinoxContainer() {
+ return equinoxContainer;
+ }
+
+ public String toString() {
+ return getModule().getCurrentRevision().toString();
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
new file mode 100644
index 000000000..e4c3ad11f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
@@ -0,0 +1,800 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.net.*;
+import java.security.CodeSource;
+import java.util.*;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.debug.FrameworkDebugOptions;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.internal.location.EclipseAdaptorMsg;
+import org.eclipse.osgi.internal.location.EquinoxLocations;
+import org.eclipse.osgi.service.debug.DebugOptions;
+import org.eclipse.osgi.service.environment.Constants;
+import org.eclipse.osgi.service.environment.EnvironmentInfo;
+import org.eclipse.osgi.util.ManifestElement;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Version;
+
+/**
+ * Internal class.
+ */
+public class EquinoxConfiguration implements EnvironmentInfo {
+ // While we recognize the SunOS operating system, we change
+ // this internally to be Solaris.
+ private static final String INTERNAL_OS_SUNOS = "SunOS"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_LINUX = "Linux"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_MACOSX = "Mac OS"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_AIX = "AIX"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_HPUX = "HP-UX"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_QNX = "QNX"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_OS400 = "OS/400"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_OS390 = "OS/390"; //$NON-NLS-1$
+ private static final String INTERNAL_OS_ZOS = "z/OS"; //$NON-NLS-1$
+ // While we recognize the i386 architecture, we change
+ // this internally to be x86.
+ private static final String INTERNAL_ARCH_I386 = "i386"; //$NON-NLS-1$
+ // While we recognize the amd64 architecture, we change
+ // this internally to be x86_64.
+ private static final String INTERNAL_AMD64 = "amd64"; //$NON-NLS-1$
+
+ public static final String VARIABLE_DELIM_STRING = "$"; //$NON-NLS-1$
+ public static final char VARIABLE_DELIM_CHAR = '$';
+
+ private final Properties configuration;
+ private final String nl;
+ private final String os;
+ private final String ws;
+ private final String arch;
+
+ private final Debug debug;
+ private final DebugOptions debugOptions;
+ private final HookRegistry hookRegistry;
+ private final AliasMapper aliasMapper = new AliasMapper();
+
+ private volatile String[] allArgs;
+ private volatile String[] frameworkArgs;
+ private volatile String[] appArgs;
+
+ // dev mode fields
+ private final boolean inDevelopmentMode;
+ private final File devLocation;
+ private final Object devMonitor = new Object();
+ private String[] devDefaultClasspath;
+ private Dictionary<String, String> devProperties = null;
+ // timestamp for the dev.properties file
+ private long devLastModified = 0;
+
+ public final boolean contextBootDelegation;
+ public final boolean compatibiltyBootDelegation;
+
+ public final List<String> LIB_EXTENSIONS;
+ public final List<String> ECLIPSE_LIB_VARIANTS;
+ public final boolean COPY_NATIVES;
+ public final List<String> ECLIPSE_NL_JAR_VARIANTS;
+ public final boolean DEFINE_PACKAGE_ATTRIBUTES;
+ public final boolean BUNDLE_SET_TCCL;
+
+ public final int BSN_VERSION;
+ public static final int BSN_VERSION_SINGLE = 1;
+ public static final int BSN_VERSION_MULTIPLE = 2;
+ public static final int BSN_VERSION_MANAGED = 3;
+
+ public final boolean throwErrorOnFailedStart;
+
+ public final boolean CLASS_CERTIFICATE;
+ public final boolean PARALLEL_CAPABLE;
+
+ // JVM os.arch property name
+ public static final String PROP_JVM_OS_ARCH = "os.arch"; //$NON-NLS-1$
+ // JVM os.name property name
+ public static final String PROP_JVM_OS_NAME = "os.name"; //$NON-NLS-1$
+ // JVM os.version property name
+ public static final String PROP_JVM_OS_VERSION = "os.version"; //$NON-NLS-1$
+ public static final String PROP_JVM_SPEC_VERSION = "java.specification.version"; //$NON-NLS-1$
+ public static final String PROP_JVM_SPEC_NAME = "java.specification.name"; //$NON-NLS-1$
+ // J2ME configuration property name
+ public static final String PROP_J2ME_MICROEDITION_CONFIGURATION = "microedition.configuration"; //$NON-NLS-1$
+ // J2ME profile property name
+ public static final String PROP_J2ME_MICROEDITION_PROFILES = "microedition.profiles"; //$NON-NLS-1$
+
+ public static final String PROP_SETPERMS_CMD = "osgi.filepermissions.command"; //$NON-NLS-1$
+ public static final String PROP_DEBUG = "osgi.debug"; //$NON-NLS-1$
+ public static final String PROP_DEBUG_VERBOSE = "osgi.debug.verbose"; //$NON-NLS-1$
+ public static final String PROP_DEV = "osgi.dev"; //$NON-NLS-1$
+ public static final String PROP_CLEAN = "osgi.clean"; //$NON-NLS-1$
+ public static final String PROP_USE_SYSTEM_PROPERTIES = "osgi.framework.useSystemProperties"; //$NON-NLS-1$
+ public static final String PROP_FRAMEWORK = "osgi.framework"; //$NON-NLS-1$
+
+ public static final String ECLIPSE_FRAMEWORK_VENDOR = "Eclipse"; //$NON-NLS-1$
+
+ public static final String PROP_OSGI_JAVA_PROFILE = "osgi.java.profile"; //$NON-NLS-1$
+ public static final String PROP_OSGI_JAVA_PROFILE_NAME = "osgi.java.profile.name"; //$NON-NLS-1$
+ // OSGi java profile bootdelegation; used to indicate how the org.osgi.framework.bootdelegation
+ // property defined in the java profile should be processed, (ingnore, override, none). default is ignore
+ public static final String PROP_OSGI_JAVA_PROFILE_BOOTDELEGATION = "osgi.java.profile.bootdelegation"; //$NON-NLS-1$
+ // indicates that the org.osgi.framework.bootdelegation in the java profile should be ingored
+ public static final String PROP_OSGI_BOOTDELEGATION_IGNORE = "ignore"; //$NON-NLS-1$
+ // indicates that the org.osgi.framework.bootdelegation in the java profile should override the system property
+ public static final String PROP_OSGI_BOOTDELEGATION_OVERRIDE = "override"; //$NON-NLS-1$
+ // indicates that the org.osgi.framework.bootdelegation in the java profile AND the system properties should be ignored
+ public static final String PROP_OSGI_BOOTDELEGATION_NONE = "none"; //$NON-NLS-1$
+
+ public static final String PROP_CONTEXT_BOOTDELEGATION = "osgi.context.bootdelegation"; //$NON-NLS-1$
+ public static final String PROP_COMPATIBILITY_BOOTDELEGATION = "osgi.compatibility.bootdelegation"; //$NON-NLS-1$
+ public static final String PROP_COMPATIBILITY_ERROR_FAILED_START = "osgi.compatibility.errorOnFailedStart"; //$NON-NLS-1$
+
+ public static final String PROP_OSGI_OS = "osgi.os"; //$NON-NLS-1$
+ public static final String PROP_OSGI_WS = "osgi.ws"; //$NON-NLS-1$
+ public static final String PROP_OSGI_ARCH = "osgi.arch"; //$NON-NLS-1$
+ public static final String PROP_OSGI_NL = "osgi.nl"; //$NON-NLS-1$
+ public static final String PROP_OSGI_NL_USER = "osgi.nl.user"; //$NON-NLS-1$
+
+ public static final String PROP_ROOT_LOCALE = "equinox.root.locale"; //$NON-NLS-1$
+
+ public static final String PROP_PARENT_CLASSLOADER = "osgi.parentClassloader"; //$NON-NLS-1$
+ // A parent classloader type that specifies the framework classlaoder
+ public static final String PARENT_CLASSLOADER_FWK = "fwk"; //$NON-NLS-1$
+ // System property used to set the context classloader parent classloader type (ccl is the default)
+ public static final String PROP_CONTEXTCLASSLOADER_PARENT = "osgi.contextClassLoaderParent"; //$NON-NLS-1$
+ public static final String CONTEXTCLASSLOADER_PARENT_APP = "app"; //$NON-NLS-1$
+ public static final String CONTEXTCLASSLOADER_PARENT_EXT = "ext"; //$NON-NLS-1$
+ public static final String CONTEXTCLASSLOADER_PARENT_BOOT = "boot"; //$NON-NLS-1$
+ public static final String CONTEXTCLASSLOADER_PARENT_FWK = "fwk"; //$NON-NLS-1$
+
+ public static final String PROP_FRAMEWORK_LIBRARY_EXTENSIONS = "osgi.framework.library.extensions"; //$NON-NLS-1$
+ public static final String PROP_FRAMEWORK_THREAD = "osgi.framework.activeThreadType"; //$NON-NLS-1$
+ public static final String FRAMEWORK_THREAD_NORMAL = "normal"; //$NON-NLS-1$
+ public static final String PROP_COPY_NATIVES = "osgi.classloader.copy.natives"; //$NON-NLS-1$
+ public static final String PROP_DEFINE_PACKAGES = "osgi.classloader.define.packages"; //$NON-NLS-1$
+ public static final String PROP_BUNDLE_SETTCCL = "eclipse.bundle.setTCCL"; //$NON-NLS-1$
+
+ public static final String PROP_EQUINOX_SECURITY = "eclipse.security"; //$NON-NLS-1$
+ public static final String PROP_FILE_LIMIT = "osgi.bundlefile.limit"; //$NON-NLS-1$
+
+ public final static String PROP_CLASS_CERTIFICATE_SUPPORT = "osgi.support.class.certificate"; //$NON-NLS-1$
+ public final static String PROP_CLASS_LOADER_TYPE = "osgi.classloader.type"; //$NON-NLS-1$
+ public final static String CLASS_LOADER_TYPE_PARALLEL = "parallel"; //$NON-NLS-1$
+
+ public static final String PROP_FORCED_RESTART = "osgi.forcedRestart"; //$NON-NLS-1$
+
+ EquinoxConfiguration(Map<String, String> initialConfig, HookRegistry hookRegistry) {
+ this.hookRegistry = hookRegistry;
+ String useSystemPropsValue = initialConfig == null ? null : initialConfig.get(PROP_USE_SYSTEM_PROPERTIES);
+ boolean useSystemProps = useSystemPropsValue == null ? false : Boolean.parseBoolean(useSystemPropsValue);
+ this.configuration = useSystemProps ? System.getProperties() : new Properties();
+ if (useSystemProps) {
+ // system properties override initial configuration
+ for (Map.Entry<String, String> configEntry : initialConfig.entrySet()) {
+ if (!this.configuration.containsKey(configEntry.getKey())) {
+ this.configuration.put(configEntry.getKey(), configEntry.getValue());
+ }
+ }
+ } else {
+ this.configuration.putAll(initialConfig);
+ }
+ initializeProperties(this.configuration, aliasMapper);
+ /*
+ * Initializes the execution context for this run of the platform. The context
+ * includes information about the locale, operating system and window system.
+ *
+ * NOTE: The OS, WS, and ARCH values should never be null. The executable should
+ * be setting these values and therefore this code path is obsolete for Eclipse
+ * when run from the executable.
+ */
+
+ // if the user didn't set the locale with a command line argument then use the default.
+ String nlValue = configuration.getProperty(PROP_OSGI_NL);
+ if (nlValue != null) {
+ StringTokenizer tokenizer = new StringTokenizer(nlValue, "_"); //$NON-NLS-1$
+ int segments = tokenizer.countTokens();
+ try {
+ Locale userLocale = null;
+ switch (segments) {
+ case 1 :
+ // use the 2 arg constructor to maintain compatibility with 1.3.1
+ userLocale = new Locale(tokenizer.nextToken(), ""); //$NON-NLS-1$
+ break;
+ case 2 :
+ userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken());
+ break;
+ case 3 :
+ userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken(), tokenizer.nextToken());
+ break;
+ default :
+ // if the user passed us in a bogus value then log a message and use the default
+ System.err.println(NLS.bind(EclipseAdaptorMsg.error_badNL, nlValue));
+ userLocale = Locale.getDefault();
+ break;
+ }
+ Locale.setDefault(userLocale);
+ // TODO what the heck is this for?? why not just use osgi.nl
+ configuration.put(PROP_OSGI_NL_USER, nlValue);
+ } catch (NoSuchElementException e) {
+ // fall through and use the default
+ }
+ }
+ nlValue = Locale.getDefault().toString();
+ configuration.put(PROP_OSGI_NL, nlValue);
+
+ // if the user didn't set the operating system with a command line
+ // argument then use the default.
+ String osValue = configuration.getProperty(PROP_OSGI_OS);
+ if (osValue == null) {
+ osValue = guessOS(System.getProperty(PROP_JVM_OS_NAME));
+ configuration.put(PROP_OSGI_OS, osValue);
+ }
+
+ // if the user didn't set the window system with a command line
+ // argument then use the default.
+ String wsValue = configuration.getProperty(PROP_OSGI_WS);
+ if (wsValue == null) {
+ wsValue = guessWS(osValue);
+ configuration.put(PROP_OSGI_WS, wsValue);
+ }
+
+ // if the user didn't set the system architecture with a command line
+ // argument then use the default.
+ String archValue = configuration.getProperty(PROP_OSGI_ARCH);
+ if (archValue == null) {
+ String name = System.getProperty(PROP_JVM_OS_ARCH);
+ // Map i386 architecture to x86
+ if (name.equalsIgnoreCase(INTERNAL_ARCH_I386))
+ archValue = Constants.ARCH_X86;
+ // Map amd64 architecture to x86_64
+ else if (name.equalsIgnoreCase(INTERNAL_AMD64))
+ archValue = Constants.ARCH_X86_64;
+ else
+ archValue = name;
+ configuration.put(PROP_OSGI_ARCH, archValue);
+ }
+
+ nl = nlValue;
+ os = osValue;
+ ws = wsValue;
+ arch = archValue;
+
+ this.debugOptions = new FrameworkDebugOptions(this);
+ this.debug = new Debug(this.debugOptions);
+
+ String osgiDev = configuration.getProperty(PROP_DEV);
+ File f = null;
+ boolean devMode = false;
+ if (osgiDev != null) {
+ try {
+ devMode = true;
+ URL location = new URL(osgiDev);
+
+ if ("file".equals(location.getProtocol())) { //$NON-NLS-1$
+ f = new File(location.getFile());
+ devLastModified = f.lastModified();
+ }
+
+ // Check the osgi.dev property to see if dev classpath entries have been defined.
+ try {
+ loadDevProperties(location.openStream());
+ devMode = true;
+ } catch (IOException e) {
+ // TODO consider logging
+ }
+
+ } catch (MalformedURLException e) {
+ devDefaultClasspath = getArrayFromList(osgiDev);
+ }
+ }
+ inDevelopmentMode = devMode;
+ devLocation = f;
+
+ contextBootDelegation = "true".equals(configuration.getProperty(PROP_CONTEXT_BOOTDELEGATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
+ compatibiltyBootDelegation = "true".equals(configuration.getProperty(PROP_COMPATIBILITY_BOOTDELEGATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
+
+ COPY_NATIVES = Boolean.valueOf(configuration.getProperty(PROP_COPY_NATIVES)).booleanValue();
+ String[] libExtensions = ManifestElement.getArrayFromList(configuration.getProperty(EquinoxConfiguration.PROP_FRAMEWORK_LIBRARY_EXTENSIONS, configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_LIBRARY_EXTENSIONS, getOSLibraryExtDefaults())), ","); //$NON-NLS-1$
+ for (int i = 0; i < libExtensions.length; i++)
+ if (libExtensions[i].length() > 0 && libExtensions[i].charAt(0) != '.')
+ libExtensions[i] = '.' + libExtensions[i];
+ LIB_EXTENSIONS = Collections.unmodifiableList(Arrays.asList(libExtensions));
+ ECLIPSE_LIB_VARIANTS = buildEclipseLibraryVariants(ws, os, arch, nl);
+ ECLIPSE_NL_JAR_VARIANTS = buildNLJarVariants(nl);
+ DEFINE_PACKAGE_ATTRIBUTES = !"noattributes".equals(configuration.getProperty(PROP_DEFINE_PACKAGES)); //$NON-NLS-1$
+
+ String bsnVersion = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_BSNVERSION);
+ if (org.osgi.framework.Constants.FRAMEWORK_BSNVERSION_SINGLE.equals(bsnVersion)) {
+ BSN_VERSION = BSN_VERSION_SINGLE;
+ } else if (org.osgi.framework.Constants.FRAMEWORK_BSNVERSION_MULTIPLE.equals(bsnVersion)) {
+ BSN_VERSION = BSN_VERSION_MULTIPLE;
+ } else {
+ BSN_VERSION = BSN_VERSION_MANAGED;
+ }
+
+ BUNDLE_SET_TCCL = "true".equals(getConfiguration("eclipse.bundle.setTCCL", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ throwErrorOnFailedStart = "true".equals(getConfiguration(PROP_COMPATIBILITY_ERROR_FAILED_START, "true")); //$NON-NLS-1$//$NON-NLS-2$
+
+ CLASS_CERTIFICATE = Boolean.valueOf(getConfiguration(PROP_CLASS_CERTIFICATE_SUPPORT, "true")).booleanValue(); //$NON-NLS-1$
+ PARALLEL_CAPABLE = CLASS_LOADER_TYPE_PARALLEL.equals(getConfiguration(PROP_CLASS_LOADER_TYPE));
+ }
+
+ public Map<String, String> asMap() {
+ Map<String, String> result = new HashMap<String, String>();
+ synchronized (configuration) {
+ for (Object key : configuration.keySet()) {
+ if (key instanceof String) {
+ Object value = configuration.get(key);
+ if (value instanceof String) {
+ result.put((String) key, (String) value);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private static List<String> buildEclipseLibraryVariants(String ws, String os, String arch, String nl) {
+ List<String> result = new ArrayList<String>();
+ result.add("ws/" + ws + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ result.add("os/" + os + "/" + arch + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ result.add("os/" + os + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ nl = nl.replace('_', '/');
+ while (nl.length() > 0) {
+ result.add("nl/" + nl + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ int i = nl.lastIndexOf('/');
+ nl = (i < 0) ? "" : nl.substring(0, i); //$NON-NLS-1$
+ }
+ result.add(""); //$NON-NLS-1$
+ return Collections.unmodifiableList(result);
+ }
+
+ private static List<String> buildNLJarVariants(String nl) {
+ List<String> result = new ArrayList<String>();
+ nl = nl.replace('_', '/');
+ while (nl.length() > 0) {
+ result.add("nl/" + nl + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ int i = nl.lastIndexOf('/');
+ nl = (i < 0) ? "" : nl.substring(0, i); //$NON-NLS-1$
+ }
+ result.add(""); //$NON-NLS-1$
+ return result;
+ }
+
+ private static String getOSLibraryExtDefaults() {
+ // Some OSes have multiple library extensions
+ // We should provide defaults to the known ones
+ // For example Mac OS X uses dylib and jnilib (bug 380350)
+ String os = System.getProperty(EquinoxConfiguration.PROP_JVM_OS_NAME);
+ return os == null || !os.startsWith("Mac OS") ? null : "dylib,jnilib"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public boolean inDevelopmentMode() {
+ return inDevelopmentMode;
+ }
+
+ public boolean inDebugMode() {
+ return debugOptions.isDebugEnabled();
+ }
+
+ public String[] getCommandLineArgs() {
+ return allArgs;
+ }
+
+ public String[] getFrameworkArgs() {
+ return frameworkArgs;
+ }
+
+ public String[] getNonFrameworkArgs() {
+ return appArgs;
+ }
+
+ public String getOSArch() {
+ return arch;
+ }
+
+ public String getNL() {
+ return nl;
+ }
+
+ public String getOS() {
+ return os;
+ }
+
+ public String getWS() {
+ return ws;
+ }
+
+ public void setAllArgs(String[] allArgs) {
+ // do not check if this is set already to allow arguments to change when multiple applications are launched
+ this.allArgs = allArgs;
+ }
+
+ public void setAppArgs(String[] appArgs) {
+ // do not check if this is set already to allow arguments to change when multiple applications are launched
+ this.appArgs = appArgs;
+ }
+
+ public void setFrameworkArgs(String[] frameworkArgs) {
+ // do not check if this is set already to allow arguments to change when multiple applications are launched
+ this.frameworkArgs = frameworkArgs;
+ }
+
+ public static String guessWS(String osName) {
+ // setup default values for known OSes if nothing was specified
+ if (osName.equals(Constants.OS_WIN32))
+ return Constants.WS_WIN32;
+ if (osName.equals(Constants.OS_LINUX))
+ return Constants.WS_GTK;
+ if (osName.equals(Constants.OS_MACOSX))
+ return Constants.WS_COCOA;
+ if (osName.equals(Constants.OS_HPUX))
+ return Constants.WS_MOTIF;
+ if (osName.equals(Constants.OS_AIX))
+ return Constants.WS_MOTIF;
+ if (osName.equals(Constants.OS_SOLARIS))
+ return Constants.WS_GTK;
+ if (osName.equals(Constants.OS_QNX))
+ return Constants.WS_PHOTON;
+ return Constants.WS_UNKNOWN;
+ }
+
+ public static String guessOS(String osName) {
+ // check to see if the OS name is "Windows 98" or some other
+ // flavour which should be converted to win32.
+ if (osName.regionMatches(true, 0, Constants.OS_WIN32, 0, 3))
+ return Constants.OS_WIN32;
+ // EXCEPTION: All mappings of SunOS convert to Solaris
+ if (osName.equalsIgnoreCase(INTERNAL_OS_SUNOS))
+ return Constants.OS_SOLARIS;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_LINUX))
+ return Constants.OS_LINUX;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_QNX))
+ return Constants.OS_QNX;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_AIX))
+ return Constants.OS_AIX;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_HPUX))
+ return Constants.OS_HPUX;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_OS400))
+ return Constants.OS_OS400;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_OS390))
+ return Constants.OS_OS390;
+ if (osName.equalsIgnoreCase(INTERNAL_OS_ZOS))
+ return Constants.OS_ZOS;
+ // os.name on Mac OS can be either Mac OS or Mac OS X
+ if (osName.regionMatches(true, 0, INTERNAL_OS_MACOSX, 0, INTERNAL_OS_MACOSX.length()))
+ return Constants.OS_MACOSX;
+ return Constants.OS_UNKNOWN;
+ }
+
+ public String getConfiguration(String key) {
+ return configuration.getProperty(key);
+ }
+
+ public String getConfiguration(String key, String defaultValue) {
+ String result = getProperty(key);
+ return result == null ? defaultValue : result;
+ }
+
+ public String setConfiguration(String key, String value) {
+ Object result = configuration.put(key, value);
+ return result instanceof String ? (String) result : null;
+ }
+
+ public String clearConfiguration(String key) {
+ Object result = configuration.remove(key);
+ return result instanceof String ? (String) result : null;
+ }
+
+ public Debug getDebug() {
+ return this.debug;
+ }
+
+ public DebugOptions getDebugOptions() {
+ return this.debugOptions;
+ }
+
+ public HookRegistry getHookRegistry() {
+ return hookRegistry;
+ }
+
+ @Override
+ public String getProperty(String key) {
+ String result = getConfiguration(key);
+ return result == null ? System.getProperty(key) : result;
+ }
+
+ @Override
+ public String setProperty(String key, String value) {
+ return setConfiguration(key, value);
+ }
+
+ public AliasMapper getAliasMapper() {
+ return aliasMapper;
+ }
+
+ /*
+ * Updates the dev classpath if the file containing the entries have changed
+ */
+ private void updateDevProperties() {
+ if (devLocation == null)
+ return;
+ synchronized (devMonitor) {
+ if (devLocation.lastModified() == devLastModified)
+ return;
+
+ try {
+ loadDevProperties(new FileInputStream(devLocation));
+ } catch (FileNotFoundException e) {
+ return;
+ }
+ devLastModified = devLocation.lastModified();
+ }
+ }
+
+ private static String[] getDevClassPath(String id, Dictionary<String, String> properties, String[] defaultClasspath) {
+ String[] result = null;
+ if (id != null && properties != null) {
+ String entry = properties.get(id);
+ if (entry != null)
+ result = getArrayFromList(entry);
+ }
+ if (result == null)
+ result = defaultClasspath;
+ return result;
+ }
+
+ /**
+ * Returns a list of classpath elements for the specified bundle symbolic name.
+ * @param id a bundle symbolic name to get the development classpath for
+ * @param properties a Dictionary of properties to use or <code>null</code> if
+ * the default develoment classpath properties should be used
+ * @return a list of development classpath elements
+ */
+ public String[] getDevClassPath(String id, Dictionary<String, String> properties) {
+ if (properties == null) {
+ synchronized (devMonitor) {
+ updateDevProperties();
+ return getDevClassPath(id, devProperties, devDefaultClasspath);
+ }
+ }
+ return getDevClassPath(id, properties, getArrayFromList(properties.get("*"))); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns a list of classpath elements for the specified bundle symbolic name.
+ * @param id a bundle symbolic name to get the development classpath for
+ * @return a list of development classpath elements
+ */
+ public String[] getDevClassPath(String id) {
+ return getDevClassPath(id, null);
+ }
+
+ private static String[] getArrayFromList(String prop) {
+ return ManifestElement.getArrayFromList(prop, ","); //$NON-NLS-1$
+ }
+
+ /*
+ * Load the given input stream into a dictionary
+ */
+ private void loadDevProperties(InputStream input) {
+ Properties props = new Properties();
+ try {
+ props.load(input);
+ } catch (IOException e) {
+ // TODO consider logging here
+ } finally {
+ if (input != null)
+ try {
+ input.close();
+ } catch (IOException e) {
+ // tried our best
+ }
+ }
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ Dictionary<String, String> result = (Dictionary) props;
+ synchronized (devMonitor) {
+ devProperties = result;
+ if (devProperties != null)
+ devDefaultClasspath = getArrayFromList(devProperties.get("*")); //$NON-NLS-1$
+ }
+ }
+
+ private static void initializeProperties(Properties configuration, AliasMapper aliasMapper) {
+ // initialize some framework properties that must always be set
+ if (configuration.get(PROP_FRAMEWORK) == null || configuration.get(EquinoxLocations.PROP_INSTALL_AREA) == null) {
+ CodeSource cs = EquinoxConfiguration.class.getProtectionDomain().getCodeSource();
+ if (cs == null)
+ throw new IllegalArgumentException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_PROPS_NOT_SET, PROP_FRAMEWORK + ", " + EquinoxLocations.PROP_INSTALL_AREA)); //$NON-NLS-1$
+ URL url = cs.getLocation();
+ // allow props to be preset
+ if (configuration.get(PROP_FRAMEWORK) == null)
+ configuration.put(PROP_FRAMEWORK, url.toExternalForm());
+ if (configuration.get(EquinoxLocations.PROP_INSTALL_AREA) == null) {
+ String filePart = url.getFile();
+ configuration.put(EquinoxLocations.PROP_INSTALL_AREA, filePart.substring(0, filePart.lastIndexOf('/')));
+ }
+ }
+ // always decode these properties
+ configuration.put(PROP_FRAMEWORK, decode(configuration.getProperty(PROP_FRAMEWORK)));
+ configuration.put(EquinoxLocations.PROP_INSTALL_AREA, decode(configuration.getProperty(EquinoxLocations.PROP_INSTALL_AREA)));
+
+ configuration.put(org.osgi.framework.Constants.FRAMEWORK_VENDOR, ECLIPSE_FRAMEWORK_VENDOR);
+ String value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_PROCESSOR);
+ if (value == null) {
+ value = System.getProperty(PROP_JVM_OS_ARCH);
+ if (value != null) {
+ configuration.put(org.osgi.framework.Constants.FRAMEWORK_PROCESSOR, aliasMapper.aliasProcessor(value));
+ }
+ }
+ value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_OS_NAME);
+ if (value == null) {
+ value = System.getProperty(PROP_JVM_OS_NAME);
+ try {
+ String canonicalValue = (String) aliasMapper.aliasOSName(value);
+ if (canonicalValue != null) {
+ value = canonicalValue;
+ }
+ } catch (ClassCastException ex) {
+ //A vector was returned from the alias mapper.
+ //The alias mapped to more than one canonical value
+ //such as "win32" for example
+ }
+ if (value != null) {
+ configuration.put(org.osgi.framework.Constants.FRAMEWORK_OS_NAME, value);
+ }
+ }
+ value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_OS_VERSION);
+ if (value == null) {
+ value = System.getProperty(PROP_JVM_OS_VERSION);
+ if (value != null) {
+ // only use the value upto the first space
+ int space = value.indexOf(' ');
+ if (space > 0) {
+ value = value.substring(0, space);
+ }
+ // fix up cases where the os version does not make a valid Version string.
+ int major = 0, minor = 0, micro = 0;
+ String qualifier = ""; //$NON-NLS-1$
+ try {
+ StringTokenizer st = new StringTokenizer(value, ".", true); //$NON-NLS-1$
+ major = parseVersionInt(st.nextToken());
+
+ if (st.hasMoreTokens()) {
+ st.nextToken(); // consume delimiter
+ minor = parseVersionInt(st.nextToken());
+
+ if (st.hasMoreTokens()) {
+ st.nextToken(); // consume delimiter
+ micro = parseVersionInt(st.nextToken());
+
+ if (st.hasMoreTokens()) {
+ st.nextToken(); // consume delimiter
+ qualifier = st.nextToken();
+ }
+ }
+ }
+ } catch (NoSuchElementException e) {
+ // ignore, use the values parsed so far
+ }
+ try {
+ value = new Version(major, minor, micro, qualifier).toString();
+ } catch (IllegalArgumentException e) {
+ // must be an invalid qualifier; just ignore it
+ value = new Version(major, minor, micro).toString();
+ }
+ configuration.put(org.osgi.framework.Constants.FRAMEWORK_OS_VERSION, value);
+ }
+ }
+ value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_LANGUAGE);
+ if (value == null)
+ // set the value of the framework language property
+ configuration.put(org.osgi.framework.Constants.FRAMEWORK_LANGUAGE, Locale.getDefault().getLanguage());
+ // set the support properties for fragments and require-bundle (bug 173090)
+ configuration.put(org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_FRAGMENT, "true"); //$NON-NLS-1$
+ configuration.put(org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, "true"); //$NON-NLS-1$
+ configuration.put(org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_EXTENSION, "true"); //$NON-NLS-1$
+ if (org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT.equals(configuration.get(org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN))) {
+ configuration.put(PROP_CLEAN, "true"); //$NON-NLS-1$
+ }
+ }
+
+ private static int parseVersionInt(String value) {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ // try up to the first non-number char
+ StringBuffer sb = new StringBuffer(value.length());
+ char[] chars = value.toCharArray();
+ for (int i = 0; i < chars.length; i++) {
+ if (!Character.isDigit(chars[i]))
+ break;
+ sb.append(chars[i]);
+ }
+ if (sb.length() > 0)
+ return Integer.parseInt(sb.toString());
+ return 0;
+ }
+ }
+
+ public static String decode(String urlString) {
+ //first encode '+' characters, because URLDecoder incorrectly converts
+ //them to spaces on certain class library implementations.
+ if (urlString.indexOf('+') >= 0) {
+ int len = urlString.length();
+ StringBuffer buf = new StringBuffer(len);
+ for (int i = 0; i < len; i++) {
+ char c = urlString.charAt(i);
+ if (c == '+')
+ buf.append("%2B"); //$NON-NLS-1$
+ else
+ buf.append(c);
+ }
+ urlString = buf.toString();
+ }
+ try {
+ return URLDecoder.decode(urlString, "UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ // Tried but failed
+ // TODO should we throw runtime exception here?
+ return urlString;
+ }
+ }
+
+ public String substituteVars(String path) {
+ StringBuffer buf = new StringBuffer(path.length());
+ StringTokenizer st = new StringTokenizer(path, VARIABLE_DELIM_STRING, true);
+ boolean varStarted = false; // indicates we are processing a var subtitute
+ String var = null; // the current var key
+ while (st.hasMoreElements()) {
+ String tok = st.nextToken();
+ if (VARIABLE_DELIM_STRING.equals(tok)) {
+ if (!varStarted) {
+ varStarted = true; // we found the start of a var
+ var = ""; //$NON-NLS-1$
+ } else {
+ // we have found the end of a var
+ String prop = null;
+ // get the value of the var from system properties
+ if (var != null && var.length() > 0)
+ prop = getProperty(var);
+ if (prop == null) {
+ try {
+ // try using the System.getenv method if it exists (bug 126921)
+ Method getenv = System.class.getMethod("getenv", new Class[] {String.class}); //$NON-NLS-1$
+ prop = (String) getenv.invoke(null, new Object[] {var});
+ } catch (Throwable t) {
+ // do nothing;
+ // on 1.4 VMs this throws an error
+ // on J2ME this method does not exist
+ }
+ }
+ if (prop != null)
+ // found a value; use it
+ buf.append(prop);
+ else
+ // could not find a value append the var name w/o delims
+ buf.append(var == null ? "" : var); //$NON-NLS-1$
+ varStarted = false;
+ var = null;
+ }
+ } else {
+ if (!varStarted)
+ buf.append(tok); // the token is not part of a var
+ else
+ var = tok; // the token is the var key; save the key to process when we find the end token
+ }
+ }
+ if (var != null)
+ // found a case of $var at the end of the path with no trailing $; just append it as is.
+ buf.append(VARIABLE_DELIM_CHAR).append(var);
+ return buf.toString();
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java
new file mode 100644
index 000000000..5db495da0
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java
@@ -0,0 +1,340 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessController;
+import java.util.*;
+import org.eclipse.osgi.framework.eventmgr.EventManager;
+import org.eclipse.osgi.framework.eventmgr.ListenerQueue;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.framework.util.SecureAction;
+import org.eclipse.osgi.internal.framework.legacy.PackageAdminImpl;
+import org.eclipse.osgi.internal.framework.legacy.StartLevelImpl;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.internal.location.EquinoxLocations;
+import org.eclipse.osgi.internal.log.EquinoxLogServices;
+import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.signedcontent.SignedContentFactory;
+import org.eclipse.osgi.storage.Storage;
+import org.eclipse.osgi.util.ManifestElement;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.*;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+import org.osgi.util.tracker.ServiceTracker;
+
+@SuppressWarnings("deprecation")
+public class EquinoxContainer {
+ public static final String NAME = "org.eclipse.osgi"; //$NON-NLS-1$
+ private static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$
+ static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
+
+ private final EquinoxConfiguration equinoxConfig;
+ private final EquinoxLocations equinoxLocations;
+ private final EquinoxLogServices logServices;
+ private final Storage storage;
+ private final PackageAdmin packageAdmin;
+ private final StartLevel startLevel;
+ private final String[] bootDelegation;
+ private final String[] bootDelegationStems;
+ private final boolean bootDelegateAll;
+
+ private final Object monitor = new Object();
+ private EventManager eventManager;
+ private EquinoxEventPublisher eventPublisher;
+ private ServiceRegistry serviceRegistry;
+ private ContextFinder contextFinder;
+ private boolean initialized = false;
+
+ private ServiceTracker<SignedContentFactory, SignedContentFactory> signedContentFactory;
+
+ public EquinoxContainer(Map<String, String> configuration) {
+ this.equinoxConfig = new EquinoxConfiguration(configuration, new HookRegistry(this));
+ this.equinoxLocations = new EquinoxLocations(this.equinoxConfig);
+ loadConfig(equinoxConfig, equinoxLocations);
+ this.logServices = new EquinoxLogServices(this.equinoxConfig, this.equinoxLocations.getConfigurationLocation());
+ this.equinoxConfig.getHookRegistry().initialize();
+
+ try {
+ this.storage = new Storage(this);
+ } catch (IOException e) {
+ throw new RuntimeException("Error initializing storage.", e); //$NON-NLS-1$
+ } catch (BundleException e) {
+ throw new RuntimeException("Error initializing storage.", e); //$NON-NLS-1$
+ }
+ this.packageAdmin = new PackageAdminImpl(storage.getModuleContainer());
+ this.startLevel = new StartLevelImpl(storage.getModuleContainer());
+
+ // set the boot delegation according to the osgi boot delegation property
+ // TODO unfortunately this has to be done after constructing storage so the vm profile is loaded
+ // TODO ideally this should be in equinox configuration or perhaps in storage
+ String bootDelegationProp = equinoxConfig.getConfiguration(Constants.FRAMEWORK_BOOTDELEGATION);
+ String[] bootPackages = ManifestElement.getArrayFromList(bootDelegationProp, ","); //$NON-NLS-1$
+ List<String> exactMatch = new ArrayList<String>(bootPackages.length);
+ List<String> stemMatch = new ArrayList<String>(bootPackages.length);
+ boolean delegateAllValue = false;
+ for (int i = 0; i < bootPackages.length; i++) {
+ if (bootPackages[i].equals("*")) { //$NON-NLS-1$
+ delegateAllValue = true;
+ exactMatch.clear();
+ stemMatch.clear();
+ break;
+ } else if (bootPackages[i].endsWith("*")) { //$NON-NLS-1$
+ if (bootPackages[i].length() > 2 && bootPackages[i].endsWith(".*")) //$NON-NLS-1$
+ stemMatch.add(bootPackages[i].substring(0, bootPackages[i].length() - 1));
+ } else {
+ exactMatch.add(bootPackages[i]);
+ }
+ }
+ bootDelegateAll = delegateAllValue;
+ bootDelegation = exactMatch.isEmpty() ? null : exactMatch.toArray(new String[exactMatch.size()]);
+ bootDelegationStems = stemMatch.isEmpty() ? null : stemMatch.toArray(new String[stemMatch.size()]);
+ }
+
+ private static void loadConfig(EquinoxConfiguration equinoxConfig, EquinoxLocations equinoxLocations) {
+ Location configArea = equinoxLocations.getConfigurationLocation();
+ if (configArea == null)
+ return;
+
+ URL location = null;
+ try {
+ location = new URL(configArea.getURL().toExternalForm() + CONFIG_FILE);
+ } catch (MalformedURLException e) {
+ // its ok. This should never happen
+ }
+ mergeProperties(equinoxConfig, loadProperties(location, equinoxConfig));
+ }
+
+ private static void mergeProperties(EquinoxConfiguration equinoxConfig, Properties source) {
+ for (Enumeration<?> e = source.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String value = source.getProperty(key);
+ if (equinoxConfig.getConfiguration(key) == null)
+ equinoxConfig.setProperty(key, value);
+ }
+ }
+
+ private static Properties loadProperties(URL location, EquinoxConfiguration equinoxConfig) {
+ Properties result = new Properties();
+ if (location == null)
+ return result;
+ try {
+ InputStream in = location.openStream();
+ try {
+ result.load(in);
+ } finally {
+ in.close();
+ }
+ } catch (IOException e) {
+ // its ok if there is no file. We'll just use the defaults for everything
+ // TODO but it might be nice to log something with gentle wording (i.e., it is not an error)
+ }
+ return substituteVars(result, equinoxConfig);
+ }
+
+ private static Properties substituteVars(Properties result, EquinoxConfiguration equinoxConfig) {
+ if (result == null) {
+ //nothing todo.
+ return null;
+ }
+ for (Enumeration<Object> eKeys = result.keys(); eKeys.hasMoreElements();) {
+ Object key = eKeys.nextElement();
+ if (key instanceof String) {
+ String value = result.getProperty((String) key);
+ if (value != null)
+ result.put(key, equinoxConfig.substituteVars(value));
+ }
+ }
+ return result;
+ }
+
+ public Storage getStorage() {
+ return storage;
+ }
+
+ public EquinoxConfiguration getConfiguration() {
+ return equinoxConfig;
+ }
+
+ public EquinoxLocations getLocations() {
+ return equinoxLocations;
+ }
+
+ public EquinoxLogServices getLogServices() {
+ return logServices;
+ }
+
+ public PackageAdmin getPackageAdmin() {
+ return packageAdmin;
+ }
+
+ public StartLevel getStartLevel() {
+ return startLevel;
+ }
+
+ public SignedContentFactory getSignedContentFactory() {
+ ServiceTracker<SignedContentFactory, SignedContentFactory> current;
+ synchronized (this.monitor) {
+ current = signedContentFactory;
+ }
+ return current == null ? null : current.getService();
+ }
+
+ public boolean isBootDelegationPackage(String name) {
+ if (bootDelegateAll)
+ return true;
+ if (bootDelegation != null)
+ for (int i = 0; i < bootDelegation.length; i++)
+ if (name.equals(bootDelegation[i]))
+ return true;
+ if (bootDelegationStems != null)
+ for (int i = 0; i < bootDelegationStems.length; i++)
+ if (name.startsWith(bootDelegationStems[i]))
+ return true;
+ return false;
+ }
+
+ void init() {
+ synchronized (this.monitor) {
+ eventManager = new EventManager("Framework Event Dispatcher: " + toString()); //$NON-NLS-1$
+ eventPublisher = new EquinoxEventPublisher(this);
+ serviceRegistry = new ServiceRegistry(this);
+ initializeContextFinder();
+ initialized = true;
+ startActiveThread();
+ }
+ }
+
+ private void startActiveThread() {
+ if (EquinoxConfiguration.FRAMEWORK_THREAD_NORMAL.equals(equinoxConfig.getConfiguration(EquinoxConfiguration.PROP_FRAMEWORK_THREAD, EquinoxConfiguration.FRAMEWORK_THREAD_NORMAL))) {
+ Thread fwkThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (EquinoxContainer.this.monitor) {
+ while (EquinoxContainer.this.initialized)
+ try {
+ EquinoxContainer.this.monitor.wait(1000);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+ }, "Framework Active Thread"); //$NON-NLS-1$
+ fwkThread.setDaemon(false);
+ fwkThread.start();
+ }
+ }
+
+ void close() {
+ synchronized (this.monitor) {
+ eventManager.close();
+ eventManager = null;
+ eventPublisher = null;
+ serviceRegistry = null;
+ storage.close();
+ initialized = false;
+ this.monitor.notifyAll();
+ }
+ }
+
+ private void initializeContextFinder() {
+ Thread current = Thread.currentThread();
+ try {
+ ClassLoader parent = null;
+ // check property for specified parent
+ String type = equinoxConfig.getConfiguration(EquinoxConfiguration.PROP_CONTEXTCLASSLOADER_PARENT);
+ if (EquinoxConfiguration.CONTEXTCLASSLOADER_PARENT_APP.equals(type))
+ parent = ClassLoader.getSystemClassLoader();
+ else if (EquinoxConfiguration.CONTEXTCLASSLOADER_PARENT_BOOT.equals(type))
+ parent = null;
+ else if (EquinoxConfiguration.CONTEXTCLASSLOADER_PARENT_FWK.equals(type))
+ parent = EquinoxContainer.class.getClassLoader();
+ else if (EquinoxConfiguration.CONTEXTCLASSLOADER_PARENT_EXT.equals(type)) {
+ ClassLoader appCL = ClassLoader.getSystemClassLoader();
+ if (appCL != null)
+ parent = appCL.getParent();
+ } else { // default is ccl (null or any other value will use ccl)
+ parent = current.getContextClassLoader();
+ }
+ contextFinder = new ContextFinder(parent);
+ current.setContextClassLoader(contextFinder);
+ return;
+ } catch (Exception e) {
+ logServices.log(NAME, FrameworkLogEntry.INFO, NLS.bind(Msg.CANNOT_SET_CONTEXTFINDER, null), e);
+ }
+
+ }
+
+ public EquinoxEventPublisher getEventPublisher() {
+ synchronized (this.monitor) {
+ return eventPublisher;
+ }
+ }
+
+ public ServiceRegistry getServiceRegistry() {
+ synchronized (this.monitor) {
+ return serviceRegistry;
+ }
+ }
+
+ public ContextFinder getContextFinder() {
+ synchronized (this.monitor) {
+ return contextFinder;
+ }
+ }
+
+ public <K, V, E> ListenerQueue<K, V, E> newListenerQueue() {
+ synchronized (this.monitor) {
+ return new ListenerQueue<K, V, E>(eventManager);
+ }
+ }
+
+ void checkAdminPermission(Bundle bundle, String action) {
+ if (bundle == null)
+ return;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AdminPermission(bundle, action));
+ }
+
+ public void handleRuntimeError(Throwable t) {
+ // TODO need to call some hook here
+ }
+
+ void systemStart(BundleContext bc) {
+ synchronized (this.monitor) {
+ signedContentFactory = new ServiceTracker<SignedContentFactory, SignedContentFactory>(bc, SignedContentFactory.class, null);
+ }
+ signedContentFactory.open();
+ }
+
+ void systemStop(BundleContext bc) {
+ ServiceTracker<SignedContentFactory, SignedContentFactory> current;
+ synchronized (this.monitor) {
+ current = signedContentFactory;
+ }
+ if (current != null) {
+ current.close();
+ }
+ }
+
+ @Override
+ public String toString() {
+ String UUID = equinoxConfig == null ? null : equinoxConfig.getConfiguration(Constants.FRAMEWORK_UUID);
+ return "Equinox Container: " + UUID; //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java
new file mode 100644
index 000000000..db11fa3f6
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework;
+
+import java.util.*;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.Module.Settings;
+import org.eclipse.osgi.internal.loader.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.Storage;
+import org.osgi.framework.*;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.service.resolver.ResolutionException;
+
+public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
+ private final EquinoxContainer container;
+ private final Storage storage;
+ private final OSGiFrameworkHooks hooks;
+ private final Map<Long, Generation> initial;
+ // The ClassLoader parent to use when creating ModuleClassLoaders.
+ private final ClassLoader moduleClassLoaderParent;
+
+ public EquinoxContainerAdaptor(EquinoxContainer container, Storage storage, Map<Long, Generation> initial) {
+ this.container = container;
+ this.storage = storage;
+ this.hooks = new OSGiFrameworkHooks(container);
+ this.initial = initial;
+ this.moduleClassLoaderParent = getModuleClassLoaderParent(container.getConfiguration());
+ }
+
+ private static ClassLoader getModuleClassLoaderParent(EquinoxConfiguration configuration) {
+ // check property for specified parent
+ // check the osgi defined property first
+ String type = configuration.getConfiguration(Constants.FRAMEWORK_BUNDLE_PARENT);
+ if (type == null) {
+ type = configuration.getConfiguration(EquinoxConfiguration.PROP_PARENT_CLASSLOADER, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT);
+ }
+
+ if (Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK.equalsIgnoreCase(type) || EquinoxConfiguration.PARENT_CLASSLOADER_FWK.equalsIgnoreCase(type))
+ return EquinoxContainer.class.getClassLoader();
+ if (Constants.FRAMEWORK_BUNDLE_PARENT_APP.equalsIgnoreCase(type))
+ return ClassLoader.getSystemClassLoader();
+ if (Constants.FRAMEWORK_BUNDLE_PARENT_EXT.equalsIgnoreCase(type)) {
+ ClassLoader appCL = ClassLoader.getSystemClassLoader();
+ if (appCL != null)
+ return appCL.getParent();
+ }
+ return new ClassLoader(Object.class.getClassLoader()) {/* boot class loader*/};
+
+ }
+
+ @Override
+ public ModuleCollisionHook getModuleCollisionHook() {
+ return hooks.getModuleCollisionHook();
+ }
+
+ @Override
+ public ResolverHookFactory getResolverHookFactory() {
+ return hooks.getResolverHookFactory();
+ }
+
+ @Override
+ public void publishContainerEvent(ContainerEvent type, Module module, Throwable error, FrameworkListener... listeners) {
+ EquinoxEventPublisher publisher = container.getEventPublisher();
+ if (publisher != null) {
+ publisher.publishFrameworkEvent(getType(type), module.getBundle(), error, listeners);
+ }
+ }
+
+ @Override
+ public void publishModuleEvent(ModuleEvent type, Module module, Module origin) {
+ EquinoxEventPublisher publisher = container.getEventPublisher();
+ if (publisher != null) {
+ publisher.publishBundleEvent(getType(type), module.getBundle(), origin.getBundle());
+ }
+ checkFrameworkExtensions(type, module);
+ }
+
+ private void checkFrameworkExtensions(ModuleEvent type, Module module) {
+ switch (type) {
+ case INSTALLED : {
+ ModuleRevision current = module.getCurrentRevision();
+ if ((BundleRevision.TYPE_FRAGMENT & current.getTypes()) != 0) {
+ Module systemModule = storage.getModuleContainer().getModule(0);
+ List<ModuleCapability> candidates = systemModule == null ? Collections.<ModuleCapability> emptyList() : systemModule.getCurrentRevision().getModuleCapabilities(HostNamespace.HOST_NAMESPACE);
+ List<ModuleRequirement> hostReqs = current.getModuleRequirements(HostNamespace.HOST_NAMESPACE);
+ if (!hostReqs.isEmpty() && !candidates.isEmpty()) {
+ if (hostReqs.get(0).matches(candidates.get(0))) {
+ try {
+ storage.getModuleContainer().resolve(Arrays.asList(module), true);
+ } catch (ResolutionException e) {
+ publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ }
+ }
+ }
+ break;
+ }
+ case RESOLVED : {
+ ModuleRevision current = module.getCurrentRevision();
+ if ((BundleRevision.TYPE_FRAGMENT & current.getTypes()) != 0) {
+ ModuleWiring wiring = current.getWiring();
+ if (wiring != null) {
+ List<ModuleWire> hosts = wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ if (!hosts.isEmpty() && hosts.get(0).getProvider().getRevisions().getModule().getId().longValue() == 0) {
+ try {
+ storage.getExtensionInstaller().addExtensionContent(current);
+ } catch (BundleException e) {
+ publishContainerEvent(ContainerEvent.ERROR, module, e);
+ }
+ }
+ }
+ }
+ break;
+ }
+ default :
+ break;
+ }
+ }
+
+ @Override
+ public Module createModule(String location, long id, EnumSet<Settings> settings, int startlevel) {
+ EquinoxBundle bundle = new EquinoxBundle(id, location, storage.getModuleContainer(), settings, startlevel, container);
+ return bundle.getModule();
+ }
+
+ @Override
+ public SystemModule createSystemModule() {
+ return (SystemModule) new EquinoxBundle.SystemBundle(storage.getModuleContainer(), container).getModule();
+ }
+
+ @Override
+ public String getProperty(String key) {
+ return storage.getConfiguration().getProperty(key);
+ }
+
+ @Override
+ public ModuleLoader createModuleLoader(ModuleWiring wiring) {
+ if (wiring.getBundle().getBundleId() == 0) {
+ return new SystemBundleLoader(wiring, container);
+ }
+ if ((wiring.getRevision().getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ return new FragmentLoader();
+ }
+ return new BundleLoader(wiring, container, moduleClassLoaderParent);
+ }
+
+ @Override
+ public Generation getRevisionInfo(String location, long id) {
+ return initial.remove(id);
+ }
+
+ @Override
+ public void associateRevision(ModuleRevision revision, Object revisionInfo) {
+ ((Generation) revisionInfo).setRevision(revision);
+ }
+
+ @Override
+ public void invalidateWiring(ModuleWiring moduleWiring, ModuleLoader current) {
+ if (current instanceof BundleLoader) {
+ BundleLoader bundleLoader = (BundleLoader) current;
+ bundleLoader.close();
+ }
+ Generation generation = (Generation) moduleWiring.getRevision().getRevisionInfo();
+ generation.clearManifestCache();
+ }
+
+ static int getType(ContainerEvent type) {
+ switch (type) {
+ case ERROR :
+ return FrameworkEvent.ERROR;
+ case INFO :
+ return FrameworkEvent.INFO;
+ case WARNING :
+ return FrameworkEvent.WARNING;
+ case REFRESH :
+ return FrameworkEvent.PACKAGES_REFRESHED;
+ case START_LEVEL :
+ return FrameworkEvent.STARTLEVEL_CHANGED;
+ case STARTED :
+ return FrameworkEvent.STARTED;
+ case STOPPED :
+ return FrameworkEvent.STOPPED;
+ case STOPPED_REFRESH :
+ return FrameworkEvent.STOPPED_BOOTCLASSPATH_MODIFIED;
+ case STOPPED_UPDATE :
+ return FrameworkEvent.STOPPED_UPDATE;
+ case STOPPED_TIMEOUT :
+ return FrameworkEvent.WAIT_TIMEDOUT;
+ default :
+ // default to error
+ return FrameworkEvent.ERROR;
+ }
+ }
+
+ private int getType(ModuleEvent type) {
+ switch (type) {
+ case INSTALLED :
+ return BundleEvent.INSTALLED;
+ case LAZY_ACTIVATION :
+ return BundleEvent.LAZY_ACTIVATION;
+ case RESOLVED :
+ return BundleEvent.RESOLVED;
+ case STARTED :
+ return BundleEvent.STARTED;
+ case STARTING :
+ return BundleEvent.STARTING;
+ case STOPPING :
+ return BundleEvent.STOPPING;
+ case STOPPED :
+ return BundleEvent.STOPPED;
+ case UNINSTALLED :
+ return BundleEvent.UNINSTALLED;
+ case UNRESOLVED :
+ return BundleEvent.UNRESOLVED;
+ case UPDATED :
+ return BundleEvent.UPDATED;
+ default :
+ // TODO log error?
+ return 0;
+ }
+ }
+
+ @Override
+ public void refreshedSystemModule() {
+ storage.getConfiguration().setConfiguration(EquinoxConfiguration.PROP_FORCED_RESTART, "true"); //$NON-NLS-1$
+ }
+
+ @Override
+ public String toString() {
+ return container.toString();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java
new file mode 100644
index 000000000..f3f40db07
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import org.eclipse.osgi.framework.eventmgr.*;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.serviceregistry.HookContext;
+import org.eclipse.osgi.internal.serviceregistry.ShrinkableCollection;
+import org.osgi.framework.*;
+import org.osgi.framework.hooks.bundle.CollisionHook;
+import org.osgi.framework.hooks.bundle.EventHook;
+
+public class EquinoxEventPublisher {
+ static final String eventHookName = EventHook.class.getName();
+ static final String collisionHookName = CollisionHook.class.getName();
+
+ static final int BUNDLEEVENT = 1;
+ static final int BUNDLEEVENTSYNC = 2;
+ /* SERVICEEVENT(3) is now handled by ServiceRegistry */
+ static final int FRAMEWORKEVENT = 4;
+
+ private final EquinoxContainer container;
+ /*
+ * The following maps objects keep track of event listeners
+ * by BundleContext. Each element is a Map that is the set
+ * of event listeners for a particular BundleContext. The max number of
+ * elements each of the following maps will have is the number of bundles
+ * installed in the Framework.
+ */
+ // Map of BundleContexts for bundle's BundleListeners.
+ private final Map<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> allBundleListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>>();
+
+ // Map of BundleContexts for bundle's SynchronousBundleListeners.
+ private final Map<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> allSyncBundleListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>>();
+
+ // Map of BundleContexts for bundle's FrameworkListeners.
+ private final Map<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> allFrameworkListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>>();
+
+ public EquinoxEventPublisher(EquinoxContainer container) {
+ this.container = container;
+ }
+
+ /**
+ * Deliver a BundleEvent to SynchronousBundleListeners (synchronous) and
+ * BundleListeners (asynchronous).
+ *
+ * @param type
+ * BundleEvent type.
+ * @param bundle
+ * Affected bundle or null.
+ * @param origin
+ * The origin of the event
+ */
+ public void publishBundleEvent(int type, Bundle bundle, Bundle origin) {
+ if (origin != null) {
+ publishBundleEvent(new BundleEvent(type, bundle, origin));
+ } else {
+ publishBundleEvent(new BundleEvent(type, bundle));
+ }
+ }
+
+ private void publishBundleEvent(final BundleEvent event) {
+ if (System.getSecurityManager() == null) {
+ publishBundleEventPrivileged(event);
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ publishBundleEventPrivileged(event);
+ return null;
+ }
+ });
+ }
+ }
+
+ void publishBundleEventPrivileged(BundleEvent event) {
+ /*
+ * We must collect the snapshots of the sync and async listeners
+ * BEFORE we dispatch the event.
+ */
+ /* Collect snapshot of SynchronousBundleListeners */
+ /* Build the listener snapshot */
+ Map<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>> listenersSync;
+ synchronized (allSyncBundleListeners) {
+ listenersSync = new HashMap<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>>(allSyncBundleListeners.size());
+ for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> entry : allSyncBundleListeners.entrySet()) {
+ CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = entry.getValue();
+ if (!listeners.isEmpty()) {
+ listenersSync.put(entry.getKey(), listeners.entrySet());
+ }
+ }
+ }
+ /* Collect snapshot of BundleListeners; only if the event is NOT STARTING or STOPPING or LAZY_ACTIVATION */
+ Map<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>> listenersAsync = null;
+ if ((event.getType() & (BundleEvent.STARTING | BundleEvent.STOPPING | BundleEvent.LAZY_ACTIVATION)) == 0) {
+ synchronized (allBundleListeners) {
+ listenersAsync = new HashMap<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>>(allBundleListeners.size());
+ for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> entry : allBundleListeners.entrySet()) {
+ CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = entry.getValue();
+ if (!listeners.isEmpty()) {
+ listenersAsync.put(entry.getKey(), listeners.entrySet());
+ }
+ }
+ }
+ }
+
+ /* shrink the snapshot.
+ * keySet returns a Collection which cannot be added to and
+ * removals from that collection will result in removals of the
+ * entry from the snapshot.
+ */
+ Collection<BundleContext> shrinkable;
+ if (listenersAsync == null) {
+ shrinkable = asBundleContexts(listenersSync.keySet());
+ } else {
+ shrinkable = new ShrinkableCollection<BundleContext>(asBundleContexts(listenersSync.keySet()), asBundleContexts(listenersAsync.keySet()));
+ }
+ notifyEventHooksPrivileged(event, shrinkable);
+
+ /* Dispatch the event to the snapshot for sync listeners */
+ if (!listenersSync.isEmpty()) {
+ ListenerQueue<SynchronousBundleListener, SynchronousBundleListener, BundleEvent> queue = container.newListenerQueue();
+ for (Map.Entry<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>> entry : listenersSync.entrySet()) {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ EventDispatcher<SynchronousBundleListener, SynchronousBundleListener, BundleEvent> dispatcher = (EventDispatcher) entry.getKey();
+ Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>> listeners = entry.getValue();
+ queue.queueListeners(listeners, dispatcher);
+ }
+ queue.dispatchEventSynchronous(BUNDLEEVENTSYNC, event);
+ }
+
+ /* Dispatch the event to the snapshot for async listeners */
+ if ((listenersAsync != null) && !listenersAsync.isEmpty()) {
+ ListenerQueue<BundleListener, BundleListener, BundleEvent> queue = container.newListenerQueue();
+ for (Map.Entry<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>> entry : listenersAsync.entrySet()) {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ EventDispatcher<BundleListener, BundleListener, BundleEvent> dispatcher = (EventDispatcher) entry.getKey();
+ Set<Map.Entry<BundleListener, BundleListener>> listeners = entry.getValue();
+ queue.queueListeners(listeners, dispatcher);
+ }
+ queue.dispatchEventAsynchronous(BUNDLEEVENT, event);
+ }
+ }
+
+ private void notifyEventHooksPrivileged(final BundleEvent event, final Collection<BundleContext> result) {
+ if (container.getConfiguration().getDebug().DEBUG_HOOKS) {
+ Debug.println("notifyBundleEventHooks(" + event.getType() + ":" + event.getBundle() + ", " + result + " )"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+
+ container.getServiceRegistry().notifyHooksPrivileged(new HookContext() {
+ public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
+ if (hook instanceof EventHook) {
+ ((EventHook) hook).event(event, result);
+ }
+ }
+
+ public String getHookClassName() {
+ return eventHookName;
+ }
+
+ public String getHookMethodName() {
+ return "event"; //$NON-NLS-1$
+ }
+ });
+ }
+
+ /**
+ * Deliver a FrameworkEvent.
+ *
+ * @param type
+ * FrameworkEvent type.
+ * @param bundle
+ * Affected bundle or null for system bundle.
+ * @param throwable
+ * Related exception or null.
+ */
+ public void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable) {
+ publishFrameworkEvent(type, bundle, throwable, (FrameworkListener[]) null);
+ }
+
+ public void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable, final FrameworkListener... listeners) {
+ if (bundle == null)
+ bundle = container.getStorage().getModuleContainer().getModule(0).getBundle();
+ final FrameworkEvent event = new FrameworkEvent(type, bundle, throwable);
+ if (System.getSecurityManager() == null) {
+ publishFrameworkEventPrivileged(event, listeners);
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ publishFrameworkEventPrivileged(event, listeners);
+ return null;
+ }
+ });
+ }
+ }
+
+ public void publishFrameworkEventPrivileged(FrameworkEvent event, FrameworkListener... callerListeners) {
+ // Build the listener snapshot
+ Map<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> listenerSnapshot;
+ synchronized (allFrameworkListeners) {
+ listenerSnapshot = new HashMap<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>>(allFrameworkListeners.size());
+ for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> entry : allFrameworkListeners.entrySet()) {
+ CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = entry.getValue();
+ if (!listeners.isEmpty()) {
+ listenerSnapshot.put(entry.getKey(), listeners.entrySet());
+ }
+ }
+ }
+ // If framework event hook were defined they would be called here
+
+ // deliver the event to the snapshot
+ ListenerQueue<FrameworkListener, FrameworkListener, FrameworkEvent> queue = container.newListenerQueue();
+
+ // add the listeners specified by the caller first
+ if (callerListeners != null && callerListeners.length > 0) {
+ Map<FrameworkListener, FrameworkListener> listeners = new HashMap<FrameworkListener, FrameworkListener>();
+ for (FrameworkListener listener : callerListeners) {
+ if (listener != null)
+ listeners.put(listener, listener);
+ }
+ // We use the system bundle context as the dispatcher
+ if (listeners.size() > 0) {
+ BundleContextImpl systemContext = (BundleContextImpl) container.getStorage().getModuleContainer().getModule(0).getBundle().getBundleContext();
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ EventDispatcher<FrameworkListener, FrameworkListener, FrameworkEvent> dispatcher = (EventDispatcher) systemContext;
+ queue.queueListeners(listeners.entrySet(), dispatcher);
+ }
+ }
+
+ for (Map.Entry<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> entry : listenerSnapshot.entrySet()) {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ EventDispatcher<FrameworkListener, FrameworkListener, FrameworkEvent> dispatcher = (EventDispatcher) entry.getKey();
+ Set<Map.Entry<FrameworkListener, FrameworkListener>> listeners = entry.getValue();
+ queue.queueListeners(listeners, dispatcher);
+ }
+
+ queue.dispatchEventAsynchronous(FRAMEWORKEVENT, event);
+ }
+
+ /**
+ * Coerce the generic type of a collection from Collection<BundleContextImpl>
+ * to Collection<BundleContext>
+ * @param c Collection to be coerced.
+ * @return c coerced to Collection<BundleContext>
+ */
+ @SuppressWarnings("unchecked")
+ public static Collection<BundleContext> asBundleContexts(Collection<? extends BundleContext> c) {
+ return (Collection<BundleContext>) c;
+ }
+
+ void addBundleListener(BundleListener listener, BundleContextImpl context) {
+ if (listener instanceof SynchronousBundleListener) {
+ container.checkAdminPermission(context.getBundle(), AdminPermission.LISTENER);
+ synchronized (allSyncBundleListeners) {
+ CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = allSyncBundleListeners.get(context);
+ if (listeners == null) {
+ listeners = new CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>();
+ allSyncBundleListeners.put(context, listeners);
+ }
+ listeners.put((SynchronousBundleListener) listener, (SynchronousBundleListener) listener);
+ }
+ } else {
+ synchronized (allBundleListeners) {
+ CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = allBundleListeners.get(context);
+ if (listeners == null) {
+ listeners = new CopyOnWriteIdentityMap<BundleListener, BundleListener>();
+ allBundleListeners.put(context, listeners);
+ }
+ listeners.put(listener, listener);
+ }
+ }
+ }
+
+ void removeBundleListener(BundleListener listener, BundleContextImpl context) {
+ if (listener instanceof SynchronousBundleListener) {
+ container.checkAdminPermission(context.getBundle(), AdminPermission.LISTENER);
+ synchronized (allSyncBundleListeners) {
+ CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = allSyncBundleListeners.get(context);
+ if (listeners != null)
+ listeners.remove(listener);
+ }
+ } else {
+ synchronized (allBundleListeners) {
+ CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = allBundleListeners.get(context);
+ if (listeners != null)
+ listeners.remove(listener);
+ }
+ }
+ }
+
+ void addFrameworkListener(FrameworkListener listener, BundleContextImpl context) {
+ synchronized (allFrameworkListeners) {
+ CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = allFrameworkListeners.get(context);
+ if (listeners == null) {
+ listeners = new CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>();
+ allFrameworkListeners.put(context, listeners);
+ }
+ listeners.put(listener, listener);
+ }
+ }
+
+ void removeFrameworkListener(FrameworkListener listener, BundleContextImpl context) {
+ synchronized (allFrameworkListeners) {
+ CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = allFrameworkListeners.get(context);
+ if (listeners != null)
+ listeners.remove(listener);
+ }
+ }
+
+ void removeAllListeners(BundleContextImpl context) {
+ synchronized (allBundleListeners) {
+ allBundleListeners.remove(context);
+ }
+ synchronized (allSyncBundleListeners) {
+ allSyncBundleListeners.remove(context);
+ }
+ synchronized (allFrameworkListeners) {
+ allFrameworkListeners.remove(context);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java
index 4611c63cb..032391dc8 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java
@@ -9,14 +9,15 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.framework;
import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.framework.util.Headers;
+import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
@@ -139,7 +140,11 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
* an invalid filter string that cannot be parsed.
*/
public static FilterImpl newInstance(String filterString) throws InvalidSyntaxException {
- return new Parser(filterString).parse();
+ return newInstance(filterString, false);
+ }
+
+ public static FilterImpl newInstance(String filterString, boolean debug) throws InvalidSyntaxException {
+ return new Parser(filterString, debug).parse();
}
/**
@@ -233,7 +238,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
case PRESENT : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("PRESENT(" + attr + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -299,7 +304,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
case PRESENT : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("PRESENT(" + attr + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -479,14 +484,17 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private final String attr;
/** filter operands */
private final Object value;
+ /** debug mode */
+ private final boolean debug;
/* normalized filter string for topLevel Filter object */
private transient volatile String filterString;
- FilterImpl(int operation, String attr, Object value) {
+ FilterImpl(int operation, String attr, Object value, boolean debug) {
this.op = operation;
this.attr = attr;
this.value = value;
+ this.debug = debug;
}
/**
@@ -530,7 +538,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare(int operation, Object value1, Object value2) {
if (value1 == null) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("compare(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -708,7 +716,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_String(int operation, String string, Object value2) {
switch (operation) {
case SUBSTRING : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -724,7 +732,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
if (substr2 == null) /* ** */
continue; /* ignore first star */
/* *xxx */
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("indexOf(\"" + substr2 + "\"," + pos + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
int index = string.indexOf(substr2, pos);
@@ -738,7 +746,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
} else /* xxx */{
int len = substr.length();
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("regionMatches(" + pos + ",\"" + substr + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if (string.regionMatches(pos, substr, 0, len)) {
@@ -752,7 +760,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
return true;
}
/* xxx */
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("regionMatches(" + pos + "," + substr + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return string.endsWith(substr);
@@ -762,13 +770,13 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
return true;
}
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return string.equals(value2);
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -778,13 +786,13 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
return string.equalsIgnoreCase(string2);
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return string.compareTo((String) value2) >= 0;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return string.compareTo((String) value2) <= 0;
@@ -796,7 +804,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Integer(int operation, int intval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -810,25 +818,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return intval == intval2;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return intval == intval2;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return intval >= intval2;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return intval <= intval2;
@@ -840,7 +848,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Long(int operation, long longval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -854,25 +862,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return longval == longval2;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return longval == longval2;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return longval >= longval2;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return longval <= longval2;
@@ -884,7 +892,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Byte(int operation, byte byteval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -898,25 +906,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return byteval == byteval2;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return byteval == byteval2;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return byteval >= byteval2;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return byteval <= byteval2;
@@ -928,7 +936,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Short(int operation, short shortval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -942,25 +950,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return shortval == shortval2;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return shortval == shortval2;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return shortval >= shortval2;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return shortval <= shortval2;
@@ -972,7 +980,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Character(int operation, char charval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -986,25 +994,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return charval == charval2;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return (charval == charval2) || (Character.toUpperCase(charval) == Character.toUpperCase(charval2)) || (Character.toLowerCase(charval) == Character.toLowerCase(charval2));
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return charval >= charval2;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return charval <= charval2;
@@ -1016,7 +1024,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Boolean(int operation, boolean boolval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -1025,25 +1033,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
boolean boolval2 = Boolean.valueOf(((String) value2).trim()).booleanValue();
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return boolval == boolval2;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return boolval == boolval2;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return boolval == boolval2;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return boolval == boolval2;
@@ -1055,7 +1063,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Float(int operation, float floatval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -1069,25 +1077,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Float.compare(floatval, floatval2) == 0;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Float.compare(floatval, floatval2) == 0;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Float.compare(floatval, floatval2) >= 0;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Float.compare(floatval, floatval2) <= 0;
@@ -1099,7 +1107,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Double(int operation, double doubleval, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -1113,25 +1121,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Double.compare(doubleval, doubleval2) == 0;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Double.compare(doubleval, doubleval2) == 0;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Double.compare(doubleval, doubleval2) >= 0;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return Double.compare(doubleval, doubleval2) <= 0;
@@ -1191,7 +1199,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Comparable(int operation, Comparable<Object> value1, Object value2) {
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -1204,25 +1212,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
try {
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.compareTo(value2) == 0;
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.compareTo(value2) == 0;
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.compareTo(value2) >= 0;
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.compareTo(value2) <= 0;
@@ -1237,7 +1245,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
private boolean compare_Unknown(int operation, Object value1, Object value2) { //RFC 59
if (operation == SUBSTRING) {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("SUBSTRING(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return false;
@@ -1250,25 +1258,25 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
try {
switch (operation) {
case EQUAL : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("EQUAL(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.equals(value2);
}
case APPROX : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("APPROX(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.equals(value2);
}
case GREATER : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("GREATER(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.equals(value2);
}
case LESS : {
- if (Debug.DEBUG_FILTER) {
+ if (debug) {
Debug.println("LESS(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return value1.equals(value2);
@@ -1381,11 +1389,13 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
* objects rooted at the parent.
*/
private static class Parser {
+ private final boolean debug;
private final String filterstring;
private final char[] filterChars;
private int pos;
- Parser(String filterstring) {
+ Parser(String filterstring, boolean debug) {
+ this.debug = debug;
this.filterstring = filterstring;
filterChars = filterstring.toCharArray();
pos = 0;
@@ -1468,7 +1478,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
operands.add(child);
}
- return new FilterImpl(FilterImpl.AND, null, operands.toArray(new FilterImpl[operands.size()]));
+ return new FilterImpl(FilterImpl.AND, null, operands.toArray(new FilterImpl[operands.size()]), debug);
}
private FilterImpl parse_or() throws InvalidSyntaxException {
@@ -1487,7 +1497,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
operands.add(child);
}
- return new FilterImpl(FilterImpl.OR, null, operands.toArray(new FilterImpl[operands.size()]));
+ return new FilterImpl(FilterImpl.OR, null, operands.toArray(new FilterImpl[operands.size()]), debug);
}
private FilterImpl parse_not() throws InvalidSyntaxException {
@@ -1501,7 +1511,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
FilterImpl child = parse_filter();
- return new FilterImpl(FilterImpl.NOT, null, child);
+ return new FilterImpl(FilterImpl.NOT, null, child, debug);
}
private FilterImpl parse_item() throws InvalidSyntaxException {
@@ -1513,21 +1523,21 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
case '~' : {
if (filterChars[pos + 1] == '=') {
pos += 2;
- return new FilterImpl(FilterImpl.APPROX, attr, parse_value());
+ return new FilterImpl(FilterImpl.APPROX, attr, parse_value(), debug);
}
break;
}
case '>' : {
if (filterChars[pos + 1] == '=') {
pos += 2;
- return new FilterImpl(FilterImpl.GREATER, attr, parse_value());
+ return new FilterImpl(FilterImpl.GREATER, attr, parse_value(), debug);
}
break;
}
case '<' : {
if (filterChars[pos + 1] == '=') {
pos += 2;
- return new FilterImpl(FilterImpl.LESS, attr, parse_value());
+ return new FilterImpl(FilterImpl.LESS, attr, parse_value(), debug);
}
break;
}
@@ -1537,7 +1547,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
pos += 2;
skipWhiteSpace();
if (filterChars[pos] == ')') {
- return new FilterImpl(FilterImpl.PRESENT, attr, null);
+ return new FilterImpl(FilterImpl.PRESENT, attr, null, debug);
}
pos = oldpos;
}
@@ -1546,9 +1556,9 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
Object string = parse_substring();
if (string instanceof String) {
- return new FilterImpl(FilterImpl.EQUAL, attr, string);
+ return new FilterImpl(FilterImpl.EQUAL, attr, string, debug);
}
- return new FilterImpl(FilterImpl.SUBSTRING, attr, string);
+ return new FilterImpl(FilterImpl.SUBSTRING, attr, string, debug);
}
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java
new file mode 100644
index 000000000..3057cc07e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleCollisionHook;
+import org.eclipse.osgi.container.namespaces.EquinoxNativeCodeNamespace;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.internal.baseadaptor.ArrayMap;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.serviceregistry.*;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.*;
+import org.osgi.framework.hooks.bundle.CollisionHook;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.osgi.framework.wiring.*;
+
+class OSGiFrameworkHooks {
+ static final String collisionHookName = CollisionHook.class.getName();
+ private final ResolverHookFactory resolverHookFactory;
+ private final ModuleCollisionHook collisionHook;
+
+ OSGiFrameworkHooks(EquinoxContainer container) {
+ resolverHookFactory = new CoreResolverHookFactory(container);
+ collisionHook = new BundleCollisionHook(container);
+ }
+
+ public ResolverHookFactory getResolverHookFactory() {
+ return resolverHookFactory;
+ }
+
+ public ModuleCollisionHook getModuleCollisionHook() {
+ return collisionHook;
+ }
+
+ static class BundleCollisionHook implements ModuleCollisionHook {
+ final Debug debug;
+ final EquinoxContainer container;
+
+ public BundleCollisionHook(EquinoxContainer container) {
+ this.container = container;
+ this.debug = container.getConfiguration().getDebug();
+ }
+
+ @Override
+ public void filterCollisions(int operationType, Module target, Collection<Module> collisionCandidates) {
+ switch (container.getConfiguration().BSN_VERSION) {
+ case EquinoxConfiguration.BSN_VERSION_SINGLE : {
+ return;
+ }
+ case EquinoxConfiguration.BSN_VERSION_MULTIPLE : {
+ collisionCandidates.clear();
+ return;
+ }
+ case EquinoxConfiguration.BSN_VERSION_MANAGED : {
+ Bundle targetBundle = target.getBundle();
+ ArrayMap<Bundle, Module> candidateBundles = new ArrayMap<Bundle, Module>(collisionCandidates.size());
+ for (Module module : collisionCandidates) {
+ candidateBundles.put(module.getBundle(), module);
+ }
+ notifyCollisionHooks(operationType, targetBundle, candidateBundles);
+ collisionCandidates.retainAll(candidateBundles.getValues());
+ return;
+ }
+ default :
+ throw new IllegalStateException("Bad configuration: " + container.getConfiguration().BSN_VERSION);
+ }
+ }
+
+ private void notifyCollisionHooks(final int operationType, final Bundle target, Collection<Bundle> collisionCandidates) {
+ final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(collisionCandidates);
+ if (System.getSecurityManager() == null) {
+ notifyCollisionHooksPriviledged(operationType, target, shrinkable);
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ notifyCollisionHooksPriviledged(operationType, target, shrinkable);
+ return null;
+ }
+ });
+ }
+ }
+
+ void notifyCollisionHooksPriviledged(final int operationType, final Bundle target, final Collection<Bundle> collisionCandidates) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("notifyCollisionHooks(" + operationType + ", " + target + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ ServiceRegistry registry = container.getServiceRegistry();
+ if (registry != null) {
+ registry.notifyHooksPrivileged(new HookContext() {
+ public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
+ if (hook instanceof CollisionHook) {
+ ((CollisionHook) hook).filterCollisions(operationType, target, collisionCandidates);
+ }
+ }
+
+ public String getHookClassName() {
+ return collisionHookName;
+ }
+
+ public String getHookMethodName() {
+ return "filterCollisions"; //$NON-NLS-1$
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * This class encapsulates the delegation to ResolverHooks that are registered with the service
+ * registry. This way the resolver implementation only has to call out to a single hook
+ * which does all the necessary service registry lookups.
+ *
+ * This class is not thread safe and expects external synchronization.
+ *
+ */
+ static class CoreResolverHookFactory implements ResolverHookFactory {
+ // need a tuple to hold the service reference and hook object
+ // do not use a map for performance reasons; no need to hash based on a key.
+ static class HookReference {
+ public HookReference(ServiceReferenceImpl<ResolverHookFactory> reference, ResolverHook hook, BundleContextImpl context) {
+ this.reference = reference;
+ this.hook = hook;
+ this.context = context;
+ }
+
+ final ServiceReferenceImpl<ResolverHookFactory> reference;
+ final ResolverHook hook;
+ final BundleContextImpl context;
+ }
+
+ final Debug debug;
+ final EquinoxContainer container;
+
+ public CoreResolverHookFactory(EquinoxContainer container) {
+ this.container = container;
+ this.debug = container.getConfiguration().getDebug();
+ }
+
+ void handleHookException(Throwable t, Object hook, String method) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println(hook.getClass().getName() + "." + method + "() exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (t != null)
+ Debug.printStackTrace(t);
+ }
+ String message = NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, hook.getClass().getName(), method);
+ throw new RuntimeException(message, new BundleException(message, BundleException.REJECTED_BY_HOOK, t));
+ }
+
+ private ServiceReferenceImpl<ResolverHookFactory>[] getHookReferences(ServiceRegistry registry, BundleContextImpl context) {
+ try {
+ @SuppressWarnings("unchecked")
+ ServiceReferenceImpl<ResolverHookFactory>[] result = (ServiceReferenceImpl<ResolverHookFactory>[]) registry.getServiceReferences(context, ResolverHookFactory.class.getName(), null, false, false);
+ return result;
+ } catch (InvalidSyntaxException e) {
+ // cannot happen; no filter
+ return null;
+ }
+ }
+
+ public ResolverHook begin(Collection<BundleRevision> triggers) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("ResolverHook.begin"); //$NON-NLS-1$
+ }
+ ServiceRegistry registry = container.getServiceRegistry();
+ if (registry == null) {
+ return new CoreResolverHook(Collections.<HookReference> emptyList());
+ }
+ Module systemModule = container.getStorage().getModuleContainer().getModule(0);
+ BundleContextImpl context = (BundleContextImpl) EquinoxContainer.secureAction.getContext(systemModule.getBundle());
+
+ ServiceReferenceImpl<ResolverHookFactory>[] refs = getHookReferences(registry, context);
+ @SuppressWarnings("unchecked")
+ List<HookReference> hookRefs = refs == null ? Collections.EMPTY_LIST : new ArrayList<CoreResolverHookFactory.HookReference>(refs.length);
+ if (refs != null) {
+ for (ServiceReferenceImpl<ResolverHookFactory> hookRef : refs) {
+ ResolverHookFactory factory = context.getService(hookRef);
+ if (factory != null) {
+ try {
+ ResolverHook hook = factory.begin(triggers);
+ if (hook != null)
+ hookRefs.add(new HookReference(hookRef, hook, context));
+ } catch (Throwable t) {
+ // need to force an end call on the ResolverHooks we got and release them
+ try {
+ new CoreResolverHook(hookRefs).end();
+ } catch (Throwable endError) {
+ // we are already in failure mode; just continue
+ }
+ handleHookException(t, factory, "begin"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ return new CoreResolverHook(hookRefs);
+ }
+
+ class CoreResolverHook implements ResolverHook {
+ private final List<HookReference> hooks;
+
+ CoreResolverHook(List<HookReference> hooks) {
+ this.hooks = hooks;
+ }
+
+ public void filterResolvable(Collection<BundleRevision> candidates) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("ResolverHook.filterResolvable(" + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (hooks.isEmpty())
+ return;
+ candidates = new ShrinkableCollection<BundleRevision>(candidates);
+ for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
+ HookReference hookRef = iHooks.next();
+ if (hookRef.reference.getBundle() == null) {
+ handleHookException(null, hookRef.hook, "filterResolvable"); //$NON-NLS-1$
+ } else {
+ try {
+ hookRef.hook.filterResolvable(candidates);
+ } catch (Throwable t) {
+ handleHookException(t, hookRef.hook, "filterResolvable"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("ResolverHook.filterSingletonCollisions(" + singleton + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ if (hooks.isEmpty())
+ return;
+ collisionCandidates = new ShrinkableCollection<BundleCapability>(collisionCandidates);
+ for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
+ HookReference hookRef = iHooks.next();
+ if (hookRef.reference.getBundle() == null) {
+ handleHookException(null, hookRef.hook, "filterSingletonCollisions"); //$NON-NLS-1$
+ } else {
+ try {
+ hookRef.hook.filterSingletonCollisions(singleton, collisionCandidates);
+ } catch (Throwable t) {
+ handleHookException(t, hookRef.hook, "filterSingletonCollisions"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("ResolverHook.filterMatches(" + requirement + ", " + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ // always filter the native code namespace
+ filterNativeSelectionFilter(requirement, candidates);
+
+ if (hooks.isEmpty())
+ return;
+ candidates = new ShrinkableCollection<BundleCapability>(candidates);
+ for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
+ HookReference hookRef = iHooks.next();
+ if (hookRef.reference.getBundle() == null) {
+ handleHookException(null, hookRef.hook, "filterMatches"); //$NON-NLS-1$
+ } else {
+ try {
+ hookRef.hook.filterMatches(requirement, candidates);
+ } catch (Throwable t) {
+ handleHookException(t, hookRef.hook, "filterMatches"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ private void filterNativeSelectionFilter(BundleRequirement requirement, Collection<BundleCapability> candidates) {
+ if (EquinoxNativeCodeNamespace.EQUINOX_NATIVECODE_NAMESPACE.equals(requirement.getNamespace())) {
+ String filterSpec = requirement.getDirectives().get(EquinoxNativeCodeNamespace.REQUIREMENT_SELECTION_FILTER_DIRECTIVE);
+ if (filterSpec != null) {
+ try {
+ Filter f = FilterImpl.newInstance(filterSpec);
+ if (!f.matches(container.getConfiguration().asMap())) {
+ candidates.clear();
+ }
+ } catch (InvalidSyntaxException e) {
+ candidates.clear();
+ }
+ }
+ }
+ }
+
+ public void end() {
+ if (debug.DEBUG_HOOKS) {
+ Debug.println("ResolverHook.end"); //$NON-NLS-1$
+ }
+ if (hooks.isEmpty())
+ return;
+ try {
+ HookReference missingHook = null;
+ Throwable endError = null;
+ HookReference endBadHook = null;
+ for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
+ HookReference hookRef = iHooks.next();
+ // We do not remove unregistered services here because we are going to remove all of them at the end
+ if (hookRef.reference.getBundle() == null) {
+ if (missingHook == null)
+ missingHook = hookRef;
+ } else {
+ try {
+ hookRef.hook.end();
+ } catch (Throwable t) {
+ // Must continue on to the next hook.end method
+ // save the error for throwing at the end
+ if (endError == null) {
+ endError = t;
+ endBadHook = hookRef;
+ }
+ }
+ }
+ }
+ if (missingHook != null)
+ handleHookException(null, missingHook.hook, "end"); //$NON-NLS-1$
+ if (endError != null)
+ handleHookException(endError, endBadHook.hook, "end"); //$NON-NLS-1$
+ } finally {
+ for (HookReference hookRef : hooks) {
+ hookRef.context.ungetService(hookRef.reference);
+ }
+ hooks.clear();
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java
new file mode 100644
index 000000000..15b25e3ea
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.framework;
+
+import java.util.*;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParserFactory;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.debug.FrameworkDebugOptions;
+import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.internal.location.EquinoxLocations;
+import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
+import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
+import org.eclipse.osgi.internal.url.EquinoxFactoryManager;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.service.debug.DebugOptions;
+import org.eclipse.osgi.service.environment.EnvironmentInfo;
+import org.eclipse.osgi.service.localization.BundleLocalization;
+import org.eclipse.osgi.service.urlconversion.URLConverter;
+import org.eclipse.osgi.storage.BundleLocalizationImpl;
+import org.eclipse.osgi.storage.url.BundleResourceHandler;
+import org.eclipse.osgi.storage.url.BundleURLConverter;
+import org.osgi.framework.*;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.permissionadmin.PermissionAdmin;
+import org.osgi.service.resolver.Resolver;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * This class activates the System Bundle.
+ */
+
+public class SystemBundleActivator implements BundleActivator {
+ private EquinoxFactoryManager urlFactoryManager;
+ private List<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>(10);
+ private List<BundleActivator> hookActivators;
+ private SecurityManager setSecurityManagner;
+
+ @SuppressWarnings("deprecation")
+ public void start(BundleContext bc) throws Exception {
+ registrations.clear();
+ EquinoxBundle bundle = (EquinoxBundle) bc.getBundle();
+
+ bundle.getEquinoxContainer().systemStart(bc);
+
+ EquinoxConfiguration configuration = bundle.getEquinoxContainer().getConfiguration();
+ installSecurityManager(configuration);
+ bundle.getEquinoxContainer().getLogServices().start(bc);
+
+ urlFactoryManager = new EquinoxFactoryManager(bundle.getEquinoxContainer());
+ urlFactoryManager.installHandlerFactories(bc);
+
+ FrameworkDebugOptions dbgOptions = (FrameworkDebugOptions) configuration.getDebugOptions();
+ dbgOptions.start(bc);
+
+ SecurityAdmin sa = bundle.getEquinoxContainer().getStorage().getSecurityAdmin();
+ ClassLoader tccl = bundle.getEquinoxContainer().getContextFinder();
+
+ registerLocations(bc, bundle.getEquinoxContainer().getLocations());
+ register(bc, EnvironmentInfo.class, bundle.getEquinoxContainer().getConfiguration(), null);
+ register(bc, PackageAdmin.class, bundle.getEquinoxContainer().getPackageAdmin(), null);
+ register(bc, StartLevel.class, bundle.getEquinoxContainer().getStartLevel(), null);
+
+ register(bc, PermissionAdmin.class, sa, null);
+ register(bc, ConditionalPermissionAdmin.class, sa, null);
+
+ register(bc, Resolver.class, bundle.getEquinoxContainer().getStorage().getAdaptor().getResolver(), null);
+
+ register(bc, DebugOptions.class, dbgOptions, null);
+
+ Hashtable<String, Object> props = new Hashtable<String, Object>(7);
+ if (tccl != null) {
+ props.clear();
+ props.put("equinox.classloader.type", "contextClassLoader"); //$NON-NLS-1$ //$NON-NLS-2$
+ register(bc, ClassLoader.class, tccl, props);
+ }
+
+ props.clear();
+ props.put("protocol", new String[] {BundleResourceHandler.OSGI_ENTRY_URL_PROTOCOL, BundleResourceHandler.OSGI_RESOURCE_URL_PROTOCOL}); //$NON-NLS-1$
+ register(bc, URLConverter.class, new BundleURLConverter(), props);
+
+ register(bc, BundleLocalization.class, new BundleLocalizationImpl(), null);
+
+ boolean setTccl = "true".equals(bundle.getEquinoxContainer().getConfiguration().getConfiguration("eclipse.parsers.setTCCL", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ register(bc, SAXParserFactory.class, new ParsingService(true, setTccl), false, null);
+ register(bc, DocumentBuilderFactory.class, new ParsingService(false, setTccl), false, null);
+
+ startHookActivators(bundle.getEquinoxContainer(), bc);
+ }
+
+ private void installSecurityManager(EquinoxConfiguration configuration) throws BundleException {
+ String securityManager = configuration.getConfiguration(Constants.FRAMEWORK_SECURITY);
+ if (System.getSecurityManager() != null && securityManager != null) {
+ throw new BundleException("Cannot specify the \"" + Constants.FRAMEWORK_SECURITY + "\" configuration property when a security manager is already installed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (securityManager == null) {
+ securityManager = configuration.getConfiguration(EquinoxConfiguration.PROP_EQUINOX_SECURITY, configuration.getProperty("java.security.manager")); //$NON-NLS-1$
+ }
+ if (securityManager != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ if (securityManager.length() == 0)
+ sm = new SecurityManager(); // use the default one from java
+ else if (securityManager.equals(Constants.FRAMEWORK_SECURITY_OSGI))
+ sm = new EquinoxSecurityManager(); // use an OSGi enabled manager that understands postponed conditions
+ else {
+ // try to use a specific classloader by classname
+ try {
+ Class<?> clazz = Class.forName(securityManager);
+ sm = (SecurityManager) clazz.newInstance();
+ } catch (ClassNotFoundException e) {
+ // do nothing
+ } catch (ClassCastException e) {
+ // do nothing
+ } catch (InstantiationException e) {
+ // do nothing
+ } catch (IllegalAccessException e) {
+ // do nothing
+ }
+ }
+ if (sm == null)
+ throw new NoClassDefFoundError(securityManager);
+ if (configuration.getDebug().DEBUG_SECURITY)
+ Debug.println("Setting SecurityManager to: " + sm); //$NON-NLS-1$
+ System.setSecurityManager(sm);
+ setSecurityManagner = sm;
+ return;
+ }
+ }
+ }
+
+ private void registerLocations(BundleContext bc, EquinoxLocations equinoxLocations) {
+ Dictionary<String, Object> locationProperties = new Hashtable<String, Object>(1);
+ Location location = equinoxLocations.getUserLocation();
+ if (location != null) {
+ locationProperties.put("type", EquinoxLocations.PROP_USER_AREA); //$NON-NLS-1$
+ register(bc, Location.class, location, locationProperties);
+ }
+ location = equinoxLocations.getInstanceLocation();
+ if (location != null) {
+ locationProperties.put("type", EquinoxLocations.PROP_INSTANCE_AREA); //$NON-NLS-1$
+ register(bc, Location.class, location, locationProperties);
+ }
+ location = equinoxLocations.getConfigurationLocation();
+ if (location != null) {
+ locationProperties.put("type", EquinoxLocations.PROP_CONFIG_AREA); //$NON-NLS-1$
+ register(bc, Location.class, location, locationProperties);
+ }
+ location = equinoxLocations.getInstallLocation();
+ if (location != null) {
+ locationProperties.put("type", EquinoxLocations.PROP_INSTALL_AREA); //$NON-NLS-1$
+ register(bc, Location.class, location, locationProperties);
+ }
+
+ location = equinoxLocations.getEclipseHomeLocation();
+ if (location != null) {
+ locationProperties.put("type", EquinoxLocations.PROP_HOME_LOCATION_AREA); //$NON-NLS-1$
+ register(bc, Location.class, location, locationProperties);
+ }
+ }
+
+ private void startHookActivators(EquinoxContainer container, BundleContext context) throws Exception {
+ HookRegistry hookRegistry = container.getConfiguration().getHookRegistry();
+ List<ActivatorHookFactory> activatorHookFactories = hookRegistry.getActivatorHookFactories();
+ hookActivators = new ArrayList<BundleActivator>(activatorHookFactories.size());
+ for (ActivatorHookFactory activatorFactory : activatorHookFactories) {
+ BundleActivator activatorHook = activatorFactory.createActivator();
+ activatorHook.start(context);
+ hookActivators.add(activatorHook);
+ }
+ }
+
+ public void stop(BundleContext bc) throws Exception {
+ EquinoxBundle bundle = (EquinoxBundle) bc.getBundle();
+
+ stopHookActivators(bc);
+
+ FrameworkDebugOptions dbgOptions = (FrameworkDebugOptions) bundle.getEquinoxContainer().getConfiguration().getDebugOptions();
+ dbgOptions.stop(bc);
+
+ urlFactoryManager.uninstallHandlerFactories();
+
+ // unregister services
+ for (ServiceRegistration<?> registration : registrations)
+ registration.unregister();
+ registrations.clear();
+ bundle.getEquinoxContainer().getLogServices().stop(bc);
+ unintallSecurityManager();
+ bundle.getEquinoxContainer().systemStop(bc);
+ }
+
+ private void unintallSecurityManager() {
+ if (System.getSecurityManager() == setSecurityManagner)
+ System.setSecurityManager(null);
+ setSecurityManagner = null;
+ }
+
+ private void stopHookActivators(BundleContext context) throws Exception {
+ if (hookActivators != null) {
+ for (BundleActivator activatorHook : hookActivators) {
+ activatorHook.stop(context);
+ }
+ hookActivators.clear();
+ }
+ }
+
+ private void register(BundleContext context, Class<?> serviceClass, Object service, Dictionary<String, Object> properties) {
+ register(context, serviceClass, service, true, properties);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void register(BundleContext context, Class<?> serviceClass, Object service, boolean setRanking, Dictionary<String, Object> properties) {
+ if (properties == null)
+ properties = new Hashtable<String, Object>(7);
+ Dictionary<String, String> headers = context.getBundle().getHeaders();
+ properties.put(Constants.SERVICE_VENDOR, headers.get(Constants.BUNDLE_VENDOR));
+ if (setRanking) {
+ properties.put(Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE));
+ }
+ properties.put(Constants.SERVICE_PID, context.getBundle().getBundleId() + "." + service.getClass().getName()); //$NON-NLS-1$
+ registrations.add(context.registerService((Class<Object>) serviceClass, service, properties));
+ }
+
+ private static class ParsingService implements ServiceFactory<Object> {
+ private final boolean isSax;
+ private final boolean setTccl;
+
+ public ParsingService(boolean isSax, boolean setTccl) {
+ this.isSax = isSax;
+ this.setTccl = setTccl;
+ }
+
+ public Object getService(Bundle bundle, ServiceRegistration<Object> registration) {
+ if (!setTccl || bundle == null)
+ return createService();
+ /*
+ * Set the TCCL while creating jaxp factory instances to the
+ * requesting bundles class loader. This is needed to
+ * work around bug 285505. There are issues if multiple
+ * xerces implementations are available on the bundles class path
+ *
+ * The real issue is that the ContextFinder will only delegate
+ * to the framework class loader in this case. This class
+ * loader forces the requesting bundle to be delegated to for
+ * TCCL loads.
+ */
+ final ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ BundleWiring wiring = bundle.adapt(BundleWiring.class);
+ ClassLoader cl = wiring == null ? null : wiring.getClassLoader();
+ if (cl != null)
+ Thread.currentThread().setContextClassLoader(cl);
+ return createService();
+ } finally {
+ Thread.currentThread().setContextClassLoader(savedClassLoader);
+ }
+ }
+
+ private Object createService() {
+ if (isSax)
+ return SAXParserFactory.newInstance();
+ return DocumentBuilderFactory.newInstance();
+ }
+
+ public void ungetService(Bundle bundle, ServiceRegistration<Object> registration, Object service) {
+ // Do nothing.
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/UniversalUniqueIdentifier.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/UniversalUniqueIdentifier.java
index abeab38b1..5332c1ed1 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/UniversalUniqueIdentifier.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/UniversalUniqueIdentifier.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.framework;
import java.io.*;
import java.math.BigInteger;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java
new file mode 100644
index 000000000..b9785c1ba
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.framework.legacy;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import org.eclipse.osgi.container.*;
+import org.osgi.framework.*;
+import org.osgi.framework.namespace.*;
+import org.osgi.framework.wiring.*;
+import org.osgi.service.packageadmin.*;
+
+@Deprecated
+public class PackageAdminImpl implements PackageAdmin {
+ private final ModuleContainer container;
+
+ /*
+ * We need to make sure that the GetBundleAction class loads early to prevent a ClassCircularityError when checking permissions.
+ * See bug 161561
+ */
+ static {
+ Class<?> c;
+ c = GetBundleAction.class;
+ c.getName(); // to prevent compiler warnings
+ }
+
+ static class GetBundleAction implements PrivilegedAction<Bundle> {
+ private Class<?> clazz;
+ private PackageAdminImpl impl;
+
+ public GetBundleAction(PackageAdminImpl impl, Class<?> clazz) {
+ this.impl = impl;
+ this.clazz = clazz;
+ }
+
+ public Bundle run() {
+ return impl.getBundlePriv(clazz);
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param container the container
+ */
+ public PackageAdminImpl(ModuleContainer container) {
+ this.container = container;
+ }
+
+ public ExportedPackage[] getExportedPackages(Bundle bundle) {
+ Collection<ModuleRevision> revisions;
+ if (bundle != null) {
+ Module module = StartLevelImpl.getModule(bundle);
+ revisions = module == null ? Collections.<ModuleRevision> emptyList() : module.getRevisions().getModuleRevisions();
+ } else {
+ revisions = new HashSet<ModuleRevision>();
+ for (Module module : container.getModules()) {
+ revisions.addAll(module.getRevisions().getModuleRevisions());
+ }
+ for (ModuleRevision revision : container.getRemovalPending()) {
+ revisions.add(revision);
+ }
+ }
+
+ Collection<ExportedPackage> allExports = new ArrayList<ExportedPackage>();
+ for (ModuleRevision revision : revisions) {
+ ModuleWiring wiring = revision.getWiring();
+ if (wiring != null) {
+ List<ModuleCapability> providedPackages = wiring.getModuleCapabilities(PackageNamespace.PACKAGE_NAMESPACE);
+ for (ModuleCapability providedPackage : providedPackages) {
+ allExports.add(new ExportedPackageImpl(providedPackage, wiring));
+ }
+ }
+ }
+ return allExports.toArray(new ExportedPackage[allExports.size()]);
+ }
+
+ public ExportedPackage getExportedPackage(String name) {
+ ExportedPackage[] allExports = getExportedPackages((Bundle) null);
+ if (allExports == null)
+ return null;
+ ExportedPackage result = null;
+ for (int i = 0; i < allExports.length; i++) {
+ if (name.equals(allExports[i].getName())) {
+ if (result == null) {
+ result = allExports[i];
+ } else {
+ Version curVersion = result.getVersion();
+ Version newVersion = allExports[i].getVersion();
+ if (newVersion.compareTo(curVersion) >= 0)
+ result = allExports[i];
+ }
+ }
+ }
+ return result;
+ }
+
+ public ExportedPackage[] getExportedPackages(String name) {
+ ExportedPackage[] allExports = getExportedPackages((Bundle) null);
+ if (allExports == null)
+ return null;
+ List<ExportedPackage> result = new ArrayList<ExportedPackage>(1); // rare to have more than one
+ for (int i = 0; i < allExports.length; i++)
+ if (name.equals(allExports[i].getName()))
+ result.add(allExports[i]);
+ return (result.size() == 0 ? null : result.toArray(new ExportedPackage[result.size()]));
+ }
+
+ public void refreshPackages(Bundle[] input) {
+ container.getFrameworkWiring().refreshBundles(input == null ? null : Arrays.asList(input));
+ }
+
+ public boolean resolveBundles(Bundle[] input) {
+ return container.getFrameworkWiring().resolveBundles(input == null ? null : Arrays.asList(input));
+ }
+
+ public RequiredBundle[] getRequiredBundles(String symbolicName) {
+ Collection<ModuleRevision> revisions = container.getRevisions(symbolicName, null);
+ Collection<RequiredBundle> result = new ArrayList<RequiredBundle>();
+ for (ModuleRevision revision : revisions) {
+ ModuleWiring wiring = revision.getWiring();
+ if (wiring != null) {
+ List<ModuleCapability> bundleCapabilities = wiring.getModuleCapabilities(BundleNamespace.BUNDLE_NAMESPACE);
+ for (ModuleCapability bundleCapability : bundleCapabilities) {
+ result.add(new RequiredBundleImpl(bundleCapability, wiring));
+ }
+ }
+ }
+ return result.toArray(new RequiredBundle[result.size()]);
+ }
+
+ public Bundle[] getBundles(String symbolicName, String versionRange) {
+ if (symbolicName == null) {
+ throw new IllegalArgumentException();
+ }
+ Collection<ModuleRevision> revisions = container.getRevisions(symbolicName, null);
+ if (revisions.isEmpty()) {
+ return null;
+ }
+ List<ModuleRevision> sorted = new LinkedList<ModuleRevision>(revisions);
+ Collections.sort(sorted, new Comparator<ModuleRevision>() {
+ @Override
+ public int compare(ModuleRevision m1, ModuleRevision m2) {
+ return m2.getVersion().compareTo(m1.getVersion());
+ }
+ });
+ if (versionRange != null) {
+ VersionRange range = new VersionRange(versionRange);
+ for (Iterator<ModuleRevision> iSorted = sorted.iterator(); iSorted.hasNext();) {
+ if (!range.includes(iSorted.next().getVersion())) {
+ iSorted.remove();
+ }
+ }
+ }
+
+ if (sorted.isEmpty()) {
+ return null;
+ }
+
+ // This code depends on the array of bundles being in descending
+ // version order.
+ Bundle[] result = new Bundle[sorted.size()];
+ int i = 0;
+ for (ModuleRevision revision : sorted) {
+ result[i] = revision.getBundle();
+ i++;
+ }
+
+ return result;
+ }
+
+ public Bundle[] getFragments(Bundle bundle) {
+ ModuleWiring wiring = getWiring(bundle);
+ if (wiring == null) {
+ return null;
+ }
+ List<ModuleWire> hostWires = wiring.getProvidedModuleWires(HostNamespace.HOST_NAMESPACE);
+ Collection<Bundle> fragments = new ArrayList<Bundle>(hostWires.size());
+ for (ModuleWire wire : hostWires) {
+ Bundle fragment = wire.getRequirer().getBundle();
+ if (fragment != null) {
+ fragments.add(fragment);
+ }
+ }
+ return fragments.isEmpty() ? null : fragments.toArray(new Bundle[fragments.size()]);
+ }
+
+ public Bundle[] getHosts(Bundle bundle) {
+ ModuleWiring wiring = getWiring(bundle);
+ if (wiring == null) {
+ return null;
+ }
+ List<ModuleWire> hostWires = wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ Collection<Bundle> hosts = new ArrayList<Bundle>(hostWires.size());
+ for (ModuleWire wire : hostWires) {
+ Bundle host = wire.getProvider().getBundle();
+ if (host != null) {
+ hosts.add(host);
+ }
+ }
+ return hosts.isEmpty() ? null : hosts.toArray(new Bundle[hosts.size()]);
+ }
+
+ private ModuleWiring getWiring(Bundle bundle) {
+ Module module = StartLevelImpl.getModule(bundle);
+ if (module == null) {
+ return null;
+ }
+
+ List<ModuleRevision> revisions = module.getRevisions().getModuleRevisions();
+ if (revisions.isEmpty()) {
+ return null;
+ }
+
+ return revisions.get(0).getWiring();
+ }
+
+ Bundle getBundlePriv(Class<?> clazz) {
+ ClassLoader cl = clazz.getClassLoader();
+ if (cl instanceof BundleReference) {
+ return ((BundleReference) cl).getBundle();
+ }
+ if (cl == getClass().getClassLoader()) {
+ return container.getModule(0).getBundle();
+ }
+ return null;
+ }
+
+ public Bundle getBundle(@SuppressWarnings("rawtypes") final Class clazz) {
+ if (System.getSecurityManager() == null)
+ return getBundlePriv(clazz);
+ return AccessController.doPrivileged(new GetBundleAction(this, clazz));
+ }
+
+ public int getBundleType(Bundle bundle) {
+ Module module = StartLevelImpl.getModule(bundle);
+ if (module == null) {
+ return 0;
+ }
+ List<BundleRevision> revisions = module.getRevisions().getRevisions();
+ if (revisions.isEmpty()) {
+ return 0;
+ }
+ return (revisions.get(0).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0 ? PackageAdmin.BUNDLE_TYPE_FRAGMENT : 0;
+ }
+
+ public Collection<Bundle> getRemovalPendingBundles() {
+ return container.getFrameworkWiring().getRemovalPendingBundles();
+ }
+
+ public Collection<Bundle> getDependencyClosure(Collection<Bundle> bundles) {
+ return container.getFrameworkWiring().getDependencyClosure(bundles);
+ }
+
+ static class ExportedPackageImpl implements ExportedPackage {
+
+ private final ModuleCapability packageCapability;
+ private final ModuleWiring providerWiring;
+
+ public ExportedPackageImpl(ModuleCapability packageCapability, ModuleWiring providerWiring) {
+ this.packageCapability = packageCapability;
+ this.providerWiring = providerWiring;
+ }
+
+ public String getName() {
+ return (String) packageCapability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ }
+
+ public Bundle getExportingBundle() {
+ if (!providerWiring.isInUse())
+ return null;
+ return providerWiring.getBundle();
+ }
+
+ public Bundle[] getImportingBundles() {
+ if (!providerWiring.isInUse()) {
+ return null;
+ }
+ Set<Bundle> importing = new HashSet<Bundle>();
+
+ addRequirers(importing, providerWiring);
+
+ String packageName = getName();
+ List<ModuleWire> providedPackages = providerWiring.getProvidedModuleWires(PackageNamespace.PACKAGE_NAMESPACE);
+ for (ModuleWire packageWire : providedPackages) {
+ if (packageCapability.equals(packageWire.getCapability())) {
+ importing.add(packageWire.getRequirer().getBundle());
+ if (packageWire.getRequirerWiring().isSubstitutedPackage(packageName)) {
+ addRequirers(importing, packageWire.getRequirerWiring());
+ }
+ }
+ }
+ return importing.toArray(new Bundle[importing.size()]);
+ }
+
+ private static void addRequirers(Set<Bundle> importing, BundleWiring providerWiring) {
+ List<BundleWire> requirerWires = providerWiring.getProvidedWires(BundleNamespace.BUNDLE_NAMESPACE);
+ for (BundleWire requireBundleWire : requirerWires) {
+ Bundle requirer = requireBundleWire.getRequirer().getBundle();
+ if (importing.contains(requirer)) {
+ continue;
+ }
+ importing.add(requirer);
+ String reExport = requireBundleWire.getRequirement().getDirectives().get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE);
+ if (BundleNamespace.VISIBILITY_REEXPORT.equals(reExport)) {
+ addRequirers(importing, requireBundleWire.getRequirerWiring());
+ }
+ }
+ }
+
+ /**
+ * @deprecated
+ */
+ public String getSpecificationVersion() {
+ return getVersion().toString();
+ }
+
+ public Version getVersion() {
+ Version version = (Version) packageCapability.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ return version == null ? Version.emptyVersion : version;
+ }
+
+ public boolean isRemovalPending() {
+ return !providerWiring.isCurrent();
+ }
+
+ public String toString() {
+ return packageCapability.toString();
+ }
+ }
+
+ private static class RequiredBundleImpl implements RequiredBundle {
+ private final ModuleCapability bundleCapability;
+ private final ModuleWiring providerWiring;
+
+ public RequiredBundleImpl(ModuleCapability bundleCapability, ModuleWiring providerWiring) {
+ this.bundleCapability = bundleCapability;
+ this.providerWiring = providerWiring;
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return (String) bundleCapability.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE);
+ }
+
+ @Override
+ public Bundle getBundle() {
+ if (!providerWiring.isInUse())
+ return null;
+ return providerWiring.getBundle();
+ }
+
+ @Override
+ public Bundle[] getRequiringBundles() {
+ if (!providerWiring.isInUse()) {
+ return null;
+ }
+ Set<Bundle> requireing = new HashSet<Bundle>();
+
+ addRequirers(requireing, providerWiring);
+
+ return requireing.toArray(new Bundle[requireing.size()]);
+ }
+
+ private static void addRequirers(Set<Bundle> requiring, BundleWiring providerWiring) {
+ List<BundleWire> requirerWires = providerWiring.getProvidedWires(BundleNamespace.BUNDLE_NAMESPACE);
+ for (BundleWire requireBundleWire : requirerWires) {
+ Bundle requirer = requireBundleWire.getRequirer().getBundle();
+ if (requiring.contains(requirer)) {
+ continue;
+ }
+ requiring.add(requirer);
+ String reExport = requireBundleWire.getRequirement().getDirectives().get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE);
+ if (BundleNamespace.VISIBILITY_REEXPORT.equals(reExport)) {
+ addRequirers(requiring, requireBundleWire.getRequirerWiring());
+ }
+ }
+ }
+
+ @Override
+ public Version getVersion() {
+ Version version = (Version) bundleCapability.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ return version == null ? Version.emptyVersion : version;
+ }
+
+ public boolean isRemovalPending() {
+ return !providerWiring.isCurrent();
+ }
+
+ public String toString() {
+ return bundleCapability.toString();
+ }
+
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/StartLevelImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/StartLevelImpl.java
new file mode 100644
index 000000000..dd59feeee
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/StartLevelImpl.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.framework.legacy;
+
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleContainer;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
+import org.osgi.framework.Bundle;
+import org.osgi.service.startlevel.StartLevel;
+
+@SuppressWarnings("deprecation")
+public class StartLevelImpl implements StartLevel {
+
+ private final ModuleContainer container;
+
+ public StartLevelImpl(ModuleContainer container) {
+ this.container = container;
+ }
+
+ @Override
+ public int getStartLevel() {
+ return container.getFrameworkStartLevel().getStartLevel();
+ }
+
+ @Override
+ public void setStartLevel(int startlevel) {
+ container.getFrameworkStartLevel().setStartLevel(startlevel);
+ }
+
+ @Override
+ public int getBundleStartLevel(Bundle bundle) {
+ return getModule(bundle).getStartLevel();
+ }
+
+ @Override
+ public void setBundleStartLevel(Bundle bundle, int startlevel) {
+ getModule(bundle).setStartLevel(startlevel);
+ }
+
+ @Override
+ public int getInitialBundleStartLevel() {
+ return container.getFrameworkStartLevel().getInitialBundleStartLevel();
+ }
+
+ @Override
+ public void setInitialBundleStartLevel(int startlevel) {
+ container.getFrameworkStartLevel().setInitialBundleStartLevel(startlevel);
+ }
+
+ @Override
+ public boolean isBundlePersistentlyStarted(Bundle bundle) {
+ return getModule(bundle).isPersistentlyStarted();
+ }
+
+ @Override
+ public boolean isBundleActivationPolicyUsed(Bundle bundle) {
+ return getModule(bundle).isActivationPolicyUsed();
+ }
+
+ static Module getModule(Bundle bundle) {
+ if (bundle instanceof EquinoxBundle) {
+ return ((EquinoxBundle) bundle).getModule();
+ }
+ throw new IllegalArgumentException("Bundle is not from an equinox framework: " + bundle.getClass()); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/osname.aliases b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/osname.aliases
index 0aff94e32..0aff94e32 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/osname.aliases
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/osname.aliases
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/processor.aliases b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/processor.aliases
index 5fb0ff398..5fb0ff398 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/processor.aliases
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/processor.aliases
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ProtocolActivator.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ActivatorHookFactory.java
index 39043c01e..c2140cfc3 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ProtocolActivator.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ActivatorHookFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * Copyright (c) 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,15 +8,10 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
+package org.eclipse.osgi.internal.hookregistry;
-package org.eclipse.osgi.framework.internal.protocol;
-
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.osgi.framework.BundleContext;
-
-//TODO this is non-API, and has no internal clients - do we really need it? at least explain why
-public interface ProtocolActivator {
-
- public void start(BundleContext context, FrameworkAdaptor adaptor);
+import org.osgi.framework.BundleActivator;
+public interface ActivatorHookFactory {
+ public BundleActivator createActivator();
}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileWrapperFactoryHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java
index 2c37adb46..d2e4e55d6 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileWrapperFactoryHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,30 +9,24 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.hooks;
+package org.eclipse.osgi.internal.hookregistry;
-import java.io.IOException;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
/**
* A factory that wraps bundle file objects.
- * @see BaseAdaptor#createBundleFile(Object, BaseData)
- * @since 3.2
*/
public interface BundleFileWrapperFactoryHook {
/**
* Wraps a bundle file for the given content and base data. If the
* specified bundle file should not be wrapped then null is returned
* @param bundleFile the bundle file to be wrapped
- * @param content The object which contains the content of a bundle file.
- * @param data The base data associated with the content
+ * @param generation the generation the bundle file is for
* @param base true if the content is for the base bundle (not an inner jar, directory etc.)
* @return a wrapped bundle file for the specified content, or null if the bundle content
* is not wrapped.
- * @throws IOException if an IO error occurs
*/
- BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) throws IOException;
+ BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base);
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java
new file mode 100644
index 000000000..b77e2a58b
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.hookregistry;
+
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+
+public abstract class ClassLoaderHook {
+ /**
+ * Gets called by a classpath manager before defining a class. This method allows a class loading hook
+ * to process the bytes of a class that is about to be defined.
+ * @param name the name of the class being defined
+ * @param classbytes the bytes of the class being defined
+ * @param classpathEntry the ClasspathEntry where the class bytes have been read from.
+ * @param entry the BundleEntry source of the class bytes
+ * @param manager the class path manager used to define the requested class
+ * @return a modified array of classbytes or null if the original bytes should be used.
+ */
+ public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
+ return null;
+ }
+
+ /**
+ * Gets called by a classpath manager when looking for ClasspathEntry objects. This method allows
+ * a classloading hook to add additional ClasspathEntry objects
+ * @param cpEntries the list of ClasspathEntry objects currently available for the requested classpath
+ * @param cp the name of the requested classpath
+ * @param hostmanager the classpath manager the requested ClasspathEntry is for
+ * @param sourceGeneration the source generation of the requested ClasspathEntry
+ * @return true if a ClasspathEntry has been added to cpEntries
+ */
+ public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, Generation sourceGeneration) {
+ return false;
+ }
+
+ /**
+ * Gets called by a base data during {@link ModuleClassLoader#findLibrary(String)}.
+ * A this method is called for each configured class loading hook until one
+ * class loading hook returns a non-null value. If no class loading hook returns
+ * a non-null value then the default behavior will be used.
+ * @param generation the bundle generation to find a native library for.
+ * @param libName the name of the native library.
+ * @return The absolute path name of the native library or null.
+ */
+ public String findLocalLibrary(Generation generation, String libName) {
+ return null;
+ }
+
+ /**
+ * Gets called by a classpath manager at the end of
+ * {@link BundleLoader#getClassLoader()} is called the first time and a class loader is created.
+ * @param classLoader the newly created bundle classloader
+ */
+ public void classLoaderCreated(ModuleClassLoader classLoader) {
+ // do nothing
+ }
+
+ /**
+ * Called by a {@link BundleLoader#findClass(String)} method before delegating to the resolved constraints and
+ * local bundle for a class load. If this method returns null then normal delegation is done. If this method
+ * returns a non-null value then the rest of the delegation process is skipped and the returned value is used.
+ * If this method throws a <code>ClassNotFoundException</code> then the calling
+ * {@link BundleLoader#findClass(String)} method re-throws the exception.
+ * @param name the name of the class to find
+ * @param classLoader the module class loader
+ * @return the class found by this hook or null if normal delegation should continue
+ * @throws ClassNotFoundException to terminate the delegation and throw an exception
+ */
+ public Class<?> preFindClass(String name, ModuleClassLoader classLoader) throws ClassNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link BundleLoader#findClass(String)} method after delegating to the resolved constraints and
+ * local bundle for a class load. This method will only be called if no class was found
+ * from the normal delegation.
+ * @param name the name of the class to find
+ * @param classLoader the bundle class loader
+ * @return the class found by this hook or null if normal delegation should continue
+ * @throws ClassNotFoundException to terminate the delegation and throw an exception
+ */
+ public Class<?> postFindClass(String name, ModuleClassLoader classLoader) throws ClassNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link BundleLoader#findResource(String)} before delegating to the resolved constraints and
+ * local bundle for a resource load. If this method returns null then normal delegation is done.
+ * If this method returns a non-null value then the rest of the delegation process is skipped and the returned value is used.
+ * If this method throws an <code>FileNotFoundException</code> then the delegation is terminated.
+ * @param name the name of the resource to find
+ * @param classLoader the bundle class loader
+ * @return the resource found by this hook or null if normal delegation should continue
+ * @throws FileNotFoundException to terminate the delegation
+ */
+ public URL preFindResource(String name, ModuleClassLoader classLoader) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link BundleLoader#findResource(String)} after delegating to the resolved constraints and
+ * local bundle for a resource load. This method will only be called if no resource was found
+ * from the normal delegation.
+ * @param name the name of the resource to find
+ * @param classLoader the bundle class loader
+ * @return the resource found by this hook or null if normal delegation should continue
+ * @throws FileNotFoundException to terminate the delegation
+ */
+ public URL postFindResource(String name, ModuleClassLoader classLoader) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link BundleLoader#findResources(String)} before delegating to the resolved constraints and
+ * local bundle for a resource load. If this method returns null then normal delegation is done.
+ * If this method returns a non-null value then the rest of the delegation process is skipped and the returned value is used.
+ * If this method throws an <code>FileNotFoundException</code> then the delegation is terminated
+ * @param name the name of the resource to find
+ * @param classLoader the bundle class loader
+ * @return the resources found by this hook or null if normal delegation should continue
+ * @throws FileNotFoundException to terminate the delegation
+ */
+ public Enumeration<URL> preFindResources(String name, ModuleClassLoader classLoader) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link BundleLoader#findResources(String)} after delegating to the resolved constraints and
+ * local bundle for a resource load. This method will only be called if no resources were found
+ * from the normal delegation.
+ * @param name the name of the resource to find
+ * @param classLoader the bundle class loader
+ * @return the resources found by this hook or null if normal delegation should continue
+ * @throws FileNotFoundException to terminate the delegation
+ */
+ public Enumeration<URL> postFindResources(String name, ModuleClassLoader classLoader) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link ClasspathManager} before normal delegation. If this method returns
+ * a non-null value then the rest of the delegation process is skipped and the returned value
+ * is used.
+ * @param name the name of the library to find
+ * @param classLoader the bundle class loader
+ * @return the library found by this hook or null if normal delegation should continue
+ * @throws FileNotFoundException to terminate the delegation
+ */
+ public String preFindLibrary(String name, ModuleClassLoader classLoader) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * Called by a {@link ClasspathManager} after normal delegation. This method will only be called
+ * if no library was found from the normal delegation.
+ * @param name the name of the library to find
+ * @param classLoader the bundle class loader
+ * @return the library found by this hook or null if normal delegation should continue
+ */
+ public String postFindLibrary(String name, ModuleClassLoader classLoader) {
+ return null;
+ }
+
+ /**
+ * Gets called by a classpath manager during {@link ClasspathManager#findLocalClass(String)} before
+ * searching the local classloader for a class. A classpath manager will call this method for
+ * each configured class loading stat hook.
+ * @param name the name of the requested class
+ * @param manager the classpath manager used to find and load the requested class
+ * @throws ClassNotFoundException to prevent the requested class from loading
+ */
+ public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
+ // do nothing
+ }
+
+ /**
+ * Gets called by a classpath manager during {@link ClasspathManager#findLocalClass(String)} after
+ * searching the local classloader for a class. A classpath manager will call this method for
+ * each configured class loading stat hook.
+ * @param name the name of the requested class
+ * @param clazz the loaded class or null if not found
+ * @param manager the classpath manager used to find and load the requested class
+ * @throws ClassNotFoundException
+ */
+ public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) throws ClassNotFoundException {
+ // do nothing
+ }
+
+ /**
+ * Gets called by a classpath manager during {@link ClasspathManager#findLocalResource(String)} before
+ * searching the local classloader for a resource. A classpath manager will call this method for
+ * each configured class loading stat hook.
+ * @param name the name of the requested resource
+ * @param manager the classpath manager used to find the requested resource
+ */
+ public void preFindLocalResource(String name, ClasspathManager manager) {
+ // do nothing
+ }
+
+ /**
+ * Gets called by a classpath manager during {@link ClasspathManager#findLocalResource(String)} after
+ * searching the local classloader for a resource. A classpath manager will call this method for
+ * each configured class loading stat hook.
+ * @param name the name of the requested resource
+ * @param resource the URL to the requested resource or null if not found
+ * @param manager the classpath manager used to find the requested resource
+ */
+ public void postFindLocalResource(String name, URL resource, ClasspathManager manager) {
+ // do nothing
+ }
+
+ /**
+ * Gets called by a classpath manager after an attempt is made to define a class. This method allows
+ * a class loading stat hook to record data about a class definition.
+ * @param name the name of the class that got defined
+ * @param clazz the class object that got defined or null if an error occurred while defining a class
+ * @param classbytes the class bytes used to define the class
+ * @param classpathEntry the ClasspathEntry where the class bytes got read from
+ * @param entry the BundleEntyr source of the class bytes
+ * @param manager the classpath manager used to define the class
+ */
+ public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
+ // do nothing
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/HookConfigurator.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookConfigurator.java
index e203a1104..4363f2e31 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/HookConfigurator.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookConfigurator.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor;
+package org.eclipse.osgi.internal.hookregistry;
/**
* A hook configurator is used to add hooks to the hook registry.
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/HookRegistry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java
index e0c91e0c8..90e66ae1f 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/HookRegistry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,16 +9,19 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor;
+package org.eclipse.osgi.internal.hookregistry;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.hooks.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.hooks.DevClassLoadingHook;
+import org.eclipse.osgi.internal.hooks.EclipseLazyStarter;
+import org.eclipse.osgi.internal.signedcontent.SignedBundleHook;
+import org.eclipse.osgi.internal.weaving.WeavingHookConfigurator;
import org.eclipse.osgi.util.ManifestElement;
/**
@@ -65,19 +68,19 @@ public final class HookRegistry {
private static final String BUILTIN_HOOKS = "builtin.hooks"; //$NON-NLS-1$
- private BaseAdaptor adaptor;
- private boolean readonly = false;
- private AdaptorHook[] adaptorHooks = new AdaptorHook[0];
- private BundleWatcher[] watchers = new BundleWatcher[0];
- private ClassLoadingHook[] classLoadingHooks = new ClassLoadingHook[0];
- private ClassLoadingStatsHook[] classLoadingStatsHooks = new ClassLoadingStatsHook[0];
- private ClassLoaderDelegateHook[] classLoaderDelegateHooks = new ClassLoaderDelegateHook[0];
- private StorageHook[] storageHooks = new StorageHook[0];
- private BundleFileFactoryHook[] bundleFileFactoryHooks = new BundleFileFactoryHook[0];
- private BundleFileWrapperFactoryHook[] bundleFileWrapperFactoryHooks = new BundleFileWrapperFactoryHook[0];
-
- public HookRegistry(BaseAdaptor adaptor) {
- this.adaptor = adaptor;
+ private final EquinoxContainer container;
+ private volatile boolean initialized = false;
+ private final List<ClassLoaderHook> classLoaderHooks = new ArrayList<ClassLoaderHook>();
+ private final List<ClassLoaderHook> classLoaderHooksRO = Collections.unmodifiableList(classLoaderHooks);
+ private final List<StorageHookFactory<?, ?, ?>> storageHookFactories = new ArrayList<StorageHookFactory<?, ?, ?>>();
+ private final List<StorageHookFactory<?, ?, ?>> storageHookFactoriesRO = Collections.unmodifiableList(storageHookFactories);
+ private final List<BundleFileWrapperFactoryHook> bundleFileWrapperFactoryHooks = new ArrayList<BundleFileWrapperFactoryHook>();
+ private final List<BundleFileWrapperFactoryHook> bundleFileWrapperFactoryHooksRO = Collections.unmodifiableList(bundleFileWrapperFactoryHooks);
+ private final List<ActivatorHookFactory> activatorHookFactories = new ArrayList<ActivatorHookFactory>();
+ private final List<ActivatorHookFactory> activatorHookFactoriesRO = Collections.unmodifiableList(activatorHookFactories);
+
+ public HookRegistry(EquinoxContainer container) {
+ this.container = container;
}
/**
@@ -90,17 +93,24 @@ public final class HookRegistry {
* and remove this list from the overall list of hook configurators. <p>
* 4. Load each hook configurator class, create a new instance, then call the {@link HookConfigurator#addHooks(HookRegistry)} method <p>
* 5. Set this HookRegistry object to read only to prevent any other hooks from being added. <p>
- * @return an array of error log entries that occurred while initializing the hooks
*/
- public FrameworkLogEntry[] initialize() {
+ public void initialize() {
List<String> configurators = new ArrayList<String>(5);
List<FrameworkLogEntry> errors = new ArrayList<FrameworkLogEntry>(0); // optimistic that no errors will occur
mergeFileHookConfigurators(configurators, errors);
mergePropertyHookConfigurators(configurators);
- loadConfigurators(configurators, errors);
- // set to read-only
- readonly = true;
- return errors.toArray(new FrameworkLogEntry[errors.size()]);
+ synchronized (this) {
+ addClassLoaderHook(new DevClassLoadingHook(container.getConfiguration()));
+ addClassLoaderHook(new EclipseLazyStarter(container));
+ addClassLoaderHook(new WeavingHookConfigurator(container));
+ configurators.add(SignedBundleHook.class.getName());
+ loadConfigurators(configurators, errors);
+ // set to read-only
+ initialized = true;
+ }
+ for (FrameworkLogEntry error : errors) {
+ container.getLogServices().getFrameworkLog().log(error);
+ }
}
private void mergeFileHookConfigurators(List<String> configuratorList, List<FrameworkLogEntry> errors) {
@@ -110,7 +120,7 @@ public final class HookRegistry {
try {
hookConfigurators = cl != null ? cl.getResources(HookRegistry.HOOK_CONFIGURATORS_FILE) : ClassLoader.getSystemResources(HookRegistry.HOOK_CONFIGURATORS_FILE);
} catch (IOException e) {
- errors.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "getResources error on " + HookRegistry.HOOK_CONFIGURATORS_FILE, 0, e, null)); //$NON-NLS-1$
+ errors.add(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, "getResources error on " + HookRegistry.HOOK_CONFIGURATORS_FILE, 0, e, null)); //$NON-NLS-1$
return;
}
int curBuiltin = 0;
@@ -135,7 +145,7 @@ public final class HookRegistry {
configuratorList.add(configurators[i]);
}
} catch (IOException e) {
- errors.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "error loading: " + url.toExternalForm(), 0, e, null)); //$NON-NLS-1$
+ errors.add(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, "error loading: " + url.toExternalForm(), 0, e, null)); //$NON-NLS-1$
// ignore and continue to next URL
} finally {
if (input != null)
@@ -150,7 +160,7 @@ public final class HookRegistry {
private void mergePropertyHookConfigurators(List<String> configuratorList) {
// see if there is a configurators list
- String[] configurators = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(HookRegistry.PROP_HOOK_CONFIGURATORS), ","); //$NON-NLS-1$
+ String[] configurators = ManifestElement.getArrayFromList(container.getConfiguration().getConfiguration(HookRegistry.PROP_HOOK_CONFIGURATORS), ","); //$NON-NLS-1$
if (configurators.length > 0) {
configuratorList.clear(); // clear the list, we are only going to use the configurators from the list
for (int i = 0; i < configurators.length; i++)
@@ -159,12 +169,12 @@ public final class HookRegistry {
return; // don't do anything else
}
// Make sure the configurators from the include property are in the list
- String[] includeConfigurators = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(HookRegistry.PROP_HOOK_CONFIGURATORS_INCLUDE), ","); //$NON-NLS-1$
+ String[] includeConfigurators = ManifestElement.getArrayFromList(container.getConfiguration().getConfiguration(HookRegistry.PROP_HOOK_CONFIGURATORS_INCLUDE), ","); //$NON-NLS-1$
for (int i = 0; i < includeConfigurators.length; i++)
if (!configuratorList.contains(includeConfigurators[i]))
configuratorList.add(includeConfigurators[i]);
// Make sure the configurators from the exclude property are no in the list
- String[] excludeHooks = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(HookRegistry.PROP_HOOK_CONFIGURATORS_EXCLUDE), ","); //$NON-NLS-1$
+ String[] excludeHooks = ManifestElement.getArrayFromList(container.getConfiguration().getConfiguration(HookRegistry.PROP_HOOK_CONFIGURATORS_EXCLUDE), ","); //$NON-NLS-1$
for (int i = 0; i < excludeHooks.length; i++)
configuratorList.remove(excludeHooks[i]);
}
@@ -182,129 +192,63 @@ public final class HookRegistry {
// IllegalAccessException
// InstantiationException
// ClassCastException
- errors.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "error loading hook: " + hookName, 0, t, null)); //$NON-NLS-1$
+ errors.add(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, "error loading hook: " + hookName, 0, t, null)); //$NON-NLS-1$
}
}
}
/**
- * Returns the list of configured adaptor hooks.
- * @return the list of configured adaptor hooks.
- */
- public AdaptorHook[] getAdaptorHooks() {
- return adaptorHooks;
- }
-
- /**
- * Returns the list of configured bundle watchers.
- * @return the list of configured bundle watchers.
- */
- public BundleWatcher[] getWatchers() {
- return watchers;
- }
-
- /**
* Returns the list of configured class loading hooks.
* @return the list of configured class loading hooks.
*/
- public ClassLoadingHook[] getClassLoadingHooks() {
- return classLoadingHooks;
- }
-
- /**
- * Returns the list of configured class loading stats hooks.
- * @return the list of configured class loading stats hooks.
- */
- public ClassLoadingStatsHook[] getClassLoadingStatsHooks() {
- return classLoadingStatsHooks;
- }
-
- /**
- * Returns the list of configured class loader delegate hooks.
- * @return the list of configured class loader delegate hooks.
- */
- public ClassLoaderDelegateHook[] getClassLoaderDelegateHooks() {
- return classLoaderDelegateHooks;
+ public List<ClassLoaderHook> getClassLoaderHooks() {
+ return classLoaderHooksRO;
}
/**
* Returns the list of configured storage hooks.
* @return the list of configured storage hooks.
*/
- public StorageHook[] getStorageHooks() {
- return storageHooks;
- }
-
- /**
- * Returns the list of configured bundle file factories.
- * @return the list of configured bundle file factories.
- */
- public BundleFileFactoryHook[] getBundleFileFactoryHooks() {
- return bundleFileFactoryHooks;
+ public List<StorageHookFactory<?, ?, ?>> getStorageHookFactories() {
+ return storageHookFactoriesRO;
}
/**
* Returns the configured bundle file wrapper factories
* @return the configured bundle file wrapper factories
*/
- public BundleFileWrapperFactoryHook[] getBundleFileWrapperFactoryHooks() {
- return bundleFileWrapperFactoryHooks;
- }
-
- /**
- * Adds a adaptor hook to this hook registry.
- * @param adaptorHook an adaptor hook object.
- */
- public void addAdaptorHook(AdaptorHook adaptorHook) {
- adaptorHooks = (AdaptorHook[]) add(adaptorHook, adaptorHooks, new AdaptorHook[adaptorHooks.length + 1]);
+ public List<BundleFileWrapperFactoryHook> getBundleFileWrapperFactoryHooks() {
+ return bundleFileWrapperFactoryHooksRO;
}
/**
- * Adds a bundle watcher to this hook registry.
- * @param watcher a bundle watcher object.
+ * Returns the configured activator hook factories
+ * @return the configured activator hook factories
*/
- public void addWatcher(BundleWatcher watcher) {
- watchers = (BundleWatcher[]) add(watcher, watchers, new BundleWatcher[watchers.length + 1]);
+ public List<ActivatorHookFactory> getActivatorHookFactories() {
+ return activatorHookFactoriesRO;
}
- /**
- * Adds a class loading hook to this hook registry.
- * @param classLoadingHook a class loading hook object.
- */
- public void addClassLoadingHook(ClassLoadingHook classLoadingHook) {
- classLoadingHooks = (ClassLoadingHook[]) add(classLoadingHook, classLoadingHooks, new ClassLoadingHook[classLoadingHooks.length + 1]);
- }
-
- /**
- * Adds a class loading stats hook to this hook registry.
- * @param classLoadingStatsHook a class loading hook object.
- */
- public void addClassLoadingStatsHook(ClassLoadingStatsHook classLoadingStatsHook) {
- classLoadingStatsHooks = (ClassLoadingStatsHook[]) add(classLoadingStatsHook, classLoadingStatsHooks, new ClassLoadingStatsHook[classLoadingStatsHooks.length + 1]);
+ private <H> void add(H hook, List<H> hooks) {
+ if (initialized)
+ throw new IllegalStateException("Cannot add hooks dynamically."); //$NON-NLS-1$
+ hooks.add(hook);
}
/**
- * Adds a class loader delegate hook to this hook registry.
- * @param classLoaderDelegateHook a class loader delegate hook.
+ * Adds a class loader hook to this hook registry.
+ * @param classLoaderHook a class loading hook object.
*/
- public void addClassLoaderDelegateHook(ClassLoaderDelegateHook classLoaderDelegateHook) {
- classLoaderDelegateHooks = (ClassLoaderDelegateHook[]) add(classLoaderDelegateHook, classLoaderDelegateHooks, new ClassLoaderDelegateHook[classLoaderDelegateHooks.length + 1]);
+ public void addClassLoaderHook(ClassLoaderHook classLoaderHook) {
+ add(classLoaderHook, classLoaderHooks);
}
/**
* Adds a storage hook to this hook registry.
- * @param storageHook a storage hook object.
- */
- public void addStorageHook(StorageHook storageHook) {
- storageHooks = (StorageHook[]) add(storageHook, storageHooks, new StorageHook[storageHooks.length + 1]);
- }
-
- /**
- * Adds a bundle file factory to this hook registry.
- * @param factory a bundle file factory object.
+ * @param storageHookFactory a storage hook object.
*/
- public void addBundleFileFactoryHook(BundleFileFactoryHook factory) {
- bundleFileFactoryHooks = (BundleFileFactoryHook[]) add(factory, bundleFileFactoryHooks, new BundleFileFactoryHook[bundleFileFactoryHooks.length + 1]);
+ public void addStorageHookFactory(StorageHookFactory<?, ?, ?> storageHookFactory) {
+ add(storageHookFactory, storageHookFactories);
}
/**
@@ -312,23 +256,27 @@ public final class HookRegistry {
* @param factory a bundle file wrapper factory object.
*/
public void addBundleFileWrapperFactoryHook(BundleFileWrapperFactoryHook factory) {
- bundleFileWrapperFactoryHooks = (BundleFileWrapperFactoryHook[]) add(factory, bundleFileWrapperFactoryHooks, new BundleFileWrapperFactoryHook[bundleFileWrapperFactoryHooks.length + 1]);
+ add(factory, bundleFileWrapperFactoryHooks);
}
- private Object[] add(Object newValue, Object[] oldValues, Object[] newValues) {
- if (readonly)
- throw new IllegalStateException("Cannot add hooks dynamically."); //$NON-NLS-1$
- if (oldValues.length > 0)
- System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
- newValues[oldValues.length] = newValue;
- return newValues;
+ /**
+ * Adds an activator hook factory. The activators created by this factory will be started and stopped
+ * when the system bundle is started and stopped.
+ * @param activatorHookFactory the activator hook factory.
+ */
+ public void addActivatorHookFactory(ActivatorHookFactory activatorHookFactory) {
+ add(activatorHookFactory, activatorHookFactories);
}
/**
- * Returns the base adaptor associated with this hook registry.
- * @return the base adaptor associated with this hook registry.
+ * Returns the configuration associated with this hook registry.
+ * @return the configuration associated with this hook registry.
*/
- public BaseAdaptor getAdaptor() {
- return adaptor;
+ public EquinoxConfiguration getConfiguration() {
+ return container.getConfiguration();
+ }
+
+ public EquinoxContainer getContainer() {
+ return container;
}
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/StorageHookFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/StorageHookFactory.java
new file mode 100644
index 000000000..46a06bbee
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/StorageHookFactory.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.hookregistry;
+
+import java.io.*;
+import java.util.Dictionary;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.osgi.framework.BundleException;
+
+/**
+ * A StorageHookFactory hooks into the persistent storage loading and saving of bundle {@link Generation generations}.
+ * A factory creates StorageHook instances that get associated with each Generation object installed.<p>
+ * @see Generation#getStorageHook(Class)
+ * @since 3.2
+ */
+public abstract class StorageHookFactory<S, L, H extends StorageHookFactory.StorageHook<S, L>> {
+ protected final String KEY = this.getClass().getName().intern();
+
+ /**
+ * Returns the storage version of this storage hook. This version
+ * is used by the storage to check the consistency of cached persistent
+ * data. Any time a storage hook changes the format of its persistent
+ * data the storage version should be incremented.
+ * @return the storage version of this storage hook
+ */
+ public abstract int getStorageVersion();
+
+ public final String getKey() {
+ return KEY;
+ }
+
+ public boolean isCompatibleWith(int version) {
+ return getStorageVersion() == version;
+ }
+
+ public S createSaveContext() {
+ return null;
+ }
+
+ public L createLoadContext(int version) {
+ return null;
+ }
+
+ public abstract H createStorageHook(Generation generation);
+
+ public static abstract class StorageHook<S, L> {
+ private final Class<? extends StorageHookFactory<S, L, ? extends StorageHook<S, L>>> factoryClass;
+ private final Generation generation;
+
+ public StorageHook(Generation generation, Class<? extends StorageHookFactory<S, L, ? extends StorageHook<S, L>>> factoryClass) {
+ this.generation = generation;
+ this.factoryClass = factoryClass;
+ }
+
+ public Generation getGeneration() {
+ return generation;
+ }
+
+ /**
+ * Initializes this storage hook with the content of the specified bundle manifest.
+ * This method is called when a bundle is installed or updated.
+ * @param manifest the bundle manifest to load into this storage hook
+ * @throws BundleException if any error occurs
+ */
+ public abstract void initialize(Dictionary<String, String> manifest) throws BundleException;
+
+ /**
+ * Loads the data from the specified
+ * input stream into the storage hook. This method is called during startup to
+ * load all the persistently installed bundles. <p>
+ * It is important that this method and the {@link #save(Object, DataOutputStream)} method
+ * stay in sync. This method must be able to successfully read the data saved by the
+ * {@link #save(Object, DataOutputStream)} method.
+ * @param is an input stream used to load the storage hook's data from.
+ * @see #save(Object, DataOutputStream)
+ * @throws IOException if any error occurs
+ */
+ public abstract void load(L loadContext, DataInputStream is) throws IOException;
+
+ /**
+ * Saves the data from this storage hook into the specified output stream. This method
+ * is called if some persistent data has changed for the bundle. <p>
+ * It is important that this method and the {@link #load(Object, DataInputStream)}
+ * method stay in sync. This method must be able to save data which the
+ * {@link #load(Object, DataInputStream)} method can ready successfully.
+ * @see #load(Object, DataInputStream)
+ * @param os an output stream used to save the storage hook's data from.
+ * @throws IOException if any error occurs
+ */
+ public abstract void save(S saveContext, DataOutputStream os) throws IOException;
+
+ /**
+ * Validates the data in this storage hook, if the data is invalid then an illegal state
+ * exception is thrown
+ * @throws IllegalArgumentException if the data is invalid
+ */
+ public void validate() throws IllegalArgumentException {
+ // do nothing by default
+ }
+
+ public Class<? extends StorageHookFactory<S, L, ? extends StorageHook<S, L>>> getFactoryClass() {
+ return factoryClass;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassLoadingHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java
index a3ff4dab8..d936f4ef6 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassLoadingHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,33 +9,32 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor;
+package org.eclipse.osgi.internal.hooks;
import java.io.File;
-import java.security.ProtectionDomain;
import java.util.ArrayList;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
import org.eclipse.osgi.framework.util.KeyedElement;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
+import org.eclipse.osgi.internal.loader.classpath.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
-public class DevClassLoadingHook implements ClassLoadingHook, HookConfigurator, KeyedElement {
+public class DevClassLoadingHook extends ClassLoaderHook implements KeyedElement {
public static final String KEY = DevClassLoadingHook.class.getName();
public static final int HASHCODE = KEY.hashCode();
private static final String FRAGMENT = "@fragment@"; //$NON-NLS-1$
- public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- // Do nothing
- return null;
+ private final EquinoxConfiguration configuration;
+
+ public DevClassLoadingHook(EquinoxConfiguration configuration) {
+ this.configuration = configuration;
}
- public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) {
+ @Override
+ public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, Generation sourceGeneration) {
// first check that we are in devmode for this sourcedata
- String[] devClassPath = !DevClassPathHelper.inDevelopmentMode() ? null : DevClassPathHelper.getDevClassPath(sourcedata.getSymbolicName());
+ String[] devClassPath = !configuration.inDevelopmentMode() ? null : configuration.getDevClassPath(sourceGeneration.getRevision().getSymbolicName());
if (devClassPath == null || devClassPath.length == 0)
return false; // not in dev mode return
// check that dev classpath entries have not already been added; we mark this in the first entry below
@@ -43,17 +42,17 @@ public class DevClassLoadingHook implements ClassLoadingHook, HookConfigurator,
return false; // this source has already had its dev classpath entries added.
boolean result = false;
for (int i = 0; i < devClassPath.length; i++) {
- if (ClasspathManager.addClassPathEntry(cpEntries, devClassPath[i], hostmanager, sourcedata, sourcedomain))
+ if (hostmanager.addClassPathEntry(cpEntries, devClassPath[i], hostmanager, sourceGeneration))
result = true;
else {
String devCP = devClassPath[i];
boolean fromFragment = devCP.endsWith(FRAGMENT);
if (!fromFragment && devCP.indexOf("..") >= 0) { //$NON-NLS-1$
// if in dev mode, try using cp as a relative path from the base bundle file
- File base = sourcedata.getBundleFile().getBaseFile();
+ File base = sourceGeneration.getBundleFile().getBaseFile();
if (base.isDirectory()) {
// this is only supported for directory bundles
- ClasspathEntry entry = hostmanager.getExternalClassPath(new File(base, devCP).getAbsolutePath(), sourcedata, sourcedomain);
+ ClasspathEntry entry = hostmanager.getExternalClassPath(new File(base, devCP).getAbsolutePath(), sourceGeneration);
if (entry != null) {
cpEntries.add(entry);
result = true;
@@ -64,9 +63,9 @@ public class DevClassLoadingHook implements ClassLoadingHook, HookConfigurator,
// we assume absolute entries come from fragments. Find the source
if (fromFragment)
devCP = devCP.substring(0, devCP.length() - FRAGMENT.length());
- BaseData fragData = findFragmentSource(sourcedata, devCP, hostmanager, fromFragment);
- if (fragData != null) {
- ClasspathEntry entry = hostmanager.getExternalClassPath(devCP, fragData, sourcedomain);
+ Generation fragSource = findFragmentSource(sourceGeneration, devCP, hostmanager, fromFragment);
+ if (fragSource != null) {
+ ClasspathEntry entry = hostmanager.getExternalClassPath(devCP, fragSource);
if (entry != null) {
cpEntries.add(entry);
result = true;
@@ -82,47 +81,21 @@ public class DevClassLoadingHook implements ClassLoadingHook, HookConfigurator,
return result;
}
- private BaseData findFragmentSource(BaseData hostData, String cp, ClasspathManager manager, boolean fromFragment) {
- if (hostData != manager.getBaseData())
- return hostData;
+ private Generation findFragmentSource(Generation hostGeneration, String cp, ClasspathManager manager, boolean fromFragment) {
+ if (hostGeneration != manager.getGeneration())
+ return hostGeneration;
File file = new File(cp);
if (!file.isAbsolute())
- return hostData;
+ return hostGeneration;
FragmentClasspath[] fragCP = manager.getFragmentClasspaths();
for (int i = 0; i < fragCP.length; i++) {
- BundleFile fragBase = fragCP[i].getBundleData().getBundleFile();
+ BundleFile fragBase = fragCP[i].getGeneration().getBundleFile();
File fragFile = fragBase.getBaseFile();
if (fragFile != null && file.getPath().startsWith(fragFile.getPath()))
- return fragCP[i].getBundleData();
+ return fragCP[i].getGeneration();
}
- return fromFragment ? null : hostData;
- }
-
- public String findLibrary(BaseData data, String libName) {
- // Do nothing
- return null;
- }
-
- public ClassLoader getBundleClassLoaderParent() {
- // Do nothing
- return null;
- }
-
- public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) {
- // do nothing
- return null;
- }
-
- public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
- // do nothing
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- if (DevClassPathHelper.inDevelopmentMode())
- // only add dev classpath manager if in dev mode
- hookRegistry.addClassLoadingHook(new DevClassLoadingHook());
-
+ return fromFragment ? null : hostGeneration;
}
public boolean compare(KeyedElement other) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java
new file mode 100644
index 000000000..89933627e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.hooks;
+
+import java.util.*;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.Module.StartOptions;
+import org.eclipse.osgi.container.Module.State;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
+import org.eclipse.osgi.internal.location.EclipseAdaptorMsg;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.*;
+
+public class EclipseLazyStarter extends ClassLoaderHook {
+ private static final EnumSet<State> alreadyActive = EnumSet.of(State.ACTIVE, State.STOPPING, State.UNINSTALLED);
+ // holds the current activation trigger class and the ClasspathManagers that need to be activated
+ private final ThreadLocal<List<Object>> activationStack = new ThreadLocal<List<Object>>();
+ // used to store exceptions that occurred while activating a bundle
+ // keyed by ClasspathManager->Exception
+ // WeakHashMap is used to prevent pinning the ClasspathManager objects.
+ private final Map<ClasspathManager, ClassNotFoundException> errors = Collections.synchronizedMap(new WeakHashMap<ClasspathManager, ClassNotFoundException>());
+
+ private final EquinoxContainer container;
+
+ public EclipseLazyStarter(EquinoxContainer container) {
+ this.container = container;
+ }
+
+ @Override
+ public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
+ ModuleRevision revision = manager.getGeneration().getRevision();
+ Module module = revision.getRevisions().getModule();
+ // If the bundle is active, uninstalled or stopping then the bundle has already
+ // been initialized (though it may have been destroyed) so just return the class.
+ if (alreadyActive.contains(module.getState()))
+ return;
+ // The bundle is not active and does not require activation, just return the class
+ if (!shouldActivateFor(name, module, revision, manager))
+ return;
+ List<Object> stack = activationStack.get();
+ if (stack == null) {
+ stack = new ArrayList<Object>(6);
+ activationStack.set(stack);
+ }
+ // the first element in the stack is the name of the trigger class,
+ // each element after the trigger class is a classpath manager
+ // that must be activated after the trigger class has been defined (see postFindLocalClass)
+ int size = stack.size();
+ if (size > 1) {
+ for (int i = size - 1; i >= 1; i--)
+ if (manager == stack.get(i))
+ // the manager is already on the stack in which case we are already in the process of loading the trigger class
+ return;
+ }
+ if (size == 0)
+ stack.add(name);
+ stack.add(manager);
+ }
+
+ @Override
+ public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) throws ClassNotFoundException {
+ List<Object> stack = activationStack.get();
+ if (stack == null)
+ return;
+ int size = stack.size();
+ if (size <= 1 || stack.get(0) != name)
+ return;
+ // if we have a stack we must clear it even if (clazz == null)
+ ClasspathManager[] managers = null;
+ managers = new ClasspathManager[size - 1];
+ for (int i = 1; i < size; i++)
+ managers[i - 1] = (ClasspathManager) stack.get(i);
+ stack.clear();
+ if (clazz == null)
+ return;
+ for (int i = managers.length - 1; i >= 0; i--) {
+ if (errors.get(managers[i]) != null) {
+ if (container.getConfiguration().throwErrorOnFailedStart)
+ throw errors.get(managers[i]);
+ continue;
+ }
+
+ // The bundle must be started.
+ // Note that another thread may already be starting this bundle;
+ // In this case we will timeout after a default of 5 seconds and record the BundleException
+ long startTime = System.currentTimeMillis();
+ try {
+ // do not persist the start of this bundle
+ managers[i].getGeneration().getRevision().getRevisions().getModule().start(StartOptions.LAZY_TRIGGER);
+ } catch (BundleException e) {
+ Bundle bundle = managers[i].getGeneration().getRevision().getBundle();
+ if (e.getType() == BundleException.STATECHANGE_ERROR) {
+ String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object[] {Thread.currentThread(), name, null, bundle, new Long(System.currentTimeMillis() - startTime)});
+ container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, message, e);
+ continue;
+ }
+ String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_ACTIVATION, bundle.getSymbolicName(), Long.toString(bundle.getBundleId()));
+ ClassNotFoundException error = new ClassNotFoundException(message, e);
+ errors.put(managers[i], error);
+ if (container.getConfiguration().throwErrorOnFailedStart) {
+ container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, message, e, null);
+ throw error;
+ }
+ container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, new BundleException(message, e));
+ }
+ }
+ }
+
+ private boolean shouldActivateFor(String className, Module module, ModuleRevision revision, ClasspathManager manager) throws ClassNotFoundException {
+ if (!State.LAZY_STARTING.equals(module.getState())) {
+ // Don't activate non-starting bundles
+ if (State.RESOLVED.equals(module.getState())) {
+ // handle the resolved case where a previous error occurred
+ if (container.getConfiguration().throwErrorOnFailedStart) {
+ ClassNotFoundException error = errors.get(manager);
+ if (error != null)
+ throw error;
+ }
+ return module.isPersistentlyStarted() && module.isActivationPolicyUsed() && isLazyStartable(className, revision);
+ }
+ return false;
+ }
+
+ return isLazyStartable(className, revision);
+ }
+
+ private boolean isLazyStartable(String className, ModuleRevision revision) {
+ List<ModuleCapability> moduleDatas = revision.getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ if (moduleDatas.isEmpty()) {
+ return false;
+ }
+
+ Map<String, Object> moduleDataAttrs = moduleDatas.get(0).getAttributes();
+ String policy = (String) moduleDataAttrs.get(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY);
+ if (!EquinoxModuleDataNamespace.CAPABILITY_ACTIVATION_POLICY_LAZY.equals(policy)) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ List<String> excludes = (List<String>) moduleDataAttrs.get(EquinoxModuleDataNamespace.CAPABILITY_LAZY_EXCLUDE_ATTRIBUTE);
+ @SuppressWarnings("unchecked")
+ List<String> includes = (List<String>) moduleDataAttrs.get(EquinoxModuleDataNamespace.CAPABILITY_LAZY_INCLUDE_ATTRIBUTE);
+ // no exceptions, it is easy to figure it out
+ if (excludes == null && includes == null)
+ return true;
+ // otherwise, we need to check if the package is in the exceptions list
+ int dotPosition = className.lastIndexOf('.');
+ // the class has no package name... no exceptions apply
+ if (dotPosition == -1)
+ return true;
+ String packageName = className.substring(0, dotPosition);
+ return ((includes == null || includes.contains(packageName)) && (excludes == null || !excludes.contains(packageName)));
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
index f972160de..1f62b190b 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoader.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
@@ -17,41 +17,43 @@ import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.builders.OSGiManifestBuilderFactory;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.util.KeyedElement;
import org.eclipse.osgi.framework.util.KeyedHashSet;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.loader.buddy.PolicyHandler;
-import org.eclipse.osgi.internal.resolver.StateBuilder;
-import org.eclipse.osgi.service.resolver.*;
+import org.eclipse.osgi.internal.loader.sources.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.service.resolver.ResolutionException;
/**
* This object is responsible for all classloader delegation for a bundle.
* It represents the loaded state of the bundle. BundleLoader objects
* are created lazily; care should be taken not to force the creation
* of a BundleLoader unless it is necessary.
- * @see org.eclipse.osgi.internal.loader.BundleLoaderProxy
+ * @see org.eclipse.osgi.internal.loader.BundleLoaderSources
*/
-public class BundleLoader implements ClassLoaderDelegate {
+public class BundleLoader implements ModuleLoader {
public final static String DEFAULT_PACKAGE = "."; //$NON-NLS-1$
public final static String JAVA_PACKAGE = "java."; //$NON-NLS-1$
- public final static byte FLAG_IMPORTSINIT = 0x01;
- public final static byte FLAG_HASDYNAMICIMPORTS = 0x02;
- public final static byte FLAG_HASDYNAMICEIMPORTALL = 0x04;
- public final static byte FLAG_CLOSED = 0x08;
- public final static byte FLAG_LAZYTRIGGER = 0x10;
public final static ClassContext CLASS_CONTEXT = AccessController.doPrivileged(new PrivilegedAction<ClassContext>() {
public ClassContext run() {
return new ClassContext();
}
});
- public final static ClassLoader FW_CLASSLOADER = getClassLoader(Framework.class);
+ public final static ClassLoader FW_CLASSLOADER = getClassLoader(EquinoxContainer.class);
private static final int PRE_CLASS = 1;
private static final int POST_CLASS = 2;
@@ -59,36 +61,38 @@ public class BundleLoader implements ClassLoaderDelegate {
private static final int POST_RESOURCE = 4;
private static final int PRE_RESOURCES = 5;
private static final int POST_RESOURCES = 6;
- private static final int PRE_LIBRARY = 7;
- private static final int POST_LIBRARY = 8;
-
- /* the proxy */
- final private BundleLoaderProxy proxy;
- /* Bundle object */
- final BundleHost bundle;
- final private PolicyHandler policy;
+
+ private static final Pattern PACKAGENAME_FILTER = Pattern.compile("\\(osgi.wiring.package\\s*=\\s*([^)]+)\\)"); //$NON-NLS-1$
+
+ private final ModuleWiring wiring;
+ private final EquinoxContainer container;
+ private final Debug debug;
+ private final PolicyHandler policy;
+
/* List of package names that are exported by this BundleLoader */
- final private Collection<String> exportedPackages;
- final private Collection<String> substitutedPackages;
- /* List of required bundle BundleLoaderProxy objects */
- final BundleLoaderProxy[] requiredBundles;
- /* List of indexes into the requiredBundles list of reexported bundles */
- final int[] reexportTable;
- /* cache of required package sources. Key is packagename, value is PackageSource */
- final private KeyedHashSet requiredSources;
+ private final Collection<String> exportedPackages;
+ private final BundleLoaderSources exportSources;
- // note that the following non-final must be access using synchronization
+ /* cache of required package sources. Key is packagename, value is PackageSource */
+ private final KeyedHashSet requiredSources = new KeyedHashSet(false);
/* cache of imported packages. Key is packagename, Value is PackageSource */
- private KeyedHashSet importedSources;
+ private final KeyedHashSet importedSources = new KeyedHashSet(false);
+
+ /* @GuardedBy("importedSources") */
+ private boolean importsInitialized = false;
+ /* @GuardedBy("importedSources") */
+ private boolean dynamicAllPackages;
/* If not null, list of package stems to import dynamically. */
+ /* @GuardedBy("importedSources") */
private String[] dynamicImportPackageStems;
+ /* @GuardedBy("importedSources") */
/* If not null, list of package names to import dynamically. */
private String[] dynamicImportPackages;
- /* loader flags */
- private byte loaderFlags = 0;
- /* The is the BundleClassLoader for the bundle */
- private BundleClassLoader classloader;
- private ClassLoader parent;
+
+ private Object classLoaderMonitor = new Object();
+ /* @GuardedBy("classLoaderMonitor") */
+ private ModuleClassLoader classloader;
+ private final ClassLoader parent;
/**
* Returns the package name from the specified class name.
@@ -126,153 +130,60 @@ public class BundleLoader implements ClassLoaderDelegate {
return DEFAULT_PACKAGE;
}
- /**
- * BundleLoader runtime constructor. This object is created lazily
- * when the first request for a resource is made to this bundle.
- *
- * @param bundle Bundle object for this loader.
- * @param proxy the BundleLoaderProxy for this loader.
- * @exception org.osgi.framework.BundleException
- */
- protected BundleLoader(BundleHost bundle, BundleLoaderProxy proxy) throws BundleException {
- this.bundle = bundle;
- this.proxy = proxy;
- try {
- bundle.getBundleData().open(); /* make sure the BundleData is open */
- } catch (IOException e) {
- throw new BundleException(Msg.BUNDLE_READ_EXCEPTION, e);
- }
- BundleDescription description = proxy.getBundleDescription();
- // init the require bundles list.
- BundleDescription[] required = description.getResolvedRequires();
- if (required.length > 0) {
- // get a list of re-exported symbolic names
- Set<String> reExportSet = new HashSet<String>(required.length);
- BundleSpecification[] requiredSpecs = description.getRequiredBundles();
- if (requiredSpecs != null && requiredSpecs.length > 0)
- for (int i = 0; i < requiredSpecs.length; i++)
- if (requiredSpecs[i].isExported())
- reExportSet.add(requiredSpecs[i].getName());
-
- requiredBundles = new BundleLoaderProxy[required.length];
- int[] reexported = new int[required.length];
- int reexportIndex = 0;
- for (int i = 0; i < required.length; i++) {
- requiredBundles[i] = getLoaderProxy(required[i]);
- if (reExportSet.contains(required[i].getSymbolicName()))
- reexported[reexportIndex++] = i;
- }
- if (reexportIndex > 0) {
- reexportTable = new int[reexportIndex];
- System.arraycopy(reexported, 0, reexportTable, 0, reexportIndex);
- } else {
- reexportTable = null;
- }
- requiredSources = new KeyedHashSet(10, false);
- } else {
- requiredBundles = null;
- reexportTable = null;
- requiredSources = null;
- }
+ public BundleLoader(ModuleWiring wiring, EquinoxContainer container, ClassLoader parent) {
+ this.wiring = wiring;
+ this.container = container;
+ this.debug = container.getConfiguration().getDebug();
+ this.parent = parent;
// init the provided packages set
- ExportPackageDescription[] exports = description.getSelectedExports();
- if (exports != null && exports.length > 0) {
- exportedPackages = Collections.synchronizedCollection(exports.length > 10 ? new HashSet<String>(exports.length) : new ArrayList<String>(exports.length));
- initializeExports(exports, exportedPackages);
- } else {
- exportedPackages = Collections.synchronizedCollection(new ArrayList<String>(0));
- }
+ exportSources = new BundleLoaderSources(this);
+ List<ModuleCapability> exports = wiring.getModuleCapabilities(PackageNamespace.PACKAGE_NAMESPACE);
+ exportedPackages = Collections.synchronizedCollection(exports.size() > 10 ? new HashSet<String>(exports.size()) : new ArrayList<String>(exports.size()));
+ initializeExports(exports, exportSources, exportedPackages);
- ExportPackageDescription substituted[] = description.getSubstitutedExports();
- if (substituted.length > 0) {
- substitutedPackages = substituted.length > 10 ? new HashSet<String>(substituted.length) : new ArrayList<String>(substituted.length);
- for (int i = 0; i < substituted.length; i++)
- substitutedPackages.add(substituted[i].getName());
- } else {
- substitutedPackages = null;
- }
-
- //This is the fastest way to access to the description for fragments since the hostdescription.getFragments() is slow
- BundleFragment[] fragmentObjects = bundle.getFragments();
- BundleDescription[] fragments = new BundleDescription[fragmentObjects == null ? 0 : fragmentObjects.length];
- for (int i = 0; i < fragments.length; i++)
- fragments[i] = fragmentObjects[i].getBundleDescription();
// init the dynamic imports tables
- if (description.hasDynamicImports())
- addDynamicImportPackage(description.getImportPackages());
- // ...and its fragments
- for (int i = 0; i < fragments.length; i++)
- if (fragments[i].isResolved() && fragments[i].hasDynamicImports())
- addDynamicImportPackage(fragments[i].getImportPackages());
+ addDynamicImportPackage(wiring.getModuleRequirements(PackageNamespace.PACKAGE_NAMESPACE));
//Initialize the policy handler
- String buddyList = null;
- try {
- buddyList = bundle.getBundleData().getManifest().get(Constants.BUDDY_LOADER);
- } catch (BundleException e) {
- // do nothing; buddyList == null
+ List<ModuleCapability> moduleDatas = wiring.getRevision().getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ @SuppressWarnings("unchecked")
+ List<String> buddyList = (List<String>) (moduleDatas.isEmpty() ? null : moduleDatas.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_BUDDY_POLICY));
+ policy = buddyList != null ? new PolicyHandler(this, buddyList, container.getPackageAdmin()) : null;
+ if (policy != null) {
+ Module systemModule = container.getStorage().getModuleContainer().getModule(0);
+ Bundle systemBundle = systemModule.getBundle();
+ policy.open(systemBundle.getBundleContext());
}
- policy = buddyList != null ? new PolicyHandler(this, buddyList, bundle.getFramework().getPackageAdmin()) : null;
- if (policy != null)
- policy.open(bundle.getFramework().getSystemBundleContext());
}
- private void initializeExports(ExportPackageDescription[] exports, Collection<String> exportNames) {
- for (int i = 0; i < exports.length; i++) {
- if (proxy.forceSourceCreation(exports[i])) {
- if (!exportNames.contains(exports[i].getName())) {
+ public ModuleWiring getWiring() {
+ return wiring;
+ }
+
+ private static void initializeExports(List<ModuleCapability> exports, BundleLoaderSources sources, Collection<String> exportNames) {
+ for (ModuleCapability export : exports) {
+ String name = (String) export.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ if (sources.forceSourceCreation(export)) {
+ if (!exportNames.contains(name)) {
// must force filtered and reexport sources to be created early
// to prevent lazy normal package source creation.
// We only do this for the first export of a package name.
- proxy.createPackageSource(exports[i], true);
+ sources.createPackageSource(export, true);
}
}
- exportNames.add(exports[i].getName());
- }
- }
-
- public synchronized KeyedHashSet getImportedSources(KeyedHashSet visited) {
- if ((loaderFlags & FLAG_IMPORTSINIT) != 0)
- return importedSources;
- BundleDescription bundleDesc = proxy.getBundleDescription();
- ExportPackageDescription[] packages = bundleDesc.getResolvedImports();
- if (packages != null && packages.length > 0) {
- if (importedSources == null)
- importedSources = new KeyedHashSet(packages.length, false);
- for (int i = 0; i < packages.length; i++) {
- if (packages[i].getExporter() == bundleDesc)
- continue; // ignore imports resolved to this bundle
- PackageSource source = createExportPackageSource(packages[i], visited);
- if (source != null)
- importedSources.add(source);
- }
- }
- loaderFlags |= FLAG_IMPORTSINIT;
- return importedSources;
- }
-
- public synchronized boolean isLazyTriggerSet() {
- return (loaderFlags & FLAG_LAZYTRIGGER) != 0;
- }
-
- public void setLazyTrigger() throws BundleException {
- synchronized (this) {
- loaderFlags |= FLAG_LAZYTRIGGER;
+ exportNames.add(name);
}
- BundleLoaderProxy.secureAction.start(bundle, Bundle.START_TRANSIENT | BundleHost.LAZY_TRIGGER);
}
- final PackageSource createExportPackageSource(ExportPackageDescription export, KeyedHashSet visited) {
- BundleLoaderProxy exportProxy = getLoaderProxy(export.getExporter());
- if (exportProxy == null)
- // TODO log error!!
- return null;
- PackageSource requiredSource = exportProxy.getBundleLoader().findRequiredSource(export.getName(), visited);
- PackageSource exportSource = exportProxy.createPackageSource(export, false);
+ final PackageSource createExportPackageSource(ModuleWire importWire, Collection<BundleLoader> visited) {
+ BundleLoader providerLoader = (BundleLoader) importWire.getProviderWiring().getModuleLoader();
+ String name = (String) importWire.getCapability().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ PackageSource requiredSource = providerLoader.findRequiredSource(name, visited);
+ PackageSource exportSource = providerLoader.exportSources.createPackageSource(importWire.getCapability(), false);
if (requiredSource == null)
return exportSource;
- return createMultiSource(export.getName(), new PackageSource[] {requiredSource, exportSource});
+ return createMultiSource(name, new PackageSource[] {requiredSource, exportSource});
}
private static PackageSource createMultiSource(String packageName, PackageSource[] sources) {
@@ -288,38 +199,41 @@ public class BundleLoader implements ClassLoaderDelegate {
return new MultiSourcePackage(packageName, sourceList.toArray(new SingleSourcePackage[sourceList.size()]));
}
- /*
- * get the loader proxy for a bundle description
- */
- public final BundleLoaderProxy getLoaderProxy(BundleDescription source) {
- Object userObject = source.getUserObject();
- if (!(userObject instanceof BundleLoaderProxy)) {
- // may need to force the proxy to be created
- long exportingID = source.getBundleId();
- BundleHost exportingBundle = (BundleHost) bundle.getFramework().getBundle(exportingID);
- if (exportingBundle == null)
- return null;
- userObject = exportingBundle.getLoaderProxy();
+ public ModuleClassLoader getModuleClassLoader() {
+ synchronized (classLoaderMonitor) {
+ if (classloader == null) {
+ final Generation generation = (Generation) wiring.getRevision().getRevisionInfo();
+ if (System.getSecurityManager() == null) {
+ classloader = new ModuleClassLoader(parent, generation.getBundleInfo().getStorage().getConfiguration(), this, generation);
+ } else {
+ classloader = AccessController.doPrivileged(new PrivilegedAction<ModuleClassLoader>() {
+ @Override
+ public ModuleClassLoader run() {
+ return new ModuleClassLoader(parent, generation.getBundleInfo().getStorage().getConfiguration(), BundleLoader.this, generation);
+ }
+ });
+ }
+ }
+ return classloader;
}
- return (BundleLoaderProxy) userObject;
}
- public BundleLoaderProxy getLoaderProxy() {
- return proxy;
+ public void close() {
+ synchronized (classLoaderMonitor) {
+ if (classloader != null) {
+ classloader.getClasspathManager().close();
+ classloader = null;
+ }
+ }
}
- /*
- * Close the the BundleLoader.
- *
- */
- synchronized void close() {
- if ((loaderFlags & FLAG_CLOSED) != 0)
- return;
- if (classloader != null)
- classloader.close();
- if (policy != null)
- policy.close(bundle.getFramework().getSystemBundleContext());
- loaderFlags |= FLAG_CLOSED; /* This indicates the BundleLoader is destroyed */
+ @Override
+ public ClassLoader getClassLoader() {
+ return getModuleClassLoader();
+ }
+
+ public ClassLoader getParentClassLoader() {
+ return this.parent;
}
/**
@@ -332,12 +246,12 @@ public class BundleLoader implements ClassLoaderDelegate {
* @exception java.lang.ClassNotFoundException if the class definition was not found.
*/
final public Class<?> loadClass(String name) throws ClassNotFoundException {
- BundleClassLoader bcl = createClassLoader();
+ ModuleClassLoader mcl = getModuleClassLoader();
// The instanceof check here is just to be safe. The javadoc contract stated in BundleClassLoader
// mandate that BundleClassLoaders be an instance of ClassLoader.
- if (name.length() > 0 && name.charAt(0) == '[' && bcl instanceof ClassLoader)
- return Class.forName(name, false, (ClassLoader) bcl);
- return bcl.loadClass(name);
+ if (name.length() > 0 && name.charAt(0) == '[')
+ return Class.forName(name, false, mcl);
+ return mcl.loadClass(name);
}
/**
@@ -350,36 +264,7 @@ public class BundleLoader implements ClassLoaderDelegate {
* @return the resulting resource URL or null if it does not exist.
*/
final URL getResource(String name) {
- return createClassLoader().getResource(name);
- }
-
- public final synchronized ClassLoader getParentClassLoader() {
- if (parent != null)
- return parent;
- createClassLoader();
- return parent;
- }
-
- final public synchronized BundleClassLoader createClassLoader() {
- if (classloader != null)
- return classloader;
- String[] classpath;
- try {
- classpath = bundle.getBundleData().getClassPath();
- } catch (BundleException e) {
- // no classpath
- classpath = new String[0];
- bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
- }
- if (classpath == null) {
- // no classpath
- classpath = new String[0];
- bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, new BundleException(Msg.BUNDLE_NO_CLASSPATH_MATCH, BundleException.MANIFEST_ERROR));
- }
- BundleClassLoader bcl = createBCLPrevileged(bundle.getProtectionDomain(), classpath);
- parent = getParentPrivileged(bcl);
- classloader = bcl;
- return classloader;
+ return getModuleClassLoader().getResource(name);
}
/**
@@ -388,18 +273,18 @@ public class BundleLoader implements ClassLoaderDelegate {
* @return The loaded Class or null if the class is not found.
* @throws ClassNotFoundException
*/
- Class<?> findLocalClass(String name) throws ClassNotFoundException {
- if (Debug.DEBUG_LOADER)
+ public Class<?> findLocalClass(String name) throws ClassNotFoundException {
+ if (debug.DEBUG_LOADER)
Debug.println("BundleLoader[" + this + "].findLocalClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
try {
- Class<?> clazz = createClassLoader().findLocalClass(name);
- if (Debug.DEBUG_LOADER && clazz != null)
+ Class<?> clazz = getModuleClassLoader().findLocalClass(name);
+ if (debug.DEBUG_LOADER && clazz != null)
Debug.println("BundleLoader[" + this + "] found local class " + name); //$NON-NLS-1$ //$NON-NLS-2$
return clazz;
} catch (ClassNotFoundException e) {
- if (e instanceof StatusException) {
- if ((((StatusException) e).getStatusCode() & StatusException.CODE_ERROR) != 0)
- throw e;
+ if (e.getCause() instanceof BundleException) {
+ // Here we assume this is because of a lazy activation error
+ throw e;
}
return null;
}
@@ -413,24 +298,23 @@ public class BundleLoader implements ClassLoaderDelegate {
}
Class<?> findClass(String name, boolean checkParent) throws ClassNotFoundException {
- ClassLoader parentCL = getParentClassLoader();
- if (checkParent && parentCL != null && name.startsWith(JAVA_PACKAGE))
+ if (checkParent && parent != null && name.startsWith(JAVA_PACKAGE))
// 1) if startsWith "java." delegate to parent and terminate search
// we want to throw ClassNotFoundExceptions if a java.* class cannot be loaded from the parent.
- return parentCL.loadClass(name);
- return findClassInternal(name, checkParent, parentCL);
+ return parent.loadClass(name);
+ return findClassInternal(name, checkParent);
}
- private Class<?> findClassInternal(String name, boolean checkParent, ClassLoader parentCL) throws ClassNotFoundException {
- if (Debug.DEBUG_LOADER)
+ private Class<?> findClassInternal(String name, boolean checkParent) throws ClassNotFoundException {
+ if (debug.DEBUG_LOADER)
Debug.println("BundleLoader[" + this + "].loadBundleClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String pkgName = getPackageName(name);
boolean bootDelegation = false;
// follow the OSGi delegation model
- if (checkParent && parentCL != null && bundle.getFramework().isBootDelegationPackage(pkgName))
+ if (checkParent && parent != null && container.isBootDelegationPackage(pkgName))
// 2) if part of the bootdelegation list then delegate to parent and continue of failure
try {
- return parentCL.loadClass(name);
+ return parent.loadClass(name);
} catch (ClassNotFoundException cnfe) {
// we want to continue
bootDelegation = true;
@@ -491,10 +375,10 @@ public class BundleLoader implements ClassLoaderDelegate {
return result;
// hack to support backwards compatibiility for bootdelegation
// or last resort; do class context trick to work around VM bugs
- if (parentCL != null && !bootDelegation && ((checkParent && bundle.getFramework().compatibiltyBootDelegation) || isRequestFromVM()))
+ if (parent != null && !bootDelegation && ((checkParent && container.getConfiguration().compatibiltyBootDelegation) || isRequestFromVM()))
// we don't need to continue if a CNFE is thrown here.
try {
- return parentCL.loadClass(name);
+ return parent.loadClass(name);
} catch (ClassNotFoundException e) {
// we want to generate our own exception below
}
@@ -503,35 +387,30 @@ public class BundleLoader implements ClassLoaderDelegate {
@SuppressWarnings("unchecked")
private <E> E searchHooks(String name, int type) throws ClassNotFoundException, FileNotFoundException {
- ClassLoaderDelegateHook[] delegateHooks = bundle.getFramework().getDelegateHooks();
- if (delegateHooks == null)
+
+ List<ClassLoaderHook> loaderHooks = container.getConfiguration().getHookRegistry().getClassLoaderHooks();
+ if (loaderHooks == null)
return null;
E result = null;
- for (int i = 0; i < delegateHooks.length && result == null; i++) {
+ for (ClassLoaderHook hook : loaderHooks) {
switch (type) {
case PRE_CLASS :
- result = (E) delegateHooks[i].preFindClass(name, createClassLoader(), bundle.getBundleData());
+ result = (E) hook.preFindClass(name, getModuleClassLoader());
break;
case POST_CLASS :
- result = (E) delegateHooks[i].postFindClass(name, createClassLoader(), bundle.getBundleData());
+ result = (E) hook.postFindClass(name, getModuleClassLoader());
break;
case PRE_RESOURCE :
- result = (E) delegateHooks[i].preFindResource(name, createClassLoader(), bundle.getBundleData());
+ result = (E) hook.preFindResource(name, getModuleClassLoader());
break;
case POST_RESOURCE :
- result = (E) delegateHooks[i].postFindResource(name, createClassLoader(), bundle.getBundleData());
+ result = (E) hook.postFindResource(name, getModuleClassLoader());
break;
case PRE_RESOURCES :
- result = (E) delegateHooks[i].preFindResources(name, createClassLoader(), bundle.getBundleData());
+ result = (E) hook.preFindResources(name, getModuleClassLoader());
break;
case POST_RESOURCES :
- result = (E) delegateHooks[i].postFindResources(name, createClassLoader(), bundle.getBundleData());
- break;
- case PRE_LIBRARY :
- result = (E) delegateHooks[i].preFindLibrary(name, createClassLoader(), bundle.getBundleData());
- break;
- case POST_LIBRARY :
- result = (E) delegateHooks[i].postFindLibrary(name, createClassLoader(), bundle.getBundleData());
+ result = (E) hook.postFindResources(name, getModuleClassLoader());
break;
}
}
@@ -539,7 +418,7 @@ public class BundleLoader implements ClassLoaderDelegate {
}
private boolean isRequestFromVM() {
- if (bundle.getFramework().isBootDelegationPackage("*") || !bundle.getFramework().contextBootDelegation) //$NON-NLS-1$
+ if (!container.getConfiguration().contextBootDelegation)
return false;
// works around VM bugs that require all classloaders to have access to parent packages
Class<?>[] context = CLASS_CONTEXT.getClassContext();
@@ -552,7 +431,7 @@ public class BundleLoader implements ClassLoaderDelegate {
// only find in parent if the class is not "Class" (Class#forName case) or if the class is not loaded with a BundleClassLoader
ClassLoader cl = getClassLoader(context[i]);
if (cl != FW_CLASSLOADER) { // extra check incase an adaptor adds another class into the stack besides an instance of ClassLoader
- if (Class.class != context[i] && !(cl instanceof BundleClassLoader))
+ if (Class.class != context[i] && !(cl instanceof ModuleClassLoader))
return true;
break;
}
@@ -582,17 +461,16 @@ public class BundleLoader implements ClassLoaderDelegate {
name = name.substring(1); /* remove leading slash before search */
String pkgName = getResourcePackageName(name);
boolean bootDelegation = false;
- ClassLoader parentCL = getParentClassLoader();
// follow the OSGi delegation model
// First check the parent classloader for system resources, if it is a java resource.
- if (checkParent && parentCL != null) {
+ if (checkParent && parent != null) {
if (pkgName.startsWith(JAVA_PACKAGE))
// 1) if startsWith "java." delegate to parent and terminate search
// we never delegate java resource requests past the parent
- return parentCL.getResource(name);
- else if (bundle.getFramework().isBootDelegationPackage(pkgName)) {
+ return parent.getResource(name);
+ else if (container.isBootDelegationPackage(pkgName)) {
// 2) if part of the bootdelegation list then delegate to parent and continue of failure
- URL result = parentCL.getResource(name);
+ URL result = parent.getResource(name);
if (result != null)
return result;
bootDelegation = true;
@@ -647,9 +525,9 @@ public class BundleLoader implements ClassLoaderDelegate {
return result;
// hack to support backwards compatibiility for bootdelegation
// or last resort; do class context trick to work around VM bugs
- if (parentCL != null && !bootDelegation && ((checkParent && bundle.getFramework().compatibiltyBootDelegation) || isRequestFromVM()))
+ if (parent != null && !bootDelegation && ((checkParent && container.getConfiguration().compatibiltyBootDelegation) || isRequestFromVM()))
// we don't need to continue if the resource is not found here
- return parentCL.getResource(name);
+ return parent.getResource(name);
return result;
}
@@ -713,6 +591,7 @@ public class BundleLoader implements ClassLoaderDelegate {
return subPackage.startsWith(prefix);
}
+ @Override
public Collection<String> listResources(String path, String filePattern, int options) {
String pkgName = getResourcePackageName(path.endsWith("/") ? path : path + '/'); //$NON-NLS-1$
if ((path.length() > 1) && (path.charAt(0) == '/')) /* if name has a leading slash */
@@ -731,13 +610,11 @@ public class BundleLoader implements ClassLoaderDelegate {
}
// now add package names from required bundles
- if (requiredBundles != null) {
- KeyedHashSet visited = new KeyedHashSet(false);
- visited.add(bundle); // always add ourselves so we do not recurse back to ourselves
- for (BundleLoaderProxy requiredProxy : requiredBundles) {
- BundleLoader requiredLoader = requiredProxy.getBundleLoader();
- requiredLoader.addProvidedPackageNames(requiredProxy.getSymbolicName(), pkgName, packages, subPackages, visited);
- }
+ Collection<BundleLoader> visited = new ArrayList<BundleLoader>();
+ visited.add(this); // always add ourselves so we do not recurse back to ourselves
+ List<ModuleWire> requireBundles = wiring.getRequiredModuleWires(BundleNamespace.BUNDLE_NAMESPACE);
+ for (ModuleWire bundleWire : requireBundles) {
+ ((BundleLoader) bundleWire.getProviderWiring().getModuleLoader()).addProvidedPackageNames(pkgName, packages, subPackages, visited);
}
boolean localSearch = (options & BundleWiring.LISTRESOURCES_LOCAL) != 0;
@@ -765,7 +642,7 @@ public class BundleLoader implements ClassLoaderDelegate {
}
// now search locally
- Collection<String> localResources = createClassLoader().listLocalResources(path, filePattern, options);
+ Collection<String> localResources = getModuleClassLoader().listLocalResources(path, filePattern, options);
for (String resource : localResources) {
String resourcePkg = getResourcePackageName(resource);
if (!importedPackages.contains(resourcePkg) && !result.contains(resource))
@@ -774,6 +651,11 @@ public class BundleLoader implements ClassLoaderDelegate {
return result;
}
+ @Override
+ public List<URL> findEntries(String path, String filePattern, int options) {
+ return getModuleClassLoader().findEntries(path, filePattern, options);
+ }
+
/*
* This method is used by Bundle.getResources to do proper parent delegation.
*/
@@ -784,11 +666,10 @@ public class BundleLoader implements ClassLoaderDelegate {
// follow the OSGi delegation model
// First check the parent classloader for system resources, if it is a java resource.
Enumeration<URL> result = null;
- if (pkgName.startsWith(JAVA_PACKAGE) || bundle.getFramework().isBootDelegationPackage(pkgName)) {
+ if (pkgName.startsWith(JAVA_PACKAGE) || container.isBootDelegationPackage(pkgName)) {
// 1) if startsWith "java." delegate to parent and terminate search
// 2) if part of the bootdelegation list then delegate to parent and continue of failure
- ClassLoader parentCL = getParentClassLoader();
- result = parentCL == null ? null : parentCL.getResources(name);
+ result = parent == null ? null : parent.getResources(name);
if (pkgName.startsWith(JAVA_PACKAGE))
return result;
}
@@ -816,8 +697,8 @@ public class BundleLoader implements ClassLoaderDelegate {
* @param name The name of the resource to find.
* @return The URL to the resource or null if the resource is not found.
*/
- URL findLocalResource(final String name) {
- return createClassLoader().findLocalResource(name);
+ public URL findLocalResource(final String name) {
+ return getModuleClassLoader().findLocalResource(name);
}
/**
@@ -827,95 +708,8 @@ public class BundleLoader implements ClassLoaderDelegate {
* @param name the resource name
* @return an Enumeration of URLs for the resources
*/
- Enumeration<URL> findLocalResources(String name) {
- return createClassLoader().findLocalResources(name);
- }
-
- /**
- * Returns the absolute path name of a native library.
- *
- * @param name the library name
- * @return the absolute path of the native library or null if not found
- */
- public String findLibrary(final String name) {
- if (System.getSecurityManager() == null)
- return findLocalLibrary(name);
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
- public String run() {
- return findLocalLibrary(name);
- }
- });
- }
-
- final String findLocalLibrary(final String name) {
- String result = null;
- try {
- result = (String) searchHooks(name, PRE_LIBRARY);
- } catch (FileNotFoundException e) {
- return null;
- } catch (ClassNotFoundException e) {
- // will not happen
- }
- if (result != null)
- return result;
- result = bundle.getBundleData().findLibrary(name);
- if (result != null)
- return result;
-
- // look in fragments imports ...
- BundleFragment[] fragments = bundle.getFragments();
- if (fragments != null)
- for (int i = 0; i < fragments.length; i++) {
- result = fragments[i].getBundleData().findLibrary(name);
- if (result != null)
- return result;
- }
- try {
- return (String) searchHooks(name, POST_LIBRARY);
- } catch (FileNotFoundException e) {
- return null; // this is not necessary; but being consistent in case another step is added below
- } catch (ClassNotFoundException e) {
- // will not happen
- }
- return null;
- }
-
- /*
- * Return the bundle we are associated with.
- */
- public final AbstractBundle getBundle() {
- return bundle;
- }
-
- private BundleClassLoader createBCLPrevileged(final BundleProtectionDomain pd, final String[] cp) {
- // Create the classloader as previleged code if security manager is present.
- if (System.getSecurityManager() == null)
- return createBCL(pd, cp);
-
- return AccessController.doPrivileged(new PrivilegedAction<BundleClassLoader>() {
- public BundleClassLoader run() {
- return createBCL(pd, cp);
- }
- });
-
- }
-
- BundleClassLoader createBCL(final BundleProtectionDomain pd, final String[] cp) {
- BundleClassLoader bcl = bundle.getBundleData().createClassLoader(BundleLoader.this, pd, cp);
- // attach existing fragments to classloader
- BundleFragment[] fragments = bundle.getFragments();
- if (fragments != null)
- for (int i = 0; i < fragments.length; i++) {
- try {
- bcl.attachFragment(fragments[i].getBundleData(), fragments[i].getProtectionDomain(), fragments[i].getBundleData().getClassPath());
- } catch (BundleException be) {
- bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be);
- }
- }
-
- // finish the initialization of the classloader.
- bcl.initialize();
- return bcl;
+ public Enumeration<URL> findLocalResources(String name) {
+ return getModuleClassLoader().findLocalResources(name);
}
/**
@@ -923,8 +717,7 @@ public class BundleLoader implements ClassLoaderDelegate {
* @return String
*/
public final String toString() {
- BundleData result = bundle.getBundleData();
- return result == null ? "BundleLoader.bundledata == null!" : result.toString(); //$NON-NLS-1$
+ return wiring.getRevision().toString();
}
/**
@@ -934,113 +727,109 @@ public class BundleLoader implements ClassLoaderDelegate {
* @param pkgname The name of the requested class' package.
* @return true if the package should be imported.
*/
- private final synchronized boolean isDynamicallyImported(String pkgname) {
+ private final boolean isDynamicallyImported(String pkgname) {
if (this instanceof SystemBundleLoader)
return false; // system bundle cannot dynamically import
// must check for startsWith("java.") to satisfy R3 section 4.7.2
if (pkgname.startsWith("java.")) //$NON-NLS-1$
return true;
- /* quick shortcut check */
- if ((loaderFlags & FLAG_HASDYNAMICIMPORTS) == 0)
- return false;
-
- /* "*" shortcut */
- if ((loaderFlags & FLAG_HASDYNAMICEIMPORTALL) != 0)
- return true;
-
- /* match against specific names */
- if (dynamicImportPackages != null)
- for (int i = 0; i < dynamicImportPackages.length; i++)
- if (pkgname.equals(dynamicImportPackages[i]))
- return true;
+ synchronized (importedSources) {
+ /* "*" shortcut */
+ if (dynamicAllPackages)
+ return true;
- /* match against names with trailing wildcards */
- if (dynamicImportPackageStems != null)
- for (int i = 0; i < dynamicImportPackageStems.length; i++)
- if (pkgname.startsWith(dynamicImportPackageStems[i]))
- return true;
+ /* match against specific names */
+ if (dynamicImportPackages != null)
+ for (int i = 0; i < dynamicImportPackages.length; i++)
+ if (pkgname.equals(dynamicImportPackages[i]))
+ return true;
+ /* match against names with trailing wildcards */
+ if (dynamicImportPackageStems != null)
+ for (int i = 0; i < dynamicImportPackageStems.length; i++)
+ if (pkgname.startsWith(dynamicImportPackageStems[i]))
+ return true;
+ }
return false;
}
- final void addExportedProvidersFor(String symbolicName, String packageName, List<PackageSource> result, KeyedHashSet visited) {
- if (!visited.add(bundle))
+ final void addExportedProvidersFor(String packageName, List<PackageSource> result, Collection<BundleLoader> visited) {
+ if (visited.contains(this))
return;
-
+ visited.add(this);
// See if we locally provide the package.
PackageSource local = null;
if (isExportedPackage(packageName))
- local = proxy.getPackageSource(packageName);
+ local = exportSources.getPackageSource(packageName);
else if (isSubstitutedExport(packageName)) {
result.add(findImportedSource(packageName, visited));
return; // should not continue to required bundles in this case
}
// Must search required bundles that are exported first.
- if (requiredBundles != null) {
- int size = reexportTable == null ? 0 : reexportTable.length;
- int reexportIndex = 0;
- for (int i = 0; i < requiredBundles.length; i++) {
- if (local != null) {
- // always add required bundles first if we locally provide the package
- // This allows a bundle to provide a package from a required bundle without
- // re-exporting the whole required bundle.
- requiredBundles[i].getBundleLoader().addExportedProvidersFor(symbolicName, packageName, result, visited);
- } else if (reexportIndex < size && reexportTable[reexportIndex] == i) {
- reexportIndex++;
- requiredBundles[i].getBundleLoader().addExportedProvidersFor(symbolicName, packageName, result, visited);
- }
+ List<ModuleWire> requireBundles = wiring.getRequiredModuleWires(BundleNamespace.BUNDLE_NAMESPACE);
+ for (ModuleWire bundleWire : requireBundles) {
+ if (local != null || BundleNamespace.VISIBILITY_REEXPORT.equals(bundleWire.getRequirement().getDirectives().get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE))) {
+ // always add required bundles first if we locally provide the package
+ // This allows a bundle to provide a package from a required bundle without
+ // re-exporting the whole required bundle.
+ ((BundleLoader) bundleWire.getProviderWiring().getModuleLoader()).addExportedProvidersFor(packageName, result, visited);
}
}
-
// now add the locally provided package.
- if (local != null && local.isFriend(symbolicName))
+ if (local != null)
result.add(local);
}
- final void addProvidedPackageNames(String symbolicName, String packageName, List<String> result, boolean subPackages, KeyedHashSet visitied) {
- if (!visitied.add(bundle))
+ final void addProvidedPackageNames(String packageName, List<String> result, boolean subPackages, Collection<BundleLoader> visited) {
+ if (visited.contains(this))
return;
+ visited.add(this);
for (String exported : exportedPackages) {
if (exported.equals(packageName) || (subPackages && isSubPackage(packageName, exported))) {
if (!result.contains(exported))
result.add(exported);
}
}
- if (substitutedPackages != null)
- for (String substituted : substitutedPackages) {
- if (substituted.equals(packageName) || (subPackages && isSubPackage(packageName, substituted))) {
- if (!result.contains(substituted))
- result.add(substituted);
- }
+
+ for (String substituted : wiring.getSubstitutedNames()) {
+ if (substituted.equals(packageName) || (subPackages && isSubPackage(packageName, substituted))) {
+ if (!result.contains(substituted))
+ result.add(substituted);
}
- if (requiredBundles != null) {
- int size = reexportTable == null ? 0 : reexportTable.length;
- int reexportIndex = 0;
- for (int i = 0; i < requiredBundles.length; i++) {
- if (reexportIndex < size && reexportTable[reexportIndex] == i) {
- reexportIndex++;
- requiredBundles[i].getBundleLoader().addProvidedPackageNames(symbolicName, packageName, result, subPackages, visitied);
- }
+ }
+ List<ModuleWire> requireBundles = wiring.getRequiredModuleWires(BundleNamespace.BUNDLE_NAMESPACE);
+ for (ModuleWire bundleWire : requireBundles) {
+ if (BundleNamespace.VISIBILITY_REEXPORT.equals(bundleWire.getRequirement().getDirectives().get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE))) {
+ ((BundleLoader) bundleWire.getProviderWiring().getModuleLoader()).addProvidedPackageNames(packageName, result, subPackages, visited);
}
}
}
- final boolean isExportedPackage(String name) {
+ public final boolean isExportedPackage(String name) {
return exportedPackages.contains(name);
}
final boolean isSubstitutedExport(String name) {
- return substitutedPackages == null ? false : substitutedPackages.contains(name);
+ return wiring.isSubstitutedPackage(name);
}
- private void addDynamicImportPackage(ImportPackageSpecification[] packages) {
- if (packages == null)
+ private void addDynamicImportPackage(List<ModuleRequirement> packageImports) {
+ if (packageImports.isEmpty()) {
return;
- List<String> dynamicImports = new ArrayList<String>(packages.length);
- for (int i = 0; i < packages.length; i++)
- if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(packages[i].getDirective(Constants.RESOLUTION_DIRECTIVE)))
- dynamicImports.add(packages[i].getName());
+ }
+ List<String> dynamicImports = new ArrayList<String>(packageImports.size());
+ for (ModuleRequirement packageImport : packageImports) {
+ if (PackageNamespace.RESOLUTION_DYNAMIC.equals(packageImport.getDirectives().get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
+ Matcher matcher = PACKAGENAME_FILTER.matcher(packageImport.getDirectives().get(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE));
+ if (matcher.find()) {
+ String dynamicName = matcher.group(1);
+ if (dynamicName != null) {
+ dynamicImports.add(dynamicName);
+ }
+ }
+ }
+ }
if (dynamicImports.size() > 0)
addDynamicImportPackage(dynamicImports.toArray(new String[dynamicImports.size()]));
}
@@ -1056,50 +845,51 @@ public class BundleLoader implements ClassLoaderDelegate {
if (packages == null)
return;
- loaderFlags |= FLAG_HASDYNAMICIMPORTS;
- int size = packages.length;
- List<String> stems;
- if (dynamicImportPackageStems == null) {
- stems = new ArrayList<String>(size);
- } else {
- stems = new ArrayList<String>(size + dynamicImportPackageStems.length);
- for (int i = 0; i < dynamicImportPackageStems.length; i++) {
- stems.add(dynamicImportPackageStems[i]);
+ synchronized (importedSources) {
+ int size = packages.length;
+ List<String> stems;
+ if (dynamicImportPackageStems == null) {
+ stems = new ArrayList<String>(size);
+ } else {
+ stems = new ArrayList<String>(size + dynamicImportPackageStems.length);
+ for (int i = 0; i < dynamicImportPackageStems.length; i++) {
+ stems.add(dynamicImportPackageStems[i]);
+ }
}
- }
- List<String> names;
- if (dynamicImportPackages == null) {
- names = new ArrayList<String>(size);
- } else {
- names = new ArrayList<String>(size + dynamicImportPackages.length);
- for (int i = 0; i < dynamicImportPackages.length; i++) {
- names.add(dynamicImportPackages[i]);
+ List<String> names;
+ if (dynamicImportPackages == null) {
+ names = new ArrayList<String>(size);
+ } else {
+ names = new ArrayList<String>(size + dynamicImportPackages.length);
+ for (int i = 0; i < dynamicImportPackages.length; i++) {
+ names.add(dynamicImportPackages[i]);
+ }
}
- }
- for (int i = 0; i < size; i++) {
- String name = packages[i];
- if (isDynamicallyImported(name))
- continue;
- if (name.equals("*")) { /* shortcut *///$NON-NLS-1$
- loaderFlags |= FLAG_HASDYNAMICEIMPORTALL;
- return;
- }
+ for (int i = 0; i < size; i++) {
+ String name = packages[i];
+ if (isDynamicallyImported(name))
+ continue;
+ if (name.equals("*")) { /* shortcut *///$NON-NLS-1$
+ dynamicAllPackages = true;
+ return;
+ }
- if (name.endsWith(".*")) //$NON-NLS-1$
- stems.add(name.substring(0, name.length() - 1));
- else
- names.add(name);
- }
+ if (name.endsWith(".*")) //$NON-NLS-1$
+ stems.add(name.substring(0, name.length() - 1));
+ else
+ names.add(name);
+ }
- size = stems.size();
- if (size > 0)
- dynamicImportPackageStems = stems.toArray(new String[size]);
+ size = stems.size();
+ if (size > 0)
+ dynamicImportPackageStems = stems.toArray(new String[size]);
- size = names.size();
- if (size > 0)
- dynamicImportPackages = names.toArray(new String[size]);
+ size = names.size();
+ if (size > 0)
+ dynamicImportPackages = names.toArray(new String[size]);
+ }
}
/**
@@ -1108,35 +898,36 @@ public class BundleLoader implements ClassLoaderDelegate {
* not added again.
* @param packages the DynamicImport-Package elements to add.
*/
- public final synchronized void addDynamicImportPackage(ManifestElement[] packages) {
+ public final void addDynamicImportPackage(ManifestElement[] packages) {
if (packages == null)
return;
List<String> dynamicImports = new ArrayList<String>(packages.length);
- List<ImportPackageSpecification> dynamicImportSpecs = new ArrayList<ImportPackageSpecification>(packages.length);
+ StringBuilder importSpec = new StringBuilder();
for (ManifestElement dynamicImportElement : packages) {
String[] names = dynamicImportElement.getValueComponents();
for (String name : names)
dynamicImports.add(name);
- StateBuilder.addImportPackages(dynamicImportElement, dynamicImportSpecs, 2, true);
+ if (importSpec.length() > 0) {
+ importSpec.append(',');
+ }
+ importSpec.append(dynamicImportElement.toString());
}
+
if (dynamicImports.size() > 0) {
addDynamicImportPackage(dynamicImports.toArray(new String[dynamicImports.size()]));
- BundleDescription revision = getLoaderProxy().getBundleDescription();
- State state = revision.getContainingState();
- state.addDynamicImportPackages(revision, dynamicImportSpecs.toArray(new ImportPackageSpecification[dynamicImportSpecs.size()]));
- }
- }
- synchronized public void attachFragment(BundleFragment fragment) throws BundleException {
- ExportPackageDescription[] exports = proxy.getBundleDescription().getSelectedExports();
- if (classloader == null) {
- initializeExports(exports, exportedPackages);
- return;
+ Map<String, String> dynamicImportMap = new HashMap<String, String>();
+ dynamicImportMap.put(Constants.DYNAMICIMPORT_PACKAGE, importSpec.toString());
+
+ try {
+ ModuleRevisionBuilder builder = OSGiManifestBuilderFactory.createBuilder(dynamicImportMap);
+ wiring.addDynamicImports(builder);
+ } catch (BundleException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
}
- String[] classpath = fragment.getBundleData().getClassPath();
- if (classpath != null)
- classloader.attachFragment(fragment.getBundleData(), fragment.getProtectionDomain(), classpath);
- initializeExports(exports, exportedPackages);
}
/*
@@ -1153,7 +944,7 @@ public class BundleLoader implements ClassLoaderDelegate {
return findRequiredSource(pkgName, null);
}
- private PackageSource findImportedSource(String pkgName, KeyedHashSet visited) {
+ private PackageSource findImportedSource(String pkgName, Collection<BundleLoader> visited) {
KeyedHashSet imports = getImportedSources(visited);
if (imports == null)
return null;
@@ -1162,39 +953,56 @@ public class BundleLoader implements ClassLoaderDelegate {
}
}
- private PackageSource findDynamicSource(String pkgName) {
- if (isDynamicallyImported(pkgName)) {
- ExportPackageDescription exportPackage = bundle.getFramework().getAdaptor().getState().linkDynamicImport(proxy.getBundleDescription(), pkgName);
- if (exportPackage != null) {
- PackageSource source = createExportPackageSource(exportPackage, null);
- synchronized (this) {
- if (importedSources == null)
- importedSources = new KeyedHashSet(false);
- }
- synchronized (importedSources) {
+ public KeyedHashSet getImportedSources(Collection<BundleLoader> visited) {
+ synchronized (importedSources) {
+ if (importsInitialized) {
+ return importedSources;
+ }
+ List<ModuleWire> importWires = wiring.getRequiredModuleWires(PackageNamespace.PACKAGE_NAMESPACE);
+ for (ModuleWire importWire : importWires) {
+ PackageSource source = createExportPackageSource(importWire, visited);
+ if (source != null) {
importedSources.add(source);
}
- return source;
+ }
+ importsInitialized = true;
+ return importedSources;
+ }
+ }
+
+ private PackageSource findDynamicSource(String pkgName) {
+ if (!isExportedPackage(pkgName) && isDynamicallyImported(pkgName)) {
+ ModuleRevision revision = wiring.getRevision();
+ try {
+ ModuleWire dynamicWire = revision.getRevisions().getModule().getContainer().resolveDynamic(pkgName, revision);
+ if (dynamicWire != null) {
+ PackageSource source = createExportPackageSource(dynamicWire, null);
+ synchronized (importedSources) {
+ importedSources.add(source);
+ }
+ return source;
+ }
+ } catch (ResolutionException e) {
+ // do nothing;
}
}
return null;
}
- private PackageSource findRequiredSource(String pkgName, KeyedHashSet visited) {
- if (requiredBundles == null)
- return null;
+ private PackageSource findRequiredSource(String pkgName, Collection<BundleLoader> visited) {
synchronized (requiredSources) {
PackageSource result = (PackageSource) requiredSources.getByKey(pkgName);
if (result != null)
return result.isNullSource() ? null : result;
}
if (visited == null)
- visited = new KeyedHashSet(false);
- visited.add(bundle); // always add ourselves so we do not recurse back to ourselves
+ visited = new ArrayList<BundleLoader>();
+ if (!visited.contains(this))
+ visited.add(this); // always add ourselves so we do not recurse back to ourselves
List<PackageSource> result = new ArrayList<PackageSource>(3);
- for (int i = 0; i < requiredBundles.length; i++) {
- BundleLoader requiredLoader = requiredBundles[i].getBundleLoader();
- requiredLoader.addExportedProvidersFor(proxy.getSymbolicName(), pkgName, result, visited);
+ List<ModuleWire> requireBundles = wiring.getRequiredModuleWires(BundleNamespace.BUNDLE_NAMESPACE);
+ for (ModuleWire bundleWire : requireBundles) {
+ ((BundleLoader) bundleWire.getProviderWiring().getModuleLoader()).addExportedProvidersFor(pkgName, result, visited);
}
// found some so cache the result for next time and return
PackageSource source;
@@ -1226,7 +1034,7 @@ public class BundleLoader implements ClassLoaderDelegate {
if (!isExportedPackage(pkgName))
return result;
// if the package is exported then we need to get the local source
- PackageSource localSource = proxy.getPackageSource(pkgName);
+ PackageSource localSource = exportSources.getPackageSource(pkgName);
if (result == null)
return localSource;
if (localSource == null)
@@ -1234,37 +1042,10 @@ public class BundleLoader implements ClassLoaderDelegate {
return createMultiSource(pkgName, new PackageSource[] {result, localSource});
}
- private ClassLoader getParentPrivileged(final BundleClassLoader bcl) {
- if (System.getSecurityManager() == null)
- return bcl.getParent();
-
- return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
- public ClassLoader run() {
- return bcl.getParent();
- }
- });
- }
-
static final class ClassContext extends SecurityManager {
// need to make this method public
public Class<?>[] getClassContext() {
return super.getClassContext();
}
}
-
- static public void closeBundleLoader(BundleLoaderProxy proxy) {
- if (proxy == null)
- return;
- // First close the BundleLoader
- BundleLoader loader = proxy.getBasicBundleLoader();
- if (loader != null)
- loader.close();
- proxy.setStale();
- // if proxy is not null then make sure to unset user object
- // associated with the proxy in the state
- BundleDescription description = proxy.getBundleDescription();
- // must set it back to the bundle object; not null
- // need to make sure the user object is a BundleReference
- description.setUserObject(proxy.getBundleData());
- }
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoaderSources.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoaderSources.java
new file mode 100644
index 000000000..f1fad46d7
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoaderSources.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.loader;
+
+import java.security.AccessController;
+import java.util.Map;
+import org.eclipse.osgi.container.ModuleCapability;
+import org.eclipse.osgi.framework.util.KeyedHashSet;
+import org.eclipse.osgi.framework.util.SecureAction;
+import org.eclipse.osgi.internal.loader.sources.*;
+import org.osgi.framework.namespace.PackageNamespace;
+
+public class BundleLoaderSources {
+ static SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
+ private final KeyedHashSet pkgSources;
+ private final BundleLoader loader;
+
+ public BundleLoaderSources(BundleLoader loader) {
+ this.pkgSources = new KeyedHashSet(false);
+ this.loader = loader;
+ }
+
+ PackageSource getPackageSource(String pkgName) {
+ // getByKey is called outside of a synch block because we really do not
+ // care too much of duplicates getting created. Only the first one will
+ // successfully get stored into pkgSources
+ PackageSource pkgSource = (PackageSource) pkgSources.getByKey(pkgName);
+ if (pkgSource == null) {
+ pkgSource = new SingleSourcePackage(pkgName, loader);
+ synchronized (pkgSources) {
+ pkgSources.add(pkgSource);
+ }
+ }
+ return pkgSource;
+ }
+
+ boolean forceSourceCreation(ModuleCapability packageCapability) {
+ Map<String, String> directives = packageCapability.getDirectives();
+ return directives.get(PackageNamespace.CAPABILITY_EXCLUDE_DIRECTIVE) != null || directives.get(PackageNamespace.CAPABILITY_EXCLUDE_DIRECTIVE) != null;
+ }
+
+ // creates a PackageSource from an ExportPackageDescription. This is called when initializing
+ // a BundleLoader to ensure that the proper PackageSource gets created and used for
+ // filtered and reexport packages. The storeSource flag is used by initialize to indicate
+ // that the source for special case package sources (filtered or re-exported should be stored
+ // in the cache. if this flag is set then a normal SinglePackageSource will not be created
+ // (i.e. it will be created lazily)
+ public PackageSource createPackageSource(ModuleCapability packageCapability, boolean storeSource) {
+ PackageSource pkgSource = null;
+
+ String name = (String) packageCapability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ // check to see if it is a filtered export
+ String includes = packageCapability.getDirectives().get(PackageNamespace.CAPABILITY_INCLUDE_DIRECTIVE);
+ String excludes = packageCapability.getDirectives().get(PackageNamespace.CAPABILITY_EXCLUDE_DIRECTIVE);
+ if (includes != null || excludes != null) {
+ pkgSource = new FilteredSourcePackage(name, loader, includes, excludes);
+ }
+
+ if (storeSource) {
+ // if the package source is not null then store the source only if it is not already present;
+ // getByKey is called outside of a synch block because we really do not
+ // care too much of duplicates getting created. Only the first one will
+ // successfully get stored into pkgSources
+ if (pkgSource != null && pkgSources.getByKey(name) == null)
+ synchronized (pkgSources) {
+ pkgSources.add(pkgSource);
+ }
+ } else {
+ // we are not storing the special case sources, but pkgSource == null this means this
+ // is a normal package source; get it and return it.
+ if (pkgSource == null) {
+ pkgSource = getPackageSource(name);
+ // the first export cached may not be a simple single source like we need.
+ if (pkgSource.getClass() != SingleSourcePackage.class)
+ return new SingleSourcePackage(name, loader);
+ }
+ }
+
+ return pkgSource;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/FragmentLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/FragmentLoader.java
new file mode 100644
index 000000000..77d8b9932
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/FragmentLoader.java
@@ -0,0 +1,24 @@
+package org.eclipse.osgi.internal.loader;
+
+import java.net.URL;
+import java.util.*;
+import org.eclipse.osgi.container.ModuleLoader;
+
+public class FragmentLoader implements ModuleLoader {
+
+ @Override
+ public List<URL> findEntries(String path, String filePattern, int options) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Collection<String> listResources(String path, String filePattern, int options) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java
index 6d252fd95..cbf0810e3 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor;
+package org.eclipse.osgi.internal.loader;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -18,74 +18,86 @@ import java.net.URL;
import java.security.*;
import java.security.cert.Certificate;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.*;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignerInfo;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleReference;
+
+public class ModuleClassLoader extends ClassLoader implements BundleReference {
+ public static class GenerationProtectionDomain extends ProtectionDomain implements BundleReference {
+ private final Generation generation;
+
+ public GenerationProtectionDomain(CodeSource codesource, PermissionCollection permissions, Generation generation) {
+ super(codesource, permissions);
+ this.generation = generation;
+ }
+
+ public Bundle getBundle() {
+ return generation.getRevision().getBundle();
+ }
+ }
-/**
- * The default implementation of <code>BaseClassLoader</code>. This implementation extends
- * <code>ClassLoader</code>.
- * @see BaseClassLoader
- * @see ClasspathManager
- */
-public class DefaultClassLoader extends ClassLoader implements ParallelClassLoader {
/**
* A PermissionCollection for AllPermissions; shared across all ProtectionDomains when security is disabled
*/
protected static final PermissionCollection ALLPERMISSIONS;
- private final static String CLASS_CERTIFICATE_SUPPORT = "osgi.support.class.certificate"; //$NON-NLS-1$
- private final static String CLASS_LOADER_TYPE = "osgi.classloader.type"; //$NON-NLS-1$
- private final static String CLASS_LOADER_TYPE_PARALLEL = "parallel"; //$NON-NLS-1$
- private static final boolean CLASS_CERTIFICATE;
- private static final boolean PARALLEL_CAPABLE;
+ private static final boolean REGISTERED_AS_PARALLEL;
+
@SuppressWarnings("unchecked")
private static final Enumeration<URL> EMPTY_ENUMERATION = Collections.enumeration(Collections.EMPTY_LIST);
static {
- CLASS_CERTIFICATE = Boolean.valueOf(FrameworkProperties.getProperty(CLASS_CERTIFICATE_SUPPORT, "true")).booleanValue(); //$NON-NLS-1$
AllPermission allPerm = new AllPermission();
ALLPERMISSIONS = allPerm.newPermissionCollection();
if (ALLPERMISSIONS != null)
ALLPERMISSIONS.add(allPerm);
- boolean typeParallel = CLASS_LOADER_TYPE_PARALLEL.equals(FrameworkProperties.getProperty(CLASS_LOADER_TYPE, CLASS_LOADER_TYPE_PARALLEL));
- boolean parallelCapable = false;
+ boolean registeredAsParallel;
try {
- if (typeParallel) {
- Method parallelCapableMetod = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable", (Class[]) null); //$NON-NLS-1$
- parallelCapableMetod.setAccessible(true);
- parallelCapable = ((Boolean) parallelCapableMetod.invoke(null, (Object[]) null)).booleanValue();
- }
+ Method parallelCapableMetod = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable", (Class[]) null); //$NON-NLS-1$
+ parallelCapableMetod.setAccessible(true);
+ registeredAsParallel = ((Boolean) parallelCapableMetod.invoke(null, (Object[]) null)).booleanValue();
} catch (Throwable e) {
// must do everything to avoid failing in clinit
- parallelCapable = false;
+ registeredAsParallel = false;
}
- PARALLEL_CAPABLE = parallelCapable;
+ REGISTERED_AS_PARALLEL = registeredAsParallel;
}
- protected ClassLoaderDelegate delegate;
- protected ProtectionDomain domain;
- // Note that PDE has internal dependency on this field type/name (bug 267238)
- protected ClasspathManager manager;
+ private final EquinoxConfiguration configuration;
+ private final Debug debug;
+ private final BundleLoader delegate;
+ private final Generation generation;
+ // TODO Note that PDE has internal dependency on this field type/name (bug 267238)
+ private final ClasspathManager manager;
/**
* Constructs a new DefaultClassLoader.
* @param parent the parent classloader
* @param delegate the delegate for this classloader
- * @param domain the domain for this classloader
- * @param bundledata the bundledata for this classloader
- * @param classpath the classpath for this classloader
+ * @param generation the generation for this class loader
*/
- public DefaultClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, ProtectionDomain domain, BaseData bundledata, String[] classpath) {
+ public ModuleClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation) {
super(parent);
+ this.configuration = configuration;
+ this.debug = configuration.getDebug();
this.delegate = delegate;
- this.domain = domain;
- this.manager = new ClasspathManager(bundledata, classpath, this);
+ this.generation = generation;
+ this.manager = new ClasspathManager(generation, this);
+ }
+
+ /**
+ * Returns the generation of the host revision associated with this class loader
+ * @return the generation for this class loader
+ */
+ Generation getGeneration() {
+ return this.generation;
}
/**
@@ -100,7 +112,7 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
* @throws ClassNotFoundException if the class is not found.
*/
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- if (Debug.DEBUG_LOADER)
+ if (debug.DEBUG_LOADER)
Debug.println("BundleClassLoader[" + delegate + "].loadClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
try {
// Just ask the delegate. This could result in findLocalClass(name) being called.
@@ -110,7 +122,7 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
resolveClass(clazz);
return (clazz);
} catch (Error e) {
- if (Debug.DEBUG_LOADER) {
+ if (debug.DEBUG_LOADER) {
Debug.println("BundleClassLoader[" + delegate + "].loadClass(" + name + ") failed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Debug.printStackTrace(e);
}
@@ -118,7 +130,7 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
} catch (ClassNotFoundException e) {
// If the class is not found do not try to look for it locally.
// The delegate would have already done that for us.
- if (Debug.DEBUG_LOADER) {
+ if (debug.DEBUG_LOADER) {
Debug.println("BundleClassLoader[" + delegate + "].loadClass(" + name + ") failed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Debug.printStackTrace(e);
}
@@ -136,7 +148,7 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
* @return The URL of the resource or null if it does not exist.
*/
public URL getResource(String name) {
- if (Debug.DEBUG_LOADER) {
+ if (debug.DEBUG_LOADER) {
Debug.println("BundleClassLoader[" + delegate + "].getResource(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -144,7 +156,7 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
if (url != null)
return (url);
- if (Debug.DEBUG_LOADER) {
+ if (debug.DEBUG_LOADER) {
Debug.println("BundleClassLoader[" + delegate + "].getResource(" + name + ") failed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -176,15 +188,11 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
return manager.findLibrary(libname);
}
- public ProtectionDomain getDomain() {
- return domain;
- }
-
- public ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain cpDomain) {
- return new ClasspathEntry(bundlefile, createProtectionDomain(bundlefile, cpDomain));
+ public ClasspathEntry createClassPathEntry(BundleFile bundlefile, Generation entryGeneration) {
+ return new ClasspathEntry(bundlefile, createProtectionDomain(bundlefile, entryGeneration), entryGeneration);
}
- public Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry) {
+ public Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry) {
return defineClass(name, classbytes, 0, classbytes.length, classpathEntry.getDomain());
}
@@ -200,10 +208,6 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
return definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
}
- public void initialize() {
- manager.initialize();
- }
-
public URL findLocalResource(String resource) {
return manager.findLocalResource(resource);
}
@@ -216,18 +220,6 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
return manager.findLocalClass(classname);
}
- public void close() {
- manager.close();
- }
-
- public void attachFragment(BundleData sourcedata, ProtectionDomain sourcedomain, String[] sourceclasspath) {
- manager.attachFragment(sourcedata, sourcedomain, sourceclasspath);
- }
-
- public ClassLoaderDelegate getDelegate() {
- return delegate;
- }
-
/**
* Creates a ProtectionDomain which uses specified BundleFile and the permissions of the baseDomain
* @param bundlefile The source bundlefile the domain is for.
@@ -235,17 +227,19 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
* @return a ProtectionDomain which uses specified BundleFile and the permissions of the baseDomain
*/
@SuppressWarnings("deprecation")
- public static ProtectionDomain createProtectionDomain(BundleFile bundlefile, ProtectionDomain baseDomain) {
+ ProtectionDomain createProtectionDomain(BundleFile bundlefile, Generation domainGeneration) {
// create a protection domain which knows about the codesource for this classpath entry (bug 89904)
+ ProtectionDomain baseDomain = domainGeneration.getDomain();
try {
// use the permissions supplied by the domain passed in from the framework
PermissionCollection permissions;
- if (baseDomain != null)
+ if (baseDomain != null) {
permissions = baseDomain.getPermissions();
- else
+ } else {
// no domain specified. Better use a collection that has all permissions
// this is done just incase someone sets the security manager later
permissions = ALLPERMISSIONS;
+ }
Certificate[] certs = null;
SignedContent signedContent = null;
if (bundlefile instanceof BundleFileWrapperChain) {
@@ -254,12 +248,13 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
wrapper = wrapper.getNext();
signedContent = wrapper == null ? null : (SignedContent) wrapper.getWrapped();
}
- if (CLASS_CERTIFICATE && signedContent != null && signedContent.isSigned()) {
+ if (configuration.CLASS_CERTIFICATE && signedContent != null && signedContent.isSigned()) {
SignerInfo[] signers = signedContent.getSignerInfos();
if (signers.length > 0)
certs = signers[0].getCertificateChain();
}
- return new BundleProtectionDomain(permissions, new CodeSource(bundlefile.getBaseFile().toURL(), certs), null);
+ return new GenerationProtectionDomain(new CodeSource(bundlefile.getBaseFile().toURL(), certs), permissions, generation);
+ //return new ProtectionDomain(new CodeSource(bundlefile.getBaseFile().toURL(), certs), permissions);
} catch (MalformedURLException e) {
// Failed to create our own domain; just return the baseDomain
return baseDomain;
@@ -271,11 +266,11 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
}
public Bundle getBundle() {
- return manager.getBaseData().getBundle();
+ return generation.getRevision().getBundle();
}
public boolean isParallelCapable() {
- return PARALLEL_CAPABLE;
+ return REGISTERED_AS_PARALLEL || configuration.PARALLEL_CAPABLE;
}
public List<URL> findEntries(String path, String filePattern, int options) {
@@ -290,6 +285,10 @@ public class DefaultClassLoader extends ClassLoader implements ParallelClassLoad
return manager.listLocalResources(path, filePattern, options);
}
+ public BundleLoader getBundleLoader() {
+ return delegate;
+ }
+
public String toString() {
Bundle b = getBundle();
StringBuffer result = new StringBuffer(super.toString());
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/SystemBundleLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/SystemBundleLoader.java
new file mode 100644
index 000000000..72130d4ec
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/SystemBundleLoader.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.loader;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import org.eclipse.osgi.container.ModuleWiring;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+
+/**
+ * The System Bundle's BundleLoader. This BundleLoader is used by ImportClassLoaders
+ * to load a resource that is exported by the System Bundle.
+ */
+public class SystemBundleLoader extends BundleLoader {
+ public static final String EQUINOX_EE = "x-equinox-ee"; //$NON-NLS-1$
+ final ClassLoader classLoader;
+ final ModuleClassLoader moduleClassLoader;
+
+ public SystemBundleLoader(ModuleWiring wiring, EquinoxContainer container) {
+ super(wiring, container, SystemBundleLoader.class.getClassLoader().getParent());
+ this.classLoader = getClass().getClassLoader();
+ this.moduleClassLoader = new SystemModuleClassLoader(classLoader.getParent(), container.getConfiguration(), this, (Generation) wiring.getRevision().getRevisionInfo());
+ }
+
+ /**
+ * The ClassLoader that loads OSGi framework classes is used to find the class.
+ * This method never gets called because there is no BundleClassLoader for the framework.
+ */
+ public Class<?> findClass(String name) throws ClassNotFoundException {
+ Class<?> result = findLocalClass(name);
+ if (result == null)
+ throw new ClassNotFoundException(name);
+ return result;
+ }
+
+ /**
+ * The ClassLoader that loads OSGi framework classes is used to find the class.
+ */
+ public Class<?> findLocalClass(String name) {
+ try {
+ return classLoader.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ // do nothing
+ return null;
+ }
+ }
+
+ /**
+ * The ClassLoader that loads OSGi framework classes is used to find the resource.
+ */
+ public URL findLocalResource(String name) {
+ return classLoader.getResource(name);
+ }
+
+ /**
+ * The ClassLoader that loads OSGi framework classes is used to find the resource.
+ */
+ public Enumeration<URL> findLocalResources(String name) {
+ try {
+ return classLoader.getResources(name);
+ } catch (IOException e) {
+ // do nothing
+ return null;
+ }
+ }
+
+ /**
+ * The ClassLoader that loads OSGi framework classes is used to find the resource.
+ * This method never gets called because there is no ModuleClassLoader for the framework.
+ */
+ public URL findResource(String name) {
+ return findLocalResource(name);
+ }
+
+ /**
+ * The ClassLoader that loads OSGi framework classes is used to find the resource.
+ * This method never gets called because there is no ModuleClassLoader for the framework.
+ * @throws IOException
+ */
+ public Enumeration<URL> findResources(String name) throws IOException {
+ return findLocalResources(name);
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public ModuleClassLoader getModuleClassLoader() {
+ return moduleClassLoader;
+ }
+
+ class SystemModuleClassLoader extends ModuleClassLoader {
+
+ public SystemModuleClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation) {
+ super(parent, configuration, delegate, generation);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ return SystemBundleLoader.this.findClass(name);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/DependentPolicy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/DependentPolicy.java
index 74121aeaa..cd5e75b06 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/DependentPolicy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/DependentPolicy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,9 +14,11 @@ package org.eclipse.osgi.internal.loader.buddy;
import java.io.IOException;
import java.net.URL;
import java.util.*;
+import org.eclipse.osgi.container.ModuleWire;
+import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
-import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
/**
* DependentPolicy is an implementation of a buddy policy.
@@ -26,14 +28,14 @@ import org.eclipse.osgi.service.resolver.BundleDescription;
public class DependentPolicy implements IBuddyPolicy {
BundleLoader buddyRequester;
int lastDependentOfAdded = -1; //remember the index of the bundle for which we last added the dependent
- List<BundleDescription> allDependents = null; //the list of all dependents known so far
+ List<ModuleWiring> allDependents = null; //the list of all dependents known so far
public DependentPolicy(BundleLoader requester) {
buddyRequester = requester;
//Initialize with the first level of dependent the list
- allDependents = new ArrayList<BundleDescription>();
- basicAddImmediateDependents(buddyRequester.getBundle().getBundleDescription());
+ allDependents = new ArrayList<ModuleWiring>();
+ basicAddImmediateDependents(requester.getWiring());
//If there is no dependent, reset to null
if (allDependents.size() == 0)
allDependents = null;
@@ -46,24 +48,22 @@ public class DependentPolicy implements IBuddyPolicy {
Class<?> result = null;
//size may change, so we must check it every time
for (int i = 0; i < allDependents.size() && result == null; i++) {
- BundleDescription searchedBundle = allDependents.get(i);
+ ModuleWiring searchWiring = allDependents.get(i);
+ BundleLoader searchLoader = (BundleLoader) searchWiring.getModuleLoader();
try {
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(searchedBundle);
- if (proxy == null)
- continue;
- result = proxy.getBundleLoader().findClass(name);
+ result = searchLoader.findClass(name);
} catch (ClassNotFoundException e) {
if (result == null)
- addDependent(i, searchedBundle);
+ addDependent(i, searchWiring);
}
}
return result;
}
- private synchronized void addDependent(int i, BundleDescription searchedBundle) {
+ private synchronized void addDependent(int i, ModuleWiring searchedWiring) {
if (i > lastDependentOfAdded) {
lastDependentOfAdded = i;
- basicAddImmediateDependents(searchedBundle);
+ basicAddImmediateDependents(searchedWiring);
}
}
@@ -74,13 +74,11 @@ public class DependentPolicy implements IBuddyPolicy {
URL result = null;
//size may change, so we must check it every time
for (int i = 0; i < allDependents.size() && result == null; i++) {
- BundleDescription searchedBundle = allDependents.get(i);
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(searchedBundle);
- if (proxy == null)
- continue;
- result = proxy.getBundleLoader().findResource(name);
+ ModuleWiring searchWiring = allDependents.get(i);
+ BundleLoader searchLoader = (BundleLoader) searchWiring.getModuleLoader();
+ result = searchLoader.findResource(name);
if (result == null) {
- addDependent(i, searchedBundle);
+ addDependent(i, searchWiring);
}
}
return result;
@@ -93,13 +91,11 @@ public class DependentPolicy implements IBuddyPolicy {
Enumeration<URL> results = null;
//size may change, so we must check it every time
for (int i = 0; i < allDependents.size(); i++) {
- BundleDescription searchedBundle = allDependents.get(i);
+ ModuleWiring searchWiring = allDependents.get(i);
+ BundleLoader searchLoader = (BundleLoader) searchWiring.getModuleLoader();
try {
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(searchedBundle);
- if (proxy == null)
- continue;
- results = BundleLoader.compoundEnumerations(results, proxy.getBundleLoader().findResources(name));
- addDependent(i, searchedBundle);
+ results = BundleLoader.compoundEnumerations(results, searchLoader.findResources(name));
+ addDependent(i, searchWiring);
} catch (IOException e) {
//Ignore and keep looking
}
@@ -107,12 +103,15 @@ public class DependentPolicy implements IBuddyPolicy {
return results;
}
- private void basicAddImmediateDependents(BundleDescription root) {
- BundleDescription[] dependents = root.getDependents();
- for (int i = 0; i < dependents.length; i++) {
- BundleDescription toAdd = dependents[i];
- if (toAdd.getHost() == null && !allDependents.contains(toAdd)) {
- allDependents.add(toAdd);
+ private void basicAddImmediateDependents(ModuleWiring wiring) {
+ List<ModuleWire> providedWires = wiring.getProvidedModuleWires(null);
+ for (ModuleWire wire : providedWires) {
+ String namespace = wire.getRequirement().getNamespace();
+ if (PackageNamespace.PACKAGE_NAMESPACE.equals(namespace) || BundleNamespace.BUNDLE_NAMESPACE.equals(namespace)) {
+ ModuleWiring dependent = wire.getRequirerWiring();
+ if (!allDependents.contains(dependent)) {
+ allDependents.add(dependent);
+ }
}
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/GlobalPolicy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/GlobalPolicy.java
index 1985ff87a..05df9edcc 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/GlobalPolicy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/GlobalPolicy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -23,6 +23,7 @@ import org.osgi.service.packageadmin.PackageAdmin;
* version of the same package are exported in the system, the exported package
* with the highest version will be returned.
*/
+@SuppressWarnings("deprecation")
public class GlobalPolicy implements IBuddyPolicy {
private PackageAdmin admin;
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/IBuddyPolicy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/IBuddyPolicy.java
index a4066eeea..eac7e7dc1 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/IBuddyPolicy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/IBuddyPolicy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/PolicyHandler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/PolicyHandler.java
index 0795902e1..a362e3c06 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/PolicyHandler.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/PolicyHandler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,7 +12,6 @@ package org.eclipse.osgi.internal.loader.buddy;
import java.net.URL;
import java.util.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
@@ -29,6 +28,7 @@ public class PolicyHandler implements SynchronousBundleListener {
//The loader to which this policy is attached.
private final BundleLoader policedLoader;
+ private final List<String> originalBuddyList;
//List of the policies as well as cache for the one that have been created. The size of this array never changes over time. This is why the synchronization is not done when iterating over it.
private volatile Object[] policies = null;
@@ -36,9 +36,10 @@ public class PolicyHandler implements SynchronousBundleListener {
private final ThreadLocal<Set<String>> beingLoaded;
private final PackageAdmin packageAdmin;
- public PolicyHandler(BundleLoader loader, String buddyList, PackageAdmin packageAdmin) {
+ public PolicyHandler(BundleLoader loader, List<String> buddyList, PackageAdmin packageAdmin) {
policedLoader = loader;
- policies = getArrayFromList(buddyList);
+ this.originalBuddyList = buddyList;
+ policies = buddyList.toArray();
beingLoaded = new ThreadLocal<Set<String>>();
this.packageAdmin = packageAdmin;
}
@@ -209,11 +210,6 @@ public class PolicyHandler implements SynchronousBundleListener {
if ((event.getType() & (BundleEvent.RESOLVED | BundleEvent.UNRESOLVED)) == 0)
return;
// reinitialize the policies
- try {
- String list = policedLoader.getBundle().getBundleData().getManifest().get(Constants.BUDDY_LOADER);
- policies = getArrayFromList(list);
- } catch (BundleException e) {
- //Ignore
- }
+ policies = originalBuddyList.toArray();
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/RegisteredPolicy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/RegisteredPolicy.java
index bf59610c1..0d9f0fb17 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/RegisteredPolicy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/RegisteredPolicy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,15 +12,11 @@ package org.eclipse.osgi.internal.loader.buddy;
import java.io.IOException;
import java.net.URL;
-import java.util.Enumeration;
-import java.util.Iterator;
-import org.eclipse.osgi.framework.internal.core.AbstractBundle;
-import org.eclipse.osgi.framework.internal.core.Constants;
+import java.util.*;
+import org.eclipse.osgi.container.ModuleCapability;
+import org.eclipse.osgi.container.ModuleWiring;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.BundleException;
/**
*Registered policy is an implementation of a buddy policy.
@@ -36,27 +32,25 @@ public class RegisteredPolicy extends DependentPolicy {
if (allDependents == null)
return;
- for (Iterator<BundleDescription> iter = allDependents.iterator(); iter.hasNext();) {
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(iter.next());
- if (proxy == null)
+ String requesterName = requester.getWiring().getRevision().getSymbolicName();
+ for (Iterator<ModuleWiring> iter = allDependents.iterator(); iter.hasNext();) {
+ ModuleWiring wiring = iter.next();
+ List<ModuleCapability> moduleDatas = wiring.getRevision().getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ @SuppressWarnings("unchecked")
+ List<String> registeredList = (List<String>) (moduleDatas.isEmpty() ? null : moduleDatas.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_BUDDY_REGISTERED));
+ if (registeredList == null || registeredList.isEmpty()) {
iter.remove();
-
- try {
- String[] allContributions = ManifestElement.getArrayFromList(((AbstractBundle) proxy.getBundle()).getBundleData().getManifest().get(Constants.REGISTERED_POLICY));
- if (allContributions == null) {
- iter.remove();
- continue;
- }
+ } else {
boolean contributes = false;
- for (int j = 0; j < allContributions.length && contributes == false; j++) {
- if (allContributions[j].equals(buddyRequester.getBundle().getSymbolicName()))
+ for (String registeredName : registeredList) {
+ if (registeredName.equals(requesterName)) {
contributes = true;
+ break;
+ }
}
- if (!contributes)
+ if (!contributes) {
iter.remove();
-
- } catch (BundleException e) {
- iter.remove();
+ }
}
}
@@ -72,11 +66,10 @@ public class RegisteredPolicy extends DependentPolicy {
Class<?> result = null;
int size = allDependents.size();
for (int i = 0; i < size && result == null; i++) {
+ ModuleWiring searchWiring = allDependents.get(i);
+ BundleLoader searchLoader = (BundleLoader) searchWiring.getModuleLoader();
try {
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(allDependents.get(i));
- if (proxy == null)
- continue;
- result = proxy.getBundleLoader().findClass(name);
+ result = searchLoader.findClass(name);
} catch (ClassNotFoundException e) {
//Nothing to do, just keep looking
continue;
@@ -92,10 +85,9 @@ public class RegisteredPolicy extends DependentPolicy {
URL result = null;
int size = allDependents.size();
for (int i = 0; i < size && result == null; i++) {
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(allDependents.get(i));
- if (proxy == null)
- continue;
- result = proxy.getBundleLoader().findResource(name);
+ ModuleWiring searchWiring = allDependents.get(i);
+ BundleLoader searchLoader = (BundleLoader) searchWiring.getModuleLoader();
+ result = searchLoader.findResource(name);
}
return result;
}
@@ -108,10 +100,9 @@ public class RegisteredPolicy extends DependentPolicy {
int size = allDependents.size();
for (int i = 0; i < size; i++) {
try {
- BundleLoaderProxy proxy = buddyRequester.getLoaderProxy(allDependents.get(i));
- if (proxy == null)
- continue;
- results = BundleLoader.compoundEnumerations(results, proxy.getBundleLoader().findResources(name));
+ ModuleWiring searchWiring = allDependents.get(i);
+ BundleLoader searchLoader = (BundleLoader) searchWiring.getModuleLoader();
+ results = BundleLoader.compoundEnumerations(results, searchLoader.findResources(name));
} catch (IOException e) {
//Ignore and keep looking
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/SystemPolicy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/SystemPolicy.java
index a72e6ac15..859837657 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/buddy/SystemPolicy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/buddy/SystemPolicy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java
index 27fc5c4a6..704173362 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java
@@ -9,13 +9,18 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.loader;
+package org.eclipse.osgi.internal.loader.classpath;
+import java.io.IOException;
+import java.io.InputStream;
import java.security.ProtectionDomain;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+import java.util.jar.Manifest;
import org.eclipse.osgi.framework.util.KeyedElement;
import org.eclipse.osgi.framework.util.KeyedHashSet;
+import org.eclipse.osgi.storage.BundleInfo;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
/**
* A ClasspathEntry contains a single <code>BundleFile</code> which is used as
@@ -27,18 +32,21 @@ import org.eclipse.osgi.framework.util.KeyedHashSet;
public class ClasspathEntry {
private final BundleFile bundlefile;
private final ProtectionDomain domain;
+ private final Manifest manifest;
private KeyedHashSet userObjects = null;
- // Note that PDE has internal dependency on this field type/name (bug 267238)
- private volatile BaseData data;
+
+ // TODO Note that PDE has internal dependency on this field type/name (bug 267238)
+ //private volatile BaseData data;
/**
* Constructs a ClasspathElement with the specified bundlefile and domain
* @param bundlefile A BundleFile object which acts as a source
- * @param domain the ProtectDomain for all code loaded from this classpath element
+ * @param domain the protection domain
*/
- public ClasspathEntry(BundleFile bundlefile, ProtectionDomain domain) {
+ public ClasspathEntry(BundleFile bundlefile, ProtectionDomain domain, Generation generation) {
this.bundlefile = bundlefile;
this.domain = domain;
+ this.manifest = getManifest(bundlefile, generation);
}
/**
@@ -50,18 +58,6 @@ public class ClasspathEntry {
}
/**
- * Returns the base data which this entry is associated with. This can be
- * either a host or fragment base data.
- */
- public BaseData getBaseData() {
- return data;
- }
-
- void setBaseData(BaseData data) {
- this.data = data;
- }
-
- /**
* Returns the ProtectionDomain for this classpath entry
* @return the ProtectionDomain for this classpath entry
*/
@@ -93,4 +89,31 @@ public class ClasspathEntry {
userObjects.add(userObject);
}
}
+
+ private static Manifest getManifest(BundleFile cpBundleFile, Generation generation) {
+ if (!generation.hasPackageInfo() && generation.getBundleFile() == cpBundleFile) {
+ return null;
+ }
+ BundleEntry mfEntry = cpBundleFile.getEntry(BundleInfo.OSGI_BUNDLE_MANIFEST);
+ if (mfEntry != null) {
+ InputStream manIn = null;
+ try {
+ try {
+ manIn = mfEntry.getInputStream();
+ return new Manifest(manIn);
+ } finally {
+ if (manIn != null)
+ manIn.close();
+ }
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ return null;
+ }
+
+ public Manifest getManifest() {
+ return this.manifest;
+ }
+
}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java
index bba55ad7b..d166e5043 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java
@@ -9,27 +9,30 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.loader;
+package org.eclipse.osgi.internal.loader.classpath;
-import java.io.File;
-import java.io.IOException;
+import java.io.*;
import java.net.URL;
-import java.security.ProtectionDomain;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
import org.eclipse.osgi.internal.baseadaptor.ArrayMap;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.*;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleException;
-import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.namespace.HostNamespace;
/**
* A helper class for <code>BaseClassLoader</code> implementations. This class will keep track of
@@ -37,60 +40,87 @@ import org.osgi.framework.FrameworkEvent;
* class takes care of searching the <code>ClasspathEntry</code> objects for a base class loader
* implementation. Additional behavior may be added to a classpath manager by configuring
* <code>ClassLoadingHook</code> and <code>ClassLoadingStatsHook</code>.
- * @see BaseClassLoader
- * @see ClassLoadingHook
- * @see ClassLoadingStatsHook
+ * @see ModuleClassLoader
+ * @see ClassLoaderHook
* @since 3.2
*/
public class ClasspathManager {
private static final FragmentClasspath[] emptyFragments = new FragmentClasspath[0];
- private final static String PROP_CLASSLOADER_LOCK = "osgi.classloader.lock"; //$NON-NLS-1$
- private final static String VALUE_CLASSNAME_LOCK = "classname"; //$NON-NLS-1$
- private final static boolean LOCK_CLASSNAME = VALUE_CLASSNAME_LOCK.equals(FrameworkProperties.getProperty(PROP_CLASSLOADER_LOCK));
+ private static final String[] DEFAULT_CLASSPATH = new String[] {"."}; //$NON-NLS-1$
private final static Class<?>[] NULL_CLASS_RESULT = new Class[2];
- private final BaseData data;
- private final String[] classpath;
- private final BaseClassLoader classloader;
+ private final Generation generation;
+ private final ModuleClassLoader classloader;
private final boolean isParallelClassLoader;
private final Map<String, Thread> classNameLocks = new HashMap<String, Thread>(5);
+ private final HookRegistry hookRegistry;
+ private final Debug debug;
- // Note that PDE has internal dependency on this field type/name (bug 267238)
- private ClasspathEntry[] entries;
- // Note that PDE has internal dependency on this field type/name (bug 267238)
- private FragmentClasspath[] fragments = emptyFragments;
+ // TODO Note that PDE has internal dependency on this field type/name (bug 267238)
+ private final ClasspathEntry[] entries;
+ // TODO Note that PDE has internal dependency on this field type/name (bug 267238)
+ private final FragmentClasspath[] fragments;
// a Map<String,String> where "libname" is the key and libpath" is the value
private ArrayMap<String, String> loadedLibraries = null;
// used to detect recusive defineClass calls for the same class on the same class loader (bug 345500)
private ThreadLocal<Collection<String>> currentlyDefining = new ThreadLocal<Collection<String>>();
+ private final Object pkgLock = new Object();
/**
* Constructs a classpath manager for the given host base data, classpath and base class loader
- * @param data the host base data for this classpath manager
- * @param classpath the host classpath for this classpath manager
+ * @param generation the host generation for this classpath manager
* @param classloader the BaseClassLoader for this classpath manager
*/
- public ClasspathManager(BaseData data, String[] classpath, BaseClassLoader classloader) {
- this.data = data;
- this.classpath = classpath;
+ public ClasspathManager(Generation generation, ModuleClassLoader classloader) {
+ this.debug = generation.getBundleInfo().getStorage().getConfiguration().getDebug();
+ this.hookRegistry = generation.getBundleInfo().getStorage().getConfiguration().getHookRegistry();
+ this.generation = generation;
this.classloader = classloader;
- isParallelClassLoader = (classloader instanceof ParallelClassLoader) ? ((ParallelClassLoader) classloader).isParallelCapable() : false;
+ this.isParallelClassLoader = classloader != null && classloader.isParallelCapable();
+ String[] cp = getClassPath(generation.getRevision());
+ this.fragments = buildFragmentClasspaths(this.classloader, this);
+ this.entries = buildClasspath(cp, this, this.generation);
}
- /**
- * initializes this classpath manager. This must be called after all existing fragments have been
- * attached and before any resources/classes are loaded using this classpath manager.
- * <p>
- * After the classpath manager is initialized all configured class loading hooks
- * {@link ClassLoadingHook#initializedClassLoader(BaseClassLoader, BaseData)} methods are called.
- * </p>
- */
- public void initialize() {
- entries = buildClasspath(classpath, this, data, classloader == null ? null : classloader.getDomain());
- ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks();
- if (classloader != null)
- for (int i = 0; i < hooks.length; i++)
- hooks[i].initializedClassLoader(classloader, data);
+ private static String[] getClassPath(ModuleRevision revision) {
+ List<ModuleCapability> moduleDatas = revision.getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ @SuppressWarnings("unchecked")
+ List<String> cp = moduleDatas.isEmpty() ? null : (List<String>) moduleDatas.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_CLASSPATH);
+ return cp == null ? DEFAULT_CLASSPATH : cp.toArray(new String[cp.size()]);
+ }
+
+ private FragmentClasspath[] buildFragmentClasspaths(ModuleClassLoader hostloader, ClasspathManager manager) {
+ if (hostloader == null) {
+ return emptyFragments;
+ }
+ List<ModuleWire> fragmentWires = hostloader.getBundleLoader().getWiring().getProvidedModuleWires(HostNamespace.HOST_NAMESPACE);
+ List<FragmentClasspath> result = new ArrayList<FragmentClasspath>(fragmentWires.size());
+ for (ModuleWire fragmentWire : fragmentWires) {
+ ModuleRevision revision = fragmentWire.getRequirer();
+ Generation fragGeneration = (Generation) revision.getRevisionInfo();
+
+ String[] cp = getClassPath(revision);
+ ClasspathEntry[] fragEntries = buildClasspath(cp, manager, fragGeneration);
+ FragmentClasspath fragClasspath = new FragmentClasspath(fragGeneration, fragEntries);
+ insertFragment(fragClasspath, result);
+ }
+
+ return result.toArray(new FragmentClasspath[result.size()]);
+ }
+
+ private static void insertFragment(FragmentClasspath fragClasspath, List<FragmentClasspath> existing) {
+ // Find a place in the fragment list to insert this fragment.
+ long fragID = fragClasspath.getGeneration().getRevision().getRevisions().getModule().getId();
+
+ for (ListIterator<FragmentClasspath> iExisting = existing.listIterator(); iExisting.hasNext();) {
+ long otherID = iExisting.next().getGeneration().getRevision().getRevisions().getModule().getId();
+ if (fragID < otherID) {
+ iExisting.previous();
+ iExisting.add(fragClasspath);
+ return;
+ }
+ }
+ existing.add(fragClasspath);
}
/**
@@ -98,14 +128,12 @@ public class ClasspathManager {
*
*/
public void close() {
- if (entries != null) {
- for (int i = 0; i < entries.length; i++) {
- if (entries[i] != null) {
- try {
- entries[i].getBundleFile().close();
- } catch (IOException e) {
- data.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
- }
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i] != null) {
+ try {
+ entries[i].getBundleFile().close();
+ } catch (IOException e) {
+ generation.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.ERROR, generation.getRevision().getRevisions().getModule(), e);
}
}
}
@@ -113,71 +141,34 @@ public class ClasspathManager {
fragments[i].close();
}
- /**
- * Attaches the specified sourcedata, sourcedomain and sourceclasspath to this classpath manager
- * @param sourcedata the source fragment BundleData that should be attached.
- * @param sourcedomain the source fragment domain that should be attached.
- * @param sourceclasspath the source fragment classpath that should be attached.
- */
- public void attachFragment(BundleData sourcedata, ProtectionDomain sourcedomain, String[] sourceclasspath) {
- try {
- sourcedata.open(); /* make sure the BundleData is open */
- } catch (IOException e) {
- ((BaseData) sourcedata).getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, ((BaseData) sourcedata).getBundle(), e);
- }
- ClasspathEntry[] fragEntries = buildClasspath(sourceclasspath, this, (BaseData) sourcedata, sourcedomain);
- FragmentClasspath fragClasspath = new FragmentClasspath((BaseData) sourcedata, fragEntries, sourcedomain);
- insertFragment(fragClasspath);
- }
-
- private synchronized void insertFragment(FragmentClasspath fragClasspath) {
- FragmentClasspath[] newFragments = new FragmentClasspath[fragments.length + 1];
- // Find a place in the fragment list to insert this fragment.
- long fragID = fragClasspath.getBundleData().getBundleID();
- int insert = 0;
- for (int i = 0; i < fragments.length; i++) {
- long otherID = fragments[i].getBundleData().getBundleID();
- if (insert == 0 && fragID < otherID) {
- newFragments[i] = fragClasspath;
- insert = 1;
- }
- newFragments[i + insert] = fragments[i];
- }
- // This fragment has the highest ID; put it at the end of the list.
- if (insert == 0)
- newFragments[fragments.length] = fragClasspath;
- fragments = newFragments;
- }
-
- private static ClasspathEntry[] buildClasspath(String[] cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
+ private ClasspathEntry[] buildClasspath(String[] cp, ClasspathManager hostloader, Generation source) {
ArrayList<ClasspathEntry> result = new ArrayList<ClasspathEntry>(cp.length);
// add the regular classpath entries.
for (int i = 0; i < cp.length; i++)
- findClassPathEntry(result, cp[i], hostloader, sourcedata, sourcedomain);
+ findClassPathEntry(result, cp[i], hostloader, source);
return result.toArray(new ClasspathEntry[result.size()]);
}
/**
* Finds all the ClasspathEntry objects for the requested classpath. This method will first call all
- * the configured class loading hooks {@link ClassLoadingHook#addClassPathEntry(ArrayList, String, ClasspathManager, BaseData, ProtectionDomain)}
+ * the configured class loading hooks {@link ClassLoaderHook#addClassPathEntry(ArrayList, String, ClasspathManager, Generation)}
* methods. This allows class loading hooks to add additional ClasspathEntry objects to the result for the
* requested classpath. Then the local host classpath entries and attached fragment classpath entries are
* searched.
* @param result a list of ClasspathEntry objects. This list is used to add new ClasspathEntry objects to.
* @param cp the requested classpath.
* @param hostloader the host classpath manager for the classpath
- * @param sourcedata the source EquionoxData to search for the classpath
- * @param sourcedomain the source domain to used by the new ClasspathEntry
+ * @param sourceGeneration the source generation to search for the classpath
*/
- public static void findClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
- // look in classpath manager hooks first
- ClassLoadingHook[] loaderHooks = sourcedata.getAdaptor().getHookRegistry().getClassLoadingHooks();
+ private void findClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostloader, Generation sourceGeneration) {
+ List<ClassLoaderHook> loaderHooks = hookRegistry.getClassLoaderHooks();
boolean hookAdded = false;
- for (int i = 0; i < loaderHooks.length; i++)
- hookAdded |= loaderHooks[i].addClassPathEntry(result, cp, hostloader, sourcedata, sourcedomain);
- if (!addClassPathEntry(result, cp, hostloader, sourcedata, sourcedomain) && !hookAdded) {
- BundleException be = new BundleException(NLS.bind(AdaptorMsg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, cp, sourcedata.getLocation()), BundleException.MANIFEST_ERROR);
- sourcedata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.INFO, sourcedata.getBundle(), be);
+ for (ClassLoaderHook hook : loaderHooks) {
+ hookAdded |= hook.addClassPathEntry(result, cp, hostloader, sourceGeneration);
+ }
+ if (!addClassPathEntry(result, cp, hostloader, sourceGeneration) && !hookAdded) {
+ BundleException be = new BundleException(NLS.bind(AdaptorMsg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, cp, sourceGeneration.getRevision().toString()), BundleException.MANIFEST_ERROR);
+ sourceGeneration.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.INFO, sourceGeneration.getRevision().getRevisions().getModule(), be);
}
}
@@ -187,27 +178,30 @@ public class ClasspathManager {
* classpath entry is found.
* @param result a list of ClasspathEntry objects. This list is used to add new ClasspathEntry objects to.
* @param cp the requested classpath.
- * @param hostloader the host classpath manager for the classpath
- * @param sourcedata the source EquionoxData to search for the classpath
- * @param sourcedomain the source domain to used by the new ClasspathEntry
+ * @param hostManager the host classpath manager for the classpath
+ * @param source the source generation to search for the classpath
* @return true if a ClasspathEntry was added to the result
*/
- public static boolean addClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
+ public boolean addClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostManager, Generation source) {
+ return addStandardClassPathEntry(result, cp, hostManager, source) || addEclipseClassPathEntry(result, cp, hostManager, source);
+ }
+
+ public static boolean addStandardClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostManager, Generation generation) {
if (cp.equals(".")) { //$NON-NLS-1$
- result.add(hostloader.createClassPathEntry(sourcedata.getBundleFile(), sourcedomain, sourcedata));
+ result.add(hostManager.createClassPathEntry(generation.getBundleFile(), generation));
return true;
}
- ClasspathEntry element = hostloader.getClasspath(cp, sourcedata, sourcedomain);
+ ClasspathEntry element = hostManager.getClasspath(cp, generation);
if (element != null) {
result.add(element);
return true;
}
// need to check in fragments for the classpath entry.
- // only check for fragments if the data is the host's data.
- if (hostloader.data == sourcedata)
- for (int i = 0; i < hostloader.fragments.length; i++) {
- FragmentClasspath fragCP = hostloader.fragments[i];
- element = hostloader.getClasspath(cp, fragCP.getBundleData(), fragCP.getDomain());
+ // only check for fragments if the generation is the host's generation.
+ if (hostManager.generation == generation)
+ for (int i = 0; i < hostManager.fragments.length; i++) {
+ FragmentClasspath fragCP = hostManager.fragments[i];
+ element = hostManager.getClasspath(cp, fragCP.getGeneration());
if (element != null) {
result.add(element);
return true;
@@ -216,89 +210,130 @@ public class ClasspathManager {
return false;
}
+ private boolean addEclipseClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostManager, Generation source) {
+ String var = hasPrefix(cp);
+ if (var != null)
+ // find internal library using eclipse predefined vars
+ return addInternalClassPath(var, result, cp, hostManager, source);
+ if (cp.startsWith(NativeCodeFinder.EXTERNAL_LIB_PREFIX)) {
+ cp = cp.substring(NativeCodeFinder.EXTERNAL_LIB_PREFIX.length());
+ // find external library using system property substitution
+ ClasspathEntry cpEntry = hostManager.getExternalClassPath(source.getBundleInfo().getStorage().getConfiguration().substituteVars(cp), source);
+ if (cpEntry != null) {
+ result.add(cpEntry);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean addInternalClassPath(String var, ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostManager, Generation source) {
+ EquinoxConfiguration configuration = source.getBundleInfo().getStorage().getConfiguration();
+ if (var.equals("ws")) //$NON-NLS-1$
+ return ClasspathManager.addStandardClassPathEntry(cpEntries, "ws/" + configuration.getWS() + cp.substring(4), hostManager, source); //$NON-NLS-1$
+ if (var.equals("os")) //$NON-NLS-1$
+ return ClasspathManager.addStandardClassPathEntry(cpEntries, "os/" + configuration.getOS() + cp.substring(4), hostManager, source); //$NON-NLS-1$
+ if (var.equals("nl")) { //$NON-NLS-1$
+ cp = cp.substring(4);
+ List<String> NL_JAR_VARIANTS = source.getBundleInfo().getStorage().getConfiguration().ECLIPSE_NL_JAR_VARIANTS;
+ for (String nlVariant : NL_JAR_VARIANTS) {
+ if (ClasspathManager.addStandardClassPathEntry(cpEntries, "nl/" + nlVariant + cp, hostManager, source)) //$NON-NLS-1$
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //return a String representing the string found between the $s
+ private static String hasPrefix(String libPath) {
+ if (libPath.startsWith("$ws$")) //$NON-NLS-1$
+ return "ws"; //$NON-NLS-1$
+ if (libPath.startsWith("$os$")) //$NON-NLS-1$
+ return "os"; //$NON-NLS-1$
+ if (libPath.startsWith("$nl$")) //$NON-NLS-1$
+ return "nl"; //$NON-NLS-1$
+ return null;
+ }
+
/**
* Creates a new ClasspathEntry object for the requested classpath if the source exists.
* @param cp the requested classpath.
- * @param sourcedata the source EquionoxData to search for the classpath
- * @param sourcedomain the source domain to used by the new ClasspathEntry
+ * @param cpGeneration the source generation to search for the classpath
* @return a new ClasspathEntry for the requested classpath or null if the source does not exist.
*/
- public ClasspathEntry getClasspath(String cp, BaseData sourcedata, ProtectionDomain sourcedomain) {
+ public ClasspathEntry getClasspath(String cp, Generation cpGeneration) {
BundleFile bundlefile = null;
File file;
- BundleEntry cpEntry = sourcedata.getBundleFile().getEntry(cp);
+ BundleEntry cpEntry = cpGeneration.getBundleFile().getEntry(cp);
// check for internal library directories in a bundle jar file
if (cpEntry != null && cpEntry.getName().endsWith("/")) //$NON-NLS-1$
- bundlefile = createBundleFile(cp, sourcedata);
+ bundlefile = createBundleFile(cp, cpGeneration);
// check for internal library jars
- else if ((file = sourcedata.getBundleFile().getFile(cp, false)) != null)
- bundlefile = createBundleFile(file, sourcedata);
+ else if ((file = cpGeneration.getBundleFile().getFile(cp, false)) != null)
+ bundlefile = createBundleFile(file, cpGeneration);
if (bundlefile != null)
- return createClassPathEntry(bundlefile, sourcedomain, sourcedata);
+ return createClassPathEntry(bundlefile, cpGeneration);
return null;
}
/**
* Uses the requested classpath as an absolute path to locate a source for a new ClasspathEntry.
* @param cp the requested classpath
- * @param sourcedata the source EquionoxData to search for the classpath
- * @param sourcedomain the source domain to used by the new ClasspathEntry
+ * @param cpGeneration the source generation to search for the classpath
* @return a classpath entry which uses an absolut path as a source
*/
- public ClasspathEntry getExternalClassPath(String cp, BaseData sourcedata, ProtectionDomain sourcedomain) {
+ public ClasspathEntry getExternalClassPath(String cp, Generation cpGeneration) {
File file = new File(cp);
if (!file.isAbsolute())
return null;
- BundleFile bundlefile = createBundleFile(file, sourcedata);
+ BundleFile bundlefile = createBundleFile(file, cpGeneration);
if (bundlefile != null)
- return createClassPathEntry(bundlefile, sourcedomain, sourcedata);
+ return createClassPathEntry(bundlefile, cpGeneration);
return null;
}
- private static BundleFile createBundleFile(Object content, BaseData sourcedata) {
- if (content == null || (content instanceof File && !((File) content).exists()))
+ private static BundleFile createBundleFile(File content, Generation generation) {
+ if (!content.exists()) {
return null;
- try {
- return sourcedata.getAdaptor().createBundleFile(content, sourcedata);
- } catch (IOException e) {
- sourcedata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, sourcedata.getBundle(), e);
}
- return null;
+ return generation.getBundleInfo().getStorage().createBundleFile(content, generation, content.isDirectory(), false);
+ }
+
+ private static BundleFile createBundleFile(String nestedDir, Generation generation) {
+ return generation.getBundleInfo().getStorage().createNestedBundleFile(nestedDir, generation.getBundleFile(), generation);
}
- private ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain cpDomain, BaseData cpData) {
+ private ClasspathEntry createClassPathEntry(BundleFile bundlefile, Generation source) {
ClasspathEntry entry;
if (classloader != null)
- entry = classloader.createClassPathEntry(bundlefile, cpDomain);
+ entry = classloader.createClassPathEntry(bundlefile, source);
else
- entry = new ClasspathEntry(bundlefile, null);
- entry.setBaseData(cpData);
- Object domain = entry.getDomain();
- if (domain instanceof BundleProtectionDomain)
- ((BundleProtectionDomain) domain).setBundle(cpData.getBundle());
+ entry = new ClasspathEntry(bundlefile, source.getDomain(), source);
return entry;
}
/**
* Finds a local resource by searching the ClasspathEntry objects of the classpath manager.
* This method will first call all the configured class loading stats hooks
- * {@link ClassLoadingStatsHook#preFindLocalResource(String, ClasspathManager)} methods. Then it
+ * {@link ClassLoaderHook#preFindLocalResource(String, ClasspathManager)} methods. Then it
* will search for the resource. Finally it will call all the configured class loading stats hooks
- * {@link ClassLoadingStatsHook#postFindLocalResource(String, URL, ClasspathManager)} methods.
+ * {@link ClassLoaderHook#postFindLocalResource(String, URL, ClasspathManager)} methods.
* @param resource the requested resource name.
* @return the requested resource URL or null if the resource does not exist
*/
public URL findLocalResource(String resource) {
- ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
- for (int i = 0; i < hooks.length; i++)
- hooks[i].preFindLocalResource(resource, this);
+ List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
+ for (ClassLoaderHook hook : hooks) {
+ hook.preFindLocalResource(resource, this);
+ }
URL result = null;
try {
result = findLocalResourceImpl(resource, -1);
return result;
} finally {
- for (int i = 0; i < hooks.length; i++)
- hooks[i].postFindLocalResource(resource, result, this);
+ for (ClassLoaderHook hook : hooks) {
+ hook.postFindLocalResource(resource, result, this);
+ }
}
}
@@ -358,7 +393,7 @@ public class ClasspathManager {
}
private URL findResourceImpl(String name, BundleFile bundlefile, int index) {
- return bundlefile.getResourceURL(name, data, index);
+ return bundlefile.getResourceURL(name, generation.getRevision().getRevisions().getModule(), index);
}
/**
@@ -435,43 +470,45 @@ public class ClasspathManager {
/**
* Finds a local class by searching the ClasspathEntry objects of the classpath manager.
- * This method will first call all the configured class loading stats hooks
- * {@link ClassLoadingStatsHook#preFindLocalClass(String, ClasspathManager)} methods. Then it
+ * This method will first call all the configured class loader hooks
+ * {@link ClassLoaderHook#preFindLocalClass(String, ClasspathManager)} methods. Then it
* will search for the class. If a class is found then
* <ol>
- * <li>All configured class loading hooks
- * {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
+ * <li>All configured class loader hooks
+ * {@link ClassLoaderHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods will be called.</li>
* <li>The class is then defined.</li>
* <li>Finally, all configured class loading
- * stats hooks {@link ClassLoadingStatsHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
+ * stats hooks {@link ClassLoaderHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods are called.</li>
* </ol>
* Finally all the configured class loading stats hooks
- * {@link ClassLoadingStatsHook#postFindLocalClass(String, Class, ClasspathManager)} methods are called.
+ * {@link ClassLoaderHook#postFindLocalClass(String, Class, ClasspathManager)} methods are called.
* @param classname the requested class name.
* @return the requested class
* @throws ClassNotFoundException if the class does not exist
*/
public Class<?> findLocalClass(String classname) throws ClassNotFoundException {
Class<?> result = null;
- ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
+ List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
try {
- for (int i = 0; i < hooks.length; i++)
- hooks[i].preFindLocalClass(classname, this);
+ for (ClassLoaderHook hook : hooks) {
+ hook.preFindLocalClass(classname, this);
+ }
result = findLoadedClass(classname);
if (result != null)
return result;
result = findLocalClassImpl(classname, hooks);
return result;
} finally {
- for (int i = 0; i < hooks.length; i++)
- hooks[i].postFindLocalClass(classname, result, this);
+ for (ClassLoaderHook hook : hooks) {
+ hook.postFindLocalClass(classname, result, this);
+ }
}
}
private Class<?> findLoadedClass(String classname) {
- if (LOCK_CLASSNAME || isParallelClassLoader) {
+ if (isParallelClassLoader) {
boolean initialLock = lockClassName(classname);
try {
return classloader.publicFindLoaded(classname);
@@ -485,7 +522,7 @@ public class ClasspathManager {
}
}
- private Class<?> findLocalClassImpl(String classname, ClassLoadingStatsHook[] hooks) throws ClassNotFoundException {
+ private Class<?> findLocalClassImpl(String classname, List<ClassLoaderHook> hooks) throws ClassNotFoundException {
Class<?> result = null;
for (int i = 0; i < entries.length; i++) {
if (entries[i] != null) {
@@ -535,8 +572,8 @@ public class ClasspathManager {
}
}
- private Class<?> findClassImpl(String name, ClasspathEntry classpathEntry, ClassLoadingStatsHook[] hooks) {
- if (Debug.DEBUG_LOADER)
+ private Class<?> findClassImpl(String name, ClasspathEntry classpathEntry, List<ClassLoaderHook> hooks) {
+ if (debug.DEBUG_LOADER)
Debug.println("BundleClassLoader[" + classpathEntry.getBundleFile() + "].findClassImpl(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
String filename = name.replace('.', '/').concat(".class"); //$NON-NLS-1$
BundleEntry entry = classpathEntry.getBundleFile().getEntry(filename);
@@ -547,11 +584,11 @@ public class ClasspathManager {
try {
classbytes = entry.getBytes();
} catch (IOException e) {
- if (Debug.DEBUG_LOADER)
+ if (debug.DEBUG_LOADER)
Debug.println(" IOException reading " + filename + " from " + classpathEntry.getBundleFile()); //$NON-NLS-1$ //$NON-NLS-2$
throw (LinkageError) new LinkageError("Error reading class bytes: " + name).initCause(e); //$NON-NLS-1$
}
- if (Debug.DEBUG_LOADER) {
+ if (debug.DEBUG_LOADER) {
Debug.println(" read " + classbytes.length + " bytes from " + classpathEntry.getBundleFile() + "/" + filename); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Debug.println(" defining class " + name); //$NON-NLS-1$
}
@@ -567,7 +604,7 @@ public class ClasspathManager {
current.add(name);
return defineClass(name, classbytes, classpathEntry, entry, hooks);
} catch (Error e) {
- if (Debug.DEBUG_LOADER)
+ if (debug.DEBUG_LOADER)
Debug.println(" error defining class " + name); //$NON-NLS-1$
throw e;
} finally {
@@ -576,72 +613,125 @@ public class ClasspathManager {
}
/**
- * Defines the specified class. This method will first call all the configured class loading hooks
+ * Defines the specified class. This method will first call all the configured class loader hooks
* {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
- * methods. Then it will call the {@link BaseClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
- * method to define the class. After that, the class loading stat hooks are called to announce the class
+ * methods. Then it will call the {@link ModuleClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
+ * method to define the class. After that, the class loader hooks are called to announce the class
* definition.
* @param name the name of the class to define
* @param classbytes the class bytes
* @param classpathEntry the classpath entry used to load the class bytes
* @param entry the BundleEntry used to load the class bytes
- * @param statsHooks the class loading stat hooks
+ * @param hooks the class loader hooks
* @return the defined class
*/
- private Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClassLoadingStatsHook[] statsHooks) {
- ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks();
+ private Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, List<ClassLoaderHook> hooks) {
byte[] modifiedBytes = classbytes;
// The result holds two Class objects.
// The first slot to either a pre loaded class or the newly defined class.
// The second slot is only set to a newly defined class object if it was successfully defined
Class<?>[] result = NULL_CLASS_RESULT;
try {
- for (int i = 0; i < hooks.length; i++) {
- modifiedBytes = hooks[i].processClass(name, classbytes, classpathEntry, entry, this);
+ definePackage(name, classpathEntry);
+ for (ClassLoaderHook hook : hooks) {
+ modifiedBytes = hook.processClass(name, classbytes, classpathEntry, entry, this);
if (modifiedBytes != null)
classbytes = modifiedBytes;
}
- if (LOCK_CLASSNAME || isParallelClassLoader) {
+ if (isParallelClassLoader) {
boolean initialLock = lockClassName(name);
try {
- result = defineClassHoldingLock(name, classbytes, classpathEntry, entry);
+ result = defineClassHoldingLock(name, classbytes, classpathEntry);
} finally {
if (initialLock)
unlockClassName(name);
}
} else {
synchronized (classloader) {
- result = defineClassHoldingLock(name, classbytes, classpathEntry, entry);
+ result = defineClassHoldingLock(name, classbytes, classpathEntry);
}
}
} finally {
- for (int i = 0; i < statsHooks.length; i++)
+ for (ClassLoaderHook hook : hooks) {
// only pass the newly defined class to the hook
- statsHooks[i].recordClassDefine(name, result[1], classbytes, classpathEntry, entry, this);
+ hook.recordClassDefine(name, result[1], classbytes, classpathEntry, entry, this);
+ }
}
// return either the pre-loaded class or the newly defined class
return result[0];
}
- private Class<?>[] defineClassHoldingLock(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry) {
+ private void definePackage(String name, ClasspathEntry classpathEntry) {
+ // Define the package if it is not the default package.
+ int lastIndex = name.lastIndexOf('.');
+ if (lastIndex < 0) {
+ return;
+ }
+ String packageName = name.substring(0, lastIndex);
+ Object pkg;
+ synchronized (pkgLock) {
+ pkg = classloader.publicGetPackage(packageName);
+ if (pkg != null) {
+ return;
+ }
+ }
+
+ // get info about the package from the classpath entry's manifest.
+ String specTitle = null, specVersion = null, specVendor = null, implTitle = null, implVersion = null, implVendor = null;
+
+ if (generation.getBundleInfo().getStorage().getConfiguration().DEFINE_PACKAGE_ATTRIBUTES) {
+ Manifest mf = classpathEntry.getManifest();
+ if (mf != null) {
+ Attributes mainAttributes = mf.getMainAttributes();
+ String dirName = packageName.replace('.', '/') + '/';
+ Attributes packageAttributes = mf.getAttributes(dirName);
+ boolean noEntry = false;
+ if (packageAttributes == null) {
+ noEntry = true;
+ packageAttributes = mainAttributes;
+ }
+ specTitle = packageAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
+ if (specTitle == null && !noEntry)
+ specTitle = mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
+ specVersion = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
+ if (specVersion == null && !noEntry)
+ specVersion = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
+ specVendor = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
+ if (specVendor == null && !noEntry)
+ specVendor = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
+ implTitle = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
+ if (implTitle == null && !noEntry)
+ implTitle = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
+ implVersion = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+ if (implVersion == null && !noEntry)
+ implVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+ implVendor = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
+ if (implVendor == null && !noEntry)
+ implVendor = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
+ }
+ }
+
+ // The package is not defined yet define it before we define the class.
+ // TODO still need to seal packages.
+ synchronized (pkgLock) {
+ pkg = classloader.publicGetPackage(packageName);
+ if (pkg == null) {
+ classloader.publicDefinePackage(packageName, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, null);
+ }
+ }
+ }
+
+ private Class<?>[] defineClassHoldingLock(String name, byte[] classbytes, ClasspathEntry classpathEntry) {
Class<?>[] result = new Class[2];
// must call findLoadedClass here even if it was called earlier,
// the findLoadedClass and defineClass calls must be atomic
result[0] = classloader.publicFindLoaded(name);
if (result[0] == null)
- result[0] = result[1] = classloader.defineClass(name, classbytes, classpathEntry, entry);
+ result[0] = result[1] = classloader.defineClass(name, classbytes, classpathEntry);
return result;
}
/**
- * Returns the host base data for this classpath manager
- * @return the host base data for this classpath manager
- */
- public BaseData getBaseData() {
- return data;
- }
-
- /**
* Returns the fragment classpaths of this classpath manager
* @return the fragment classpaths of this classpath manager
*/
@@ -658,14 +748,6 @@ public class ClasspathManager {
}
/**
- * Returns the base class loader used by this classpath manager
- * @return the base class loader used by this classpath manager
- */
- public BaseClassLoader getBaseClassLoader() {
- return classloader;
- }
-
- /**
* Finds a library for the bundle represented by this class path managert
* @param libname the library name
* @return The absolution path to the library or null if not found
@@ -683,30 +765,65 @@ public class ClasspathManager {
if (libpath != null)
return libpath;
- libpath = classloader.getDelegate().findLibrary(libname);
+ libpath = findLibrary0(libname);
if (libpath != null)
loadedLibraries.put(libname, libpath);
return libpath;
}
}
+ private String findLibrary0(String libname) {
+ List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
+ String result = null;
+ for (ClassLoaderHook hook : hooks) {
+ try {
+ result = hook.preFindLibrary(libname, classloader);
+ if (result != null) {
+ return result;
+ }
+ } catch (FileNotFoundException e) {
+ return null;
+ }
+ }
+
+ result = generation.findLibrary(libname);
+ if (result != null) {
+ return result;
+ }
+
+ // look in fragment generations
+ for (FragmentClasspath fragment : fragments) {
+ result = fragment.getGeneration().findLibrary(libname);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ for (ClassLoaderHook hook : hooks) {
+ result = hook.postFindLibrary(libname, classloader);
+ if (result != null) {
+ return result;
+ }
+ }
+ return result;
+ }
+
/**
- * @see BundleClassLoader#findEntries(String, String, int)
+ * @see ModuleClassLoader#findEntries(String, String, int)
*/
public List<URL> findEntries(String path, String filePattern, int options) {
- BaseAdaptor adaptor = getBaseData().getAdaptor();
- List<BundleData> datas = new ArrayList<BundleData>();
+ List<Generation> generations = new ArrayList<Generation>();
// first get the host bundle file
- datas.add(getBaseData());
+ generations.add(generation);
// next get the attached fragments bundle files
FragmentClasspath[] currentFragments = getFragmentClasspaths();
for (FragmentClasspath fragmentClasspath : currentFragments)
- datas.add(fragmentClasspath.getBundleData());
+ generations.add(fragmentClasspath.getGeneration());
@SuppressWarnings("unchecked")
List<URL> result = Collections.EMPTY_LIST;
// now search over all the bundle files
- Enumeration<URL> eURLs = adaptor.findEntries(datas, path, filePattern, options);
+ Enumeration<URL> eURLs = Storage.findEntries(generations, path, filePattern, options);
if (eURLs == null)
return result;
result = new ArrayList<URL>();
@@ -716,7 +833,7 @@ public class ClasspathManager {
}
/**
- * @see BundleClassLoader#listLocalResources(String, String, int)
+ * @see ModuleClassLoader#listLocalResources(String, String, int)
*/
public Collection<String> listLocalResources(String path, String filePattern, int options) {
List<BundleFile> bundleFiles = new ArrayList<BundleFile>();
@@ -732,6 +849,14 @@ public class ClasspathManager {
bundleFiles.add(cpEntry.getBundleFile());
}
- return getBaseData().getAdaptor().listEntryPaths(bundleFiles, path, filePattern, options);
+ return Storage.listEntryPaths(bundleFiles, path, filePattern, options);
+ }
+
+ public Generation getGeneration() {
+ return generation;
+ }
+
+ public ModuleClassLoader getClassLoader() {
+ return classloader;
}
}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/FragmentClasspath.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/FragmentClasspath.java
index db25e258c..54103415a 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/FragmentClasspath.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/FragmentClasspath.java
@@ -9,12 +9,11 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.loader;
+package org.eclipse.osgi.internal.loader.classpath;
import java.io.IOException;
-import java.security.ProtectionDomain;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.osgi.framework.FrameworkEvent;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
/**
* A FragmentClasspath contains all the <code>ClasspathEntry</code> objects for a fragment
@@ -22,31 +21,21 @@ import org.osgi.framework.FrameworkEvent;
* @since 3.2
*/
public class FragmentClasspath {
- private BaseData bundledata;
+ private Generation generation;
// Note that PDE has internal dependency on this field type/name (bug 267238)
private ClasspathEntry[] entries;
- private ProtectionDomain domain;
- public FragmentClasspath(BaseData bundledata, ClasspathEntry[] entries, ProtectionDomain domain) {
- this.bundledata = bundledata;
+ public FragmentClasspath(Generation generation, ClasspathEntry[] entries) {
+ this.generation = generation;
this.entries = entries;
- this.domain = domain;
}
/**
- * Returns the fragment BaseData for this FragmentClasspath
- * @return the fragment BaseData for this FragmentClasspath
+ * Returns the fragment Generation for this FragmentClasspath
+ * @return the fragment Generation for this FragmentClasspath
*/
- public BaseData getBundleData() {
- return bundledata;
- }
-
- /**
- * Returns the fragment domain for this FragmentClasspath
- * @return the fragment domain for this FragmentClasspath
- */
- public ProtectionDomain getDomain() {
- return domain;
+ public Generation getGeneration() {
+ return generation;
}
/**
@@ -66,7 +55,7 @@ public class FragmentClasspath {
try {
entries[i].getBundleFile().close();
} catch (IOException e) {
- bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), e);
+ generation.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.ERROR, generation.getRevision().getRevisions().getModule(), e);
}
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/FilteredSourcePackage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/FilteredSourcePackage.java
index 287f9eb7a..93e386692 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/FilteredSourcePackage.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/FilteredSourcePackage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * Copyright (c) 2004, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,34 +8,24 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.loader;
+package org.eclipse.osgi.internal.loader.sources;
import java.net.URL;
import java.util.*;
+import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.util.ManifestElement;
public class FilteredSourcePackage extends SingleSourcePackage {
private static final char ALL = '*';
String[] includes;
String[] excludes;
- String[] friends;
- public FilteredSourcePackage(String name, BundleLoaderProxy supplier, String includes, String excludes, String[] friends) {
+ public FilteredSourcePackage(String name, BundleLoader supplier, String includes, String excludes) {
super(name, supplier);
if (includes != null)
this.includes = ManifestElement.getArrayFromList(includes);
if (excludes != null)
this.excludes = ManifestElement.getArrayFromList(excludes);
- this.friends = friends;
- }
-
- public boolean isFriend(String symbolicName) {
- if (friends == null)
- return true;
- for (int i = 0; i < friends.length; i++)
- if (friends[i].equals(symbolicName))
- return true;
- return false;
}
public URL getResource(String name) {
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/MultiSourcePackage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/MultiSourcePackage.java
index 83eefc6c5..69863c1f8 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/MultiSourcePackage.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/MultiSourcePackage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,15 +8,16 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.loader;
+package org.eclipse.osgi.internal.loader.sources;
import java.net.URL;
import java.util.*;
+import org.eclipse.osgi.internal.loader.BundleLoader;
public class MultiSourcePackage extends PackageSource {
SingleSourcePackage[] suppliers;
- MultiSourcePackage(String id, SingleSourcePackage[] suppliers) {
+ public MultiSourcePackage(String id, SingleSourcePackage[] suppliers) {
super(id);
this.suppliers = suppliers;
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/NullPackageSource.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/NullPackageSource.java
index 796432ba8..a1d31415e 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/NullPackageSource.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/NullPackageSource.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.loader;
+package org.eclipse.osgi.internal.loader.sources;
import java.net.URL;
import java.util.*;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java
new file mode 100644
index 000000000..d49145c12
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.loader.sources;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Enumeration;
+import org.eclipse.osgi.container.ModuleRevision;
+import org.eclipse.osgi.container.ModuleWiring;
+import org.eclipse.osgi.framework.util.KeyedElement;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.SystemBundleLoader;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+public abstract class PackageSource implements KeyedElement {
+ protected String id;
+
+ public PackageSource(String id) {
+ // others depend on the id being interned; see SingleSourcePackage.equals
+ this.id = id.intern();
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public abstract SingleSourcePackage[] getSuppliers();
+
+ public boolean compare(KeyedElement other) {
+ return id.equals(((PackageSource) other).getId());
+ }
+
+ public int getKeyHashCode() {
+ return id.hashCode();
+ }
+
+ public Object getKey() {
+ return id;
+ }
+
+ public boolean isNullSource() {
+ return false;
+ }
+
+ public abstract Class<?> loadClass(String name) throws ClassNotFoundException;
+
+ public abstract URL getResource(String name);
+
+ public abstract Enumeration<URL> getResources(String name) throws IOException;
+
+ //TODO See how this relates with FilteredSourcePackage. Overwriting or doing a double dispatch might be good.
+ // This is intentionally lenient; we don't force all suppliers to match (only one)
+ // it is better to get class cast exceptions in split package cases than miss an event
+ public boolean hasCommonSource(PackageSource other) {
+ if (other == null)
+ return false;
+ if (this == other)
+ return true;
+ SingleSourcePackage[] suppliers1 = getSuppliers();
+ SingleSourcePackage[] suppliers2 = other.getSuppliers();
+ if (suppliers1 == null || suppliers2 == null)
+ return false;
+ // This will return true if the specified source has at least one
+ // of the suppliers of this source.
+ for (int i = 0; i < suppliers1.length; i++)
+ for (int j = 0; j < suppliers2.length; j++)
+ if (suppliers2[j].equals(suppliers1[i]))
+ return true;
+ return false;
+ }
+
+ public abstract Collection<String> listResources(String path, String filePattern);
+
+ /**
+ * Used by ServiceReferenceImpl for isAssignableTo
+ * @param registrant Bundle registering service
+ * @param client Bundle desiring to use service
+ * @param className class name to use
+ * @param serviceClass class of original service object
+ * @param container the equinox container
+ * @return true if assignable given package wiring
+ */
+ public static boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className, Class<?> serviceClass, EquinoxContainer container) {
+ // 1) if the registrant == client always return true
+ if (registrant == client) {
+ return true;
+ }
+ // 2) get the package name from the specified className
+ String pkgName = BundleLoader.getPackageName(className);
+ if (pkgName.startsWith("java.")) //$NON-NLS-1$
+ return true;
+
+ BundleLoader producerBL = getBundleLoader(registrant);
+ if (producerBL == null)
+ return false;
+ BundleLoader consumerBL = getBundleLoader(client);
+ if (consumerBL == null)
+ return false;
+ // 3) for the specified bundle, find the wiring for the package. If no wiring is found return true
+ PackageSource consumerSource = consumerBL.getPackageSource(pkgName);
+ if (consumerSource == null)
+ return true;
+ // work around the issue when the package is in the EE and we delegate to boot for that package
+ if (container.isBootDelegationPackage(pkgName)) {
+ Bundle systemBundle = container.getStorage().getModuleContainer().getModule(0).getBundle();
+ SystemBundleLoader systemLoader = (SystemBundleLoader) getBundleLoader(systemBundle);
+ if (systemLoader.isExportedPackage(pkgName)) {
+ return true; // in this case we have a common source from the EE
+ }
+ }
+ // 4) For the registrant bundle, find the wiring for the package.
+ PackageSource producerSource = producerBL.getPackageSource(pkgName);
+ if (producerSource == null) {
+ if (serviceClass != null && ServiceFactory.class.isAssignableFrom(serviceClass)) {
+ @SuppressWarnings("deprecation")
+ Bundle bundle = container.getPackageAdmin().getBundle(serviceClass);
+ if (bundle != null && bundle != registrant)
+ // in this case we have a wacky ServiceFactory that is doing something we cannot
+ // verify if it is correct. Instead of failing we allow the assignment and hope for the best
+ // bug 326918
+ return true;
+ }
+ // 5) If no wiring is found for the registrant bundle then find the wiring for the classloader of the service object. If no wiring is found return false.
+ producerSource = getPackageSource(serviceClass, pkgName, container.getPackageAdmin());
+ if (producerSource == null)
+ return false;
+ }
+ // 6) If the two wirings found are equal then return true; otherwise return false.
+ return producerSource.hasCommonSource(consumerSource);
+ }
+
+ private static PackageSource getPackageSource(Class<?> serviceClass, String pkgName, @SuppressWarnings("deprecation") PackageAdmin packageAdmin) {
+ if (serviceClass == null)
+ return null;
+ @SuppressWarnings("deprecation")
+ Bundle serviceBundle = packageAdmin.getBundle(serviceClass);
+ if (serviceBundle == null)
+ return null;
+ BundleLoader producerBL = getBundleLoader(serviceBundle);
+ if (producerBL == null)
+ return null;
+ PackageSource producerSource = producerBL.getPackageSource(pkgName);
+ if (producerSource != null)
+ return producerSource;
+ // try the interfaces
+ Class<?>[] interfaces = serviceClass.getInterfaces();
+ // note that getInterfaces never returns null
+ for (int i = 0; i < interfaces.length; i++) {
+ producerSource = getPackageSource(interfaces[i], pkgName, packageAdmin);
+ if (producerSource != null)
+ return producerSource;
+ }
+ // try super class
+ return getPackageSource(serviceClass.getSuperclass(), pkgName, packageAdmin);
+ }
+
+ private static BundleLoader getBundleLoader(Bundle bundle) {
+ ModuleRevision producer = ((EquinoxBundle) bundle).getModule().getCurrentRevision();
+ ModuleWiring producerWiring = producer.getWiring();
+ return producerWiring == null ? null : (BundleLoader) producerWiring.getModuleLoader();
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SingleSourcePackage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/SingleSourcePackage.java
index 533c99676..86c1d6540 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SingleSourcePackage.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/SingleSourcePackage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,17 +8,18 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.loader;
+package org.eclipse.osgi.internal.loader.sources;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
-import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
public class SingleSourcePackage extends PackageSource {
- BundleLoaderProxy supplier;
+ BundleLoader supplier;
- public SingleSourcePackage(String id, BundleLoaderProxy supplier) {
+ public SingleSourcePackage(String id, BundleLoader supplier) {
super(id);
this.supplier = supplier;
}
@@ -32,15 +33,15 @@ public class SingleSourcePackage extends PackageSource {
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
- return supplier.getBundleLoader().findLocalClass(name);
+ return supplier.findLocalClass(name);
}
public URL getResource(String name) {
- return supplier.getBundleLoader().findLocalResource(name);
+ return supplier.findLocalResource(name);
}
public Enumeration<URL> getResources(String name) {
- return supplier.getBundleLoader().findLocalResources(name);
+ return supplier.findLocalResources(name);
}
public boolean equals(Object source) {
@@ -63,7 +64,7 @@ public class SingleSourcePackage extends PackageSource {
@Override
public Collection<String> listResources(String path, String filePattern) {
- BundleClassLoader bcl = supplier.getBundleLoader().createClassLoader();
- return bcl.listLocalResources(path, filePattern, 0);
+ ModuleClassLoader mcl = supplier.getModuleClassLoader();
+ return mcl.listLocalResources(path, filePattern, 0);
}
}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/LocationManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java
index 2e06c32fc..8721adc06 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/LocationManager.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * Copyright (c) 2004, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,34 +8,21 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.adaptor;
+package org.eclipse.osgi.internal.location;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
-import org.eclipse.core.runtime.internal.adaptor.*;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.service.datalocation.Location;
+import org.osgi.framework.Constants;
/**
* This class is used to manage the various Locations for Eclipse.
- * <p>
- * Clients may not extend this class.
- * </p>
- * @since 3.1
- * @noextend This class is not intended to be subclassed by clients.
*/
-public class LocationManager {
- private static Location installLocation = null;
- private static Location configurationLocation = null;
- private static Location userLocation = null;
- private static Location instanceLocation = null;
- private static Location eclipseHomeLocation = null;
-
+public class EquinoxLocations {
public static final String READ_ONLY_AREA_SUFFIX = ".readOnly"; //$NON-NLS-1$
public static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
public static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$
@@ -45,20 +32,10 @@ public class LocationManager {
public static final String PROP_INSTANCE_AREA_DEFAULT = "osgi.instance.area.default"; //$NON-NLS-1$
public static final String PROP_USER_AREA = "osgi.user.area"; //$NON-NLS-1$
public static final String PROP_USER_AREA_DEFAULT = "osgi.user.area.default"; //$NON-NLS-1$
- public static final String PROP_MANIFEST_CACHE = "osgi.manifest.cache"; //$NON-NLS-1$
public static final String PROP_USER_HOME = "user.home"; //$NON-NLS-1$
public static final String PROP_USER_DIR = "user.dir"; //$NON-NLS-1$
public static final String PROP_HOME_LOCATION_AREA = "eclipse.home.location"; //$NON-NLS-1$
- static final String PROP_LAUNCHER = "eclipse.launcher"; //$NON-NLS-1$
-
- // configuration area file/dir names
- public static final String BUNDLES_DIR = "bundles"; //$NON-NLS-1$
- public static final String STATE_FILE = ".state"; //$NON-NLS-1$
- public static final String LAZY_FILE = ".lazy"; //$NON-NLS-1$
- public static final String BUNDLE_DATA_FILE = ".bundledata"; //$NON-NLS-1$
- public static final String MANIFESTS_DIR = "manifests"; //$NON-NLS-1$
- public static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$
- public static final String ECLIPSE_PROPERTIES = "eclipse.properties"; //$NON-NLS-1$
+ public static final String PROP_LAUNCHER = "eclipse.launcher"; //$NON-NLS-1$
// Constants for configuration location discovery
private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
@@ -78,38 +55,22 @@ public class LocationManager {
private static final String INSTANCE_DATA_AREA_PREFIX = ".metadata/.plugins/"; //$NON-NLS-1$
- /**
- * Builds a URL with the given specification
- * @param spec the URL specification
- * @param trailingSlash flag to indicate a trailing slash on the spec
- * @return a URL
- */
- public static URL buildURL(String spec, boolean trailingSlash) {
- return LocationHelper.buildURL(spec, trailingSlash);
- }
+ private final EquinoxConfiguration equinoxConfig;
- private static void mungeConfigurationLocation() {
- // if the config property was set, munge it for backwards compatibility.
- String location = FrameworkProperties.getProperty(PROP_CONFIG_AREA);
- if (location != null) {
- if (location.endsWith(".cfg")) { //$NON-NLS-1$
- int index = location.lastIndexOf('/');
- if (index < 0)
- index = location.lastIndexOf('\\');
- location = location.substring(0, index + 1);
- FrameworkProperties.setProperty(PROP_CONFIG_AREA, location);
- }
- }
- }
+ private final Location installLocation;
+ private final Location configurationLocation;
+ private final Location userLocation;
+ private final Location instanceLocation;
+ private final Location eclipseHomeLocation;
- /**
- * Initializes the Location objects for the LocationManager.
- */
- public static void initializeLocations() {
+ public EquinoxLocations(EquinoxConfiguration equinoxConfig) {
+ this.equinoxConfig = equinoxConfig;
+
+ // Initializes the Location objects for the LocationManager.
// set the osgi storage area if it exists
- String osgiStorage = FrameworkProperties.getProperty(Constants.FRAMEWORK_STORAGE);
+ String osgiStorage = equinoxConfig.getConfiguration(Constants.FRAMEWORK_STORAGE);
if (osgiStorage != null)
- FrameworkProperties.setProperty(PROP_CONFIG_AREA, osgiStorage);
+ equinoxConfig.setConfiguration(PROP_CONFIG_AREA, osgiStorage);
// do install location initialization first since others may depend on it
// assumes that the property is already set
installLocation = buildLocation(PROP_INSTALL_AREA, null, "", true, false, null); //$NON-NLS-1$
@@ -118,20 +79,20 @@ public class LocationManager {
Location temp = buildLocation(PROP_USER_AREA_DEFAULT, null, "", false, false, null); //$NON-NLS-1$
URL defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null)
- defaultLocation = buildURL(new File(FrameworkProperties.getProperty(PROP_USER_HOME), "user").getAbsolutePath(), true); //$NON-NLS-1$
+ defaultLocation = buildURL(new File(System.getProperty(PROP_USER_HOME), "user").getAbsolutePath(), true); //$NON-NLS-1$
userLocation = buildLocation(PROP_USER_AREA, defaultLocation, "", false, false, null); //$NON-NLS-1$
temp = buildLocation(PROP_INSTANCE_AREA_DEFAULT, null, "", false, false, INSTANCE_DATA_AREA_PREFIX); //$NON-NLS-1$
defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null)
- defaultLocation = buildURL(new File(FrameworkProperties.getProperty(PROP_USER_DIR), "workspace").getAbsolutePath(), true); //$NON-NLS-1$
+ defaultLocation = buildURL(new File(System.getProperty(PROP_USER_DIR), "workspace").getAbsolutePath(), true); //$NON-NLS-1$
instanceLocation = buildLocation(PROP_INSTANCE_AREA, defaultLocation, "", false, false, INSTANCE_DATA_AREA_PREFIX); //$NON-NLS-1$
mungeConfigurationLocation();
// compute a default but it is very unlikely to be used since main will have computed everything
temp = buildLocation(PROP_CONFIG_AREA_DEFAULT, null, "", false, false, null); //$NON-NLS-1$
defaultLocation = temp == null ? null : temp.getURL();
- if (defaultLocation == null && FrameworkProperties.getProperty(PROP_CONFIG_AREA) == null)
+ if (defaultLocation == null && equinoxConfig.getConfiguration(PROP_CONFIG_AREA) == null)
// only compute the default if the configuration area property is not set
defaultLocation = buildURL(computeDefaultConfigurationLocation(), true);
configurationLocation = buildLocation(PROP_CONFIG_AREA, defaultLocation, "", false, false, null); //$NON-NLS-1$
@@ -140,24 +101,47 @@ public class LocationManager {
// cascaded.
URL parentLocation = computeSharedConfigurationLocation();
if (parentLocation != null && !parentLocation.equals(configurationLocation.getURL())) {
- Location parent = new BasicLocation(null, parentLocation, true, null);
+ Location parent = new BasicLocation(null, parentLocation, true, null, equinoxConfig);
((BasicLocation) configurationLocation).setParent(parent);
}
- initializeDerivedConfigurationLocations();
- if (FrameworkProperties.getProperty(PROP_HOME_LOCATION_AREA) == null) {
- String eclipseLauncher = FrameworkProperties.getProperty(PROP_LAUNCHER);
- String eclipseHomeLocationPath = getEclipseHomeLocation(eclipseLauncher);
+ if (equinoxConfig.getConfiguration(PROP_HOME_LOCATION_AREA) == null) {
+ String eclipseLauncher = equinoxConfig.getConfiguration(PROP_LAUNCHER);
+ String eclipseHomeLocationPath = getEclipseHomeLocation(eclipseLauncher, equinoxConfig);
if (eclipseHomeLocationPath != null)
- FrameworkProperties.setProperty(PROP_HOME_LOCATION_AREA, eclipseHomeLocationPath);
+ equinoxConfig.setConfiguration(PROP_HOME_LOCATION_AREA, eclipseHomeLocationPath);
}
// if eclipse.home.location is not set then default to osgi.install.area
- if (FrameworkProperties.getProperty(PROP_HOME_LOCATION_AREA) == null && FrameworkProperties.getProperty(PROP_INSTALL_AREA) != null)
- FrameworkProperties.setProperty(PROP_HOME_LOCATION_AREA, FrameworkProperties.getProperty(PROP_INSTALL_AREA));
+ if (equinoxConfig.getConfiguration(PROP_HOME_LOCATION_AREA) == null && equinoxConfig.getConfiguration(PROP_INSTALL_AREA) != null)
+ equinoxConfig.setConfiguration(PROP_HOME_LOCATION_AREA, equinoxConfig.getConfiguration(PROP_INSTALL_AREA));
eclipseHomeLocation = buildLocation(PROP_HOME_LOCATION_AREA, null, "", true, true, null); //$NON-NLS-1$
}
- private static String getEclipseHomeLocation(String launcher) {
+ /**
+ * Builds a URL with the given specification
+ * @param spec the URL specification
+ * @param trailingSlash flag to indicate a trailing slash on the spec
+ * @return a URL
+ */
+ public static URL buildURL(String spec, boolean trailingSlash) {
+ return LocationHelper.buildURL(spec, trailingSlash);
+ }
+
+ private void mungeConfigurationLocation() {
+ // if the config property was set, munge it for backwards compatibility.
+ String location = equinoxConfig.getConfiguration(PROP_CONFIG_AREA);
+ if (location != null) {
+ if (location.endsWith(".cfg")) { //$NON-NLS-1$
+ int index = location.lastIndexOf('/');
+ if (index < 0)
+ index = location.lastIndexOf('\\');
+ location = location.substring(0, index + 1);
+ equinoxConfig.setConfiguration(PROP_CONFIG_AREA, location);
+ }
+ }
+ }
+
+ private static String getEclipseHomeLocation(String launcher, EquinoxConfiguration equinoxConfig) {
if (launcher == null)
return null;
File launcherFile = new File(launcher);
@@ -166,7 +150,7 @@ public class LocationManager {
File launcherDir = new File(launcherFile.getParent());
// check for mac os; the os check is copied from EclipseEnvironmentInfo.
String macosx = org.eclipse.osgi.service.environment.Constants.OS_MACOSX;
- if (macosx.equals(EclipseEnvironmentInfo.getDefault().getOS()))
+ if (macosx.equals(equinoxConfig.getOS()))
launcherDir = getMacOSEclipsoeHomeLocation(launcherDir);
return (launcherDir.exists() && launcherDir.isDirectory()) ? launcherDir.getAbsolutePath() : null;
}
@@ -185,20 +169,20 @@ public class LocationManager {
}
@SuppressWarnings("deprecation")
- private static Location buildLocation(String property, URL defaultLocation, String userDefaultAppendage, boolean readOnlyDefault, boolean computeReadOnly, String dataAreaPrefix) {
- String location = FrameworkProperties.clearProperty(property);
+ private Location buildLocation(String property, URL defaultLocation, String userDefaultAppendage, boolean readOnlyDefault, boolean computeReadOnly, String dataAreaPrefix) {
+ String location = equinoxConfig.clearConfiguration(property);
// the user/product may specify a non-default readOnly setting
- String userReadOnlySetting = FrameworkProperties.getProperty(property + READ_ONLY_AREA_SUFFIX);
+ String userReadOnlySetting = equinoxConfig.getConfiguration(property + READ_ONLY_AREA_SUFFIX);
boolean readOnly = (userReadOnlySetting == null ? readOnlyDefault : Boolean.valueOf(userReadOnlySetting).booleanValue());
// if the instance location is not set, predict where the workspace will be and
// put the instance area inside the workspace meta area.
if (location == null)
- return new BasicLocation(property, defaultLocation, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(defaultLocation), dataAreaPrefix);
+ return new BasicLocation(property, defaultLocation, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(defaultLocation), dataAreaPrefix, equinoxConfig);
String trimmedLocation = location.trim();
if (trimmedLocation.equalsIgnoreCase(NONE))
return null;
if (trimmedLocation.equalsIgnoreCase(NO_DEFAULT))
- return new BasicLocation(property, null, readOnly, dataAreaPrefix);
+ return new BasicLocation(property, null, readOnly, dataAreaPrefix, equinoxConfig);
if (trimmedLocation.startsWith(USER_HOME)) {
String base = substituteVar(location, USER_HOME, PROP_USER_HOME);
location = new File(base, userDefaultAppendage).getAbsolutePath();
@@ -215,31 +199,26 @@ public class LocationManager {
URL url = buildURL(location, true);
BasicLocation result = null;
if (url != null) {
- result = new BasicLocation(property, null, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(url), dataAreaPrefix);
+ result = new BasicLocation(property, null, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(url), dataAreaPrefix, equinoxConfig);
result.setURL(url, false);
}
return result;
}
- private static String substituteVar(String source, String var, String prop) {
- String value = FrameworkProperties.getProperty(prop, ""); //$NON-NLS-1$
+ private String substituteVar(String source, String var, String prop) {
+ String value = equinoxConfig.getConfiguration(prop, ""); //$NON-NLS-1$
return value + source.substring(var.length());
}
- private static void initializeDerivedConfigurationLocations() {
- if (FrameworkProperties.getProperty(PROP_MANIFEST_CACHE) == null)
- FrameworkProperties.setProperty(PROP_MANIFEST_CACHE, getConfigurationFile(MANIFESTS_DIR).getAbsolutePath());
- }
-
- private static URL computeInstallConfigurationLocation() {
- String property = FrameworkProperties.getProperty(PROP_INSTALL_AREA);
+ private URL computeInstallConfigurationLocation() {
+ String property = equinoxConfig.getConfiguration(PROP_INSTALL_AREA);
if (property != null)
return LocationHelper.buildURL(property, true);
return null;
}
- private static URL computeSharedConfigurationLocation() {
- String property = FrameworkProperties.getProperty(PROP_SHARED_CONFIG_AREA);
+ private URL computeSharedConfigurationLocation() {
+ String property = equinoxConfig.getConfiguration(PROP_SHARED_CONFIG_AREA);
if (property == null)
return null;
try {
@@ -254,14 +233,14 @@ public class LocationManager {
// different protocol
return sharedConfigurationURL;
sharedConfigurationURL = new URL(installURL, sharedConfigurationURL.getPath());
- FrameworkProperties.setProperty(PROP_SHARED_CONFIG_AREA, sharedConfigurationURL.toExternalForm());
+ equinoxConfig.setConfiguration(PROP_SHARED_CONFIG_AREA, sharedConfigurationURL.toExternalForm());
} catch (MalformedURLException e) {
// do nothing here since it is basically impossible to get a bogus url
}
return null;
}
- private static String computeDefaultConfigurationLocation() {
+ private String computeDefaultConfigurationLocation() {
// 1) We store the config state relative to the 'eclipse' directory if possible
// 2) If this directory is read-only
// we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home>
@@ -293,12 +272,12 @@ public class LocationManager {
return false;
}
- private static String computeDefaultUserAreaLocation(String pathAppendage) {
+ private String computeDefaultUserAreaLocation(String pathAppendage) {
// we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home>
// is unique for each local user, and <application-id> is the one
// defined in .eclipseproduct marker file. If .eclipseproduct does not
// exist, use "eclipse" as the application-id.
- String installProperty = FrameworkProperties.getProperty(PROP_INSTALL_AREA);
+ String installProperty = equinoxConfig.getConfiguration(PROP_INSTALL_AREA);
URL installURL = buildURL(installProperty, true);
if (installURL == null)
return null;
@@ -328,7 +307,7 @@ public class LocationManager {
// add the hash to help prevent collisions
appName += File.separator + installDirHash;
}
- String userHome = FrameworkProperties.getProperty(PROP_USER_HOME);
+ String userHome = System.getProperty(PROP_USER_HOME);
return new File(userHome, appName + "/" + pathAppendage).getAbsolutePath(); //$NON-NLS-1$
}
@@ -336,9 +315,9 @@ public class LocationManager {
* Return hash code identifying an absolute installation path
* @return hash code as String
*/
- private static String getInstallDirHash() {
+ private String getInstallDirHash() {
// compute an install dir hash to prevent configuration area collisions with other eclipse installs
- String installProperty = FrameworkProperties.getProperty(PROP_INSTALL_AREA);
+ String installProperty = equinoxConfig.getConfiguration(PROP_INSTALL_AREA);
URL installURL = buildURL(installProperty, true);
if (installURL == null)
return ""; //$NON-NLS-1$
@@ -360,7 +339,7 @@ public class LocationManager {
* Returns the user Location object
* @return the user Location object
*/
- public static Location getUserLocation() {
+ public Location getUserLocation() {
return userLocation;
}
@@ -368,7 +347,7 @@ public class LocationManager {
* Returns the configuration Location object
* @return the configuration Location object
*/
- public static Location getConfigurationLocation() {
+ public Location getConfigurationLocation() {
return configurationLocation;
}
@@ -376,7 +355,7 @@ public class LocationManager {
* Returns the install Location object
* @return the install Location object
*/
- public static Location getInstallLocation() {
+ public Location getInstallLocation() {
return installLocation;
}
@@ -384,32 +363,11 @@ public class LocationManager {
* Returns the instance Location object
* @return the instance Location object
*/
- public static Location getInstanceLocation() {
+ public Location getInstanceLocation() {
return instanceLocation;
}
- public static Location getEclipseHomeLocation() {
+ public Location getEclipseHomeLocation() {
return eclipseHomeLocation;
}
-
- /**
- * Returns the File object under the configuration location used for the OSGi configuration
- * @return the OSGi configuration directory
- */
- public static File getOSGiConfigurationDir() {
- // TODO assumes the URL is a file: url
- return new File(configurationLocation.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME);
- }
-
- /**
- * Returns a file from the configuration area that can be used by the framework
- * @param filename the filename
- * @return a file from the configuration area
- */
- public static File getConfigurationFile(String filename) {
- File dir = getOSGiConfigurationDir();
- if (!dir.exists())
- dir.mkdirs();
- return new File(dir, filename);
- }
}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogFactory.java
index 416bbdada..692c129ea 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.log;
import java.io.*;
import org.eclipse.equinox.log.Logger;
@@ -19,11 +19,11 @@ import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.osgi.framework.*;
import org.osgi.service.log.LogService;
-public class EclipseLogFactory implements ServiceFactory<FrameworkLog> {
- final EclipseLogWriter defaultWriter;
+class EquinoxLogFactory implements ServiceFactory<FrameworkLog> {
+ final EquinoxLogWriter defaultWriter;
final LogServiceManager logManager;
- public EclipseLogFactory(EclipseLogWriter defaultWriter, LogServiceManager logManager) {
+ public EquinoxLogFactory(EquinoxLogWriter defaultWriter, LogServiceManager logManager) {
this.defaultWriter = defaultWriter;
this.logManager = logManager;
}
@@ -32,8 +32,8 @@ public class EclipseLogFactory implements ServiceFactory<FrameworkLog> {
return createFrameworkLog(bundle, defaultWriter);
}
- FrameworkLog createFrameworkLog(Bundle bundle, EclipseLogWriter eclipseWriter) {
- final EclipseLogWriter logWriter = eclipseWriter == null ? defaultWriter : eclipseWriter;
+ FrameworkLog createFrameworkLog(Bundle bundle, EquinoxLogWriter eclipseWriter) {
+ final EquinoxLogWriter logWriter = eclipseWriter == null ? defaultWriter : eclipseWriter;
final Logger logger = bundle == null ? logManager.getSystemBundleLog().getLogger(eclipseWriter.getLoggerName()) : logManager.getSystemBundleLog().getLogger(bundle, logWriter.getLoggerName());
return new FrameworkLog() {
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
index f4555e6b5..ad42eb17b 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,24 +9,22 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.log;
-import java.io.*;
-import java.net.URLConnection;
-import java.util.*;
+import java.io.File;
+import java.io.Writer;
+import java.util.Dictionary;
+import java.util.Hashtable;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
-import org.eclipse.core.runtime.adaptor.LocationManager;
import org.eclipse.equinox.log.internal.LogServiceManager;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.*;
-public class EclipseLogHook implements HookConfigurator, AdaptorHook {
+public class EquinoxLogServices {
static final String EQUINOX_LOGGER_NAME = "org.eclipse.equinox.logger"; //$NON-NLS-1$
static final String PERF_LOGGER_NAME = "org.eclipse.performance.logger"; //$NON-NLS-1$
private static final String PROP_LOG_ENABLED = "eclipse.log.enabled"; //$NON-NLS-1$
@@ -34,60 +32,52 @@ public class EclipseLogHook implements HookConfigurator, AdaptorHook {
// The eclipse log file extension */
private static final String LOG_EXT = ".log"; //$NON-NLS-1$
private final LogServiceManager logServiceManager;
- private final EclipseLogFactory eclipseLogFactory;
- private final EclipseLogWriter logWriter;
- private final EclipseLogWriter perfWriter;
-
- public EclipseLogHook() {
- String logFileProp = FrameworkProperties.getProperty(EclipseStarter.PROP_LOGFILE);
- boolean enabled = "true".equals(FrameworkProperties.getProperty(PROP_LOG_ENABLED, "true")); //$NON-NLS-1$ //$NON-NLS-2$
+ private final EquinoxLogFactory eclipseLogFactory;
+ private final EquinoxLogWriter logWriter;
+ private final EquinoxLogWriter perfWriter;
+ private final FrameworkLog rootFrameworkLog;
+
+ public EquinoxLogServices(EquinoxConfiguration environmentInfo, Location configuration) {
+ String logFileProp = environmentInfo.getConfiguration(EclipseStarter.PROP_LOGFILE);
+ boolean enabled = "true".equals(environmentInfo.getConfiguration(PROP_LOG_ENABLED, "true")); //$NON-NLS-1$ //$NON-NLS-2$
if (logFileProp != null) {
- logWriter = new EclipseLogWriter(new File(logFileProp), EQUINOX_LOGGER_NAME, enabled);
+ logWriter = new EquinoxLogWriter(new File(logFileProp), EQUINOX_LOGGER_NAME, enabled, environmentInfo);
} else {
- Location location = LocationManager.getConfigurationLocation();
File configAreaDirectory = null;
- if (location != null)
+ if (configuration != null)
// TODO assumes the URL is a file: url
- configAreaDirectory = new File(location.getURL().getFile());
+ configAreaDirectory = new File(configuration.getURL().getFile());
if (configAreaDirectory != null) {
- String logFileName = Long.toString(System.currentTimeMillis()) + EclipseLogHook.LOG_EXT;
+ String logFileName = Long.toString(System.currentTimeMillis()) + EquinoxLogServices.LOG_EXT;
File logFile = new File(configAreaDirectory, logFileName);
- FrameworkProperties.setProperty(EclipseStarter.PROP_LOGFILE, logFile.getAbsolutePath());
- logWriter = new EclipseLogWriter(logFile, EQUINOX_LOGGER_NAME, enabled);
+ environmentInfo.setConfiguration(EclipseStarter.PROP_LOGFILE, logFile.getAbsolutePath());
+ logWriter = new EquinoxLogWriter(logFile, EQUINOX_LOGGER_NAME, enabled, environmentInfo);
} else
- logWriter = new EclipseLogWriter((Writer) null, EQUINOX_LOGGER_NAME, enabled);
+ logWriter = new EquinoxLogWriter((Writer) null, EQUINOX_LOGGER_NAME, enabled, environmentInfo);
}
File logFile = logWriter.getFile();
if (logFile != null) {
File perfLogFile = new File(logFile.getParentFile(), "performance.log"); //$NON-NLS-1$
- perfWriter = new EclipseLogWriter(perfLogFile, PERF_LOGGER_NAME, true);
+ perfWriter = new EquinoxLogWriter(perfLogFile, PERF_LOGGER_NAME, true, environmentInfo);
} else {
- perfWriter = new EclipseLogWriter((Writer) null, PERF_LOGGER_NAME, true);
+ perfWriter = new EquinoxLogWriter((Writer) null, PERF_LOGGER_NAME, true, environmentInfo);
}
- if ("true".equals(FrameworkProperties.getProperty(EclipseStarter.PROP_CONSOLE_LOG))) //$NON-NLS-1$
+ if ("true".equals(environmentInfo.getConfiguration(EclipseStarter.PROP_CONSOLE_LOG))) //$NON-NLS-1$
logWriter.setConsoleLog(true);
logServiceManager = new LogServiceManager(logWriter, perfWriter);
- eclipseLogFactory = new EclipseLogFactory(logWriter, logServiceManager);
-
+ eclipseLogFactory = new EquinoxLogFactory(logWriter, logServiceManager);
+ rootFrameworkLog = eclipseLogFactory.createFrameworkLog(null, logWriter);
}
private ServiceRegistration<?> frameworkLogReg;
private ServiceRegistration<?> perfLogReg;
- public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addAdaptorHook(this);
- }
-
- public void initialize(BaseAdaptor initAdaptor) {
- // Nothing
- }
-
/**
* @throws BundleException
*/
- public void frameworkStart(BundleContext context) throws BundleException {
+ public void start(BundleContext context) throws BundleException {
logServiceManager.start(context);
frameworkLogReg = AdaptorUtil.register(FrameworkLog.class.getName(), eclipseLogFactory, context);
perfLogReg = registerPerformanceLog(context);
@@ -96,35 +86,14 @@ public class EclipseLogHook implements HookConfigurator, AdaptorHook {
/**
* @throws BundleException
*/
- public void frameworkStop(BundleContext context) throws BundleException {
+ public void stop(BundleContext context) throws BundleException {
frameworkLogReg.unregister();
perfLogReg.unregister();
logServiceManager.stop(context);
}
- public void frameworkStopping(BundleContext context) {
- // do nothing
-
- }
-
- public void addProperties(Properties properties) {
- // do nothing
- }
-
- /**
- * @throws IOException
- */
- public URLConnection mapLocationToURLConnection(String location) throws IOException {
- // do nothing
- return null;
- }
-
- public void handleRuntimeError(Throwable error) {
- // do nothing
- }
-
- public FrameworkLog createFrameworkLog() {
- return eclipseLogFactory.createFrameworkLog(null, logWriter);
+ public FrameworkLog getFrameworkLog() {
+ return rootFrameworkLog;
}
private ServiceRegistration<?> registerPerformanceLog(BundleContext context) {
@@ -144,4 +113,12 @@ public class EclipseLogHook implements HookConfigurator, AdaptorHook {
private FrameworkLog createPerformanceLog(Bundle systemBundle) {
return eclipseLogFactory.createFrameworkLog(systemBundle, perfWriter);
}
+
+ public void log(String entry, int severity, String message, Throwable throwable) {
+ log(entry, severity, message, throwable, null);
+ }
+
+ public void log(String entry, int severity, String message, Throwable throwable, FrameworkLogEntry[] children) {
+ getFrameworkLog().log(new FrameworkLogEntry(entry, severity, 0, message, 0, throwable, children));
+ }
}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogWriter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java
index 36eab8b08..f75ec6544 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLogWriter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.log;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
@@ -17,15 +17,15 @@ import java.util.Calendar;
import java.util.Date;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.eclipse.equinox.log.*;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.util.SecureAction;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogService;
-public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
+class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
private static final String PASSWORD = "-password"; //$NON-NLS-1$
/** The session tag */
private static final String SESSION = "!SESSION"; //$NON-NLS-1$
@@ -83,6 +83,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
private final String loggerName;
private final boolean enabled;
+ private final EquinoxConfiguration environmentInfo;
int maxLogSize = DEFAULT_LOG_SIZE; // The value is in KB.
int maxLogFiles = DEFAULT_LOG_FILES;
@@ -95,11 +96,12 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
* Constructs an EclipseLog which uses the specified File to log messages to
* @param outFile a file to log messages to
*/
- public EclipseLogWriter(File outFile, String loggerName, boolean enabled) {
+ public EquinoxLogWriter(File outFile, String loggerName, boolean enabled, EquinoxConfiguration environmentInfo) {
this.outFile = outFile;
this.writer = null;
this.loggerName = loggerName;
this.enabled = enabled;
+ this.environmentInfo = environmentInfo;
readLogProperties();
}
@@ -107,7 +109,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
* Constructs an EclipseLog which uses the specified Writer to log messages to
* @param writer a writer to log messages to
*/
- public EclipseLogWriter(Writer writer, String loggerName, boolean enabled) {
+ public EquinoxLogWriter(Writer writer, String loggerName, boolean enabled, EquinoxConfiguration environmentInfo) {
if (writer == null)
// log to System.err by default
this.writer = logForStream(System.err);
@@ -115,6 +117,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
this.writer = writer;
this.loggerName = loggerName;
this.enabled = enabled;
+ this.environmentInfo = environmentInfo;
}
private Throwable getRoot(Throwable t) {
@@ -159,7 +162,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
private String getSessionTimestamp() {
// Main should have set the session start-up timestamp so return that.
// Return the "now" time if not available.
- String ts = FrameworkProperties.getProperty("eclipse.startTime"); //$NON-NLS-1$
+ String ts = environmentInfo.getConfiguration("eclipse.startTime"); //$NON-NLS-1$
if (ts != null) {
try {
return getDate(new Date(Long.parseLong(ts)));
@@ -187,7 +190,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
// Write out certain values found in System.getProperties()
try {
String key = "eclipse.buildId"; //$NON-NLS-1$
- String value = FrameworkProperties.getProperty(key, "unknown"); //$NON-NLS-1$
+ String value = environmentInfo.getConfiguration(key, "unknown"); //$NON-NLS-1$
writeln(key + "=" + value); //$NON-NLS-1$
key = "java.fullversion"; //$NON-NLS-1$
@@ -207,15 +210,15 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
// then just skip over them.
}
// The Bootloader has some information that we might be interested in.
- write("BootLoader constants: OS=" + EclipseEnvironmentInfo.getDefault().getOS()); //$NON-NLS-1$
- write(", ARCH=" + EclipseEnvironmentInfo.getDefault().getOSArch()); //$NON-NLS-1$
- write(", WS=" + EclipseEnvironmentInfo.getDefault().getWS()); //$NON-NLS-1$
- writeln(", NL=" + EclipseEnvironmentInfo.getDefault().getNL()); //$NON-NLS-1$
+ write("BootLoader constants: OS=" + environmentInfo.getOS()); //$NON-NLS-1$
+ write(", ARCH=" + environmentInfo.getOSArch()); //$NON-NLS-1$
+ write(", WS=" + environmentInfo.getWS()); //$NON-NLS-1$
+ writeln(", NL=" + environmentInfo.getNL()); //$NON-NLS-1$
// Add the command-line arguments used to invoke the platform
// XXX: this includes runtime-private arguments - should we do that?
if (includeCommandLine) {
- writeArgs("Framework arguments: ", EclipseEnvironmentInfo.getDefault().getNonFrameworkArgs()); //$NON-NLS-1$
- writeArgs("Command-line arguments: ", EclipseEnvironmentInfo.getDefault().getCommandLineArgs()); //$NON-NLS-1$
+ writeArgs("Framework arguments: ", environmentInfo.getNonFrameworkArgs()); //$NON-NLS-1$
+ writeArgs("Command-line arguments: ", environmentInfo.getCommandLineArgs()); //$NON-NLS-1$
}
}
@@ -313,7 +316,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
backupIdx = 0;
}
setOutput(newFile, null, append);
- FrameworkProperties.setProperty(EclipseStarter.PROP_LOGFILE, newFile == null ? "" : newFile.getAbsolutePath()); //$NON-NLS-1$
+ environmentInfo.setConfiguration(EclipseStarter.PROP_LOGFILE, newFile == null ? "" : newFile.getAbsolutePath()); //$NON-NLS-1$
}
public synchronized File getFile() {
@@ -625,7 +628,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
* Reads the PROP_LOG_SIZE_MAX and PROP_LOG_FILE_MAX properties.
*/
private void readLogProperties() {
- String newMaxLogSize = secureAction.getProperty(PROP_LOG_SIZE_MAX);
+ String newMaxLogSize = environmentInfo.getConfiguration(PROP_LOG_SIZE_MAX);
if (newMaxLogSize != null) {
maxLogSize = Integer.parseInt(newMaxLogSize);
if (maxLogSize != 0 && maxLogSize < LOG_SIZE_MIN) {
@@ -635,7 +638,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
}
}
- String newMaxLogFiles = secureAction.getProperty(PROP_LOG_FILE_MAX);
+ String newMaxLogFiles = environmentInfo.getConfiguration(PROP_LOG_FILE_MAX);
if (newMaxLogFiles != null) {
maxLogFiles = Integer.parseInt(newMaxLogFiles);
if (maxLogFiles < 1) {
@@ -644,7 +647,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
}
}
- String newLogLevel = secureAction.getProperty(PROP_LOG_LEVEL);
+ String newLogLevel = environmentInfo.getConfiguration(PROP_LOG_LEVEL);
if (newLogLevel != null) {
if (newLogLevel.equals("ERROR")) //$NON-NLS-1$
logLevel = FrameworkLogEntry.ERROR;
@@ -656,7 +659,7 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
logLevel = FrameworkLogEntry.OK; // OK (0) means log everything
}
- includeCommandLine = "true".equals(secureAction.getProperty(PROP_LOG_INCLUDE_COMMAND_LINE, "true")); //$NON-NLS-1$//$NON-NLS-2$
+ includeCommandLine = "true".equals(environmentInfo.getConfiguration(PROP_LOG_INCLUDE_COMMAND_LINE, "true")); //$NON-NLS-1$//$NON-NLS-2$
}
/**
@@ -673,11 +676,11 @@ public class EclipseLogWriter implements SynchronousLogListener, LogFilter {
return false;
if (loggerName.equals(loggableName))
return isLoggable(convertSeverity(loggableLevel));
- if (EclipseLogHook.PERF_LOGGER_NAME.equals(loggableName))
+ if (EquinoxLogServices.PERF_LOGGER_NAME.equals(loggableName))
// we don't want to do anything with performance logger unless
// this is the performance logger (check done above).
return false;
- if (!EclipseLogHook.EQUINOX_LOGGER_NAME.equals(loggerName))
+ if (!EquinoxLogServices.EQUINOX_LOGGER_NAME.equals(loggerName))
// only the equinox log writer should pay attention to other logs
return false;
// for now only log errors; probably need this to be configurable
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/BundlePermissions.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/BundlePermissions.java
index 5ade23ff0..5ade23ff0 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/BundlePermissions.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/BundlePermissions.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/EquinoxSecurityManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/EquinoxSecurityManager.java
index 10d5ce78e..10d5ce78e 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/EquinoxSecurityManager.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/EquinoxSecurityManager.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionAdminTable.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionAdminTable.java
index 472c35009..472c35009 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionAdminTable.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionAdminTable.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionInfoCollection.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionInfoCollection.java
index 8d72ff1cd..8d72ff1cd 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionInfoCollection.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionInfoCollection.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionsHash.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionsHash.java
index 667f23e01..667f23e01 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/PermissionsHash.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/PermissionsHash.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java
index d59644242..33a94dab7 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java
@@ -16,10 +16,8 @@ import java.net.URL;
import java.security.*;
import java.security.cert.*;
import java.util.*;
-import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
-import org.eclipse.osgi.framework.adaptor.PermissionStorage;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
+import org.eclipse.osgi.storage.PermissionData;
import org.osgi.framework.*;
import org.osgi.service.condpermadmin.*;
import org.osgi.service.permissionadmin.PermissionAdmin;
@@ -34,6 +32,9 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
DEFAULT_DEFAULT.add(allPerm);
}
+ // Base implied permissions for all bundles
+ private static final String OSGI_BASE_IMPLIED_PERMISSIONS = "implied.permissions"; //$NON-NLS-1$
+
private static final String ADMIN_IMPLIED_ACTIONS = AdminPermission.RESOURCE + ',' + AdminPermission.METADATA + ',' + AdminPermission.CLASS + ',' + AdminPermission.CONTEXT;
private static final PermissionInfo[] EMPTY_PERM_INFO = new PermissionInfo[0];
/* @GuardedBy(lock) */
@@ -47,25 +48,23 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
/* @GuardedBy(lock) */
private long nextID = System.currentTimeMillis();
/* @GuardedBy(lock) */
- private final PermissionStorage permissionStorage;
+ private final PermissionData permissionStorage;
private final Object lock = new Object();
- private final Framework framework;
+ //private final EquinoxContainer container;
private final PermissionInfo[] impliedPermissionInfos;
private final EquinoxSecurityManager supportedSecurityManager;
- private SecurityAdmin(EquinoxSecurityManager supportedSecurityManager, Framework framework, PermissionInfo[] impliedPermissionInfos, PermissionInfoCollection permAdminDefaults) {
+ private SecurityAdmin(EquinoxSecurityManager supportedSecurityManager, PermissionInfo[] impliedPermissionInfos, PermissionInfoCollection permAdminDefaults) {
this.supportedSecurityManager = supportedSecurityManager;
- this.framework = framework;
this.impliedPermissionInfos = impliedPermissionInfos;
this.permAdminDefaults = permAdminDefaults;
this.permissionStorage = null;
}
- public SecurityAdmin(EquinoxSecurityManager supportedSecurityManager, Framework framework, PermissionStorage permissionStorage) throws IOException {
+ public SecurityAdmin(EquinoxSecurityManager supportedSecurityManager, PermissionData permissionStorage) {
this.supportedSecurityManager = supportedSecurityManager;
- this.framework = framework;
- this.permissionStorage = new SecurePermissionStorage(permissionStorage);
- this.impliedPermissionInfos = SecurityAdmin.getPermissionInfos(getClass().getResource(Constants.OSGI_BASE_IMPLIED_PERMISSIONS), framework);
+ this.permissionStorage = permissionStorage;
+ this.impliedPermissionInfos = SecurityAdmin.getPermissionInfos(getClass().getResource(OSGI_BASE_IMPLIED_PERMISSIONS));
String[] encodedDefaultInfos = permissionStorage.getPermissionData(null);
PermissionInfo[] defaultInfos = getPermissionInfos(encodedDefaultInfos);
if (defaultInfos != null)
@@ -115,7 +114,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
synchronized (lock) {
// get location the hard way to avoid permission check
Bundle bundle = bundlePermissions.getBundle();
- locationCollection = bundle instanceof AbstractBundle ? permAdminTable.getCollection(((AbstractBundle) bundle).getBundleData().getLocation()) : null;
+ locationCollection = bundle instanceof EquinoxBundle ? permAdminTable.getCollection(((EquinoxBundle) bundle).getModule().getLocation()) : null;
curCondAdminTable = condAdminTable;
curPermAdminDefaults = permAdminDefaults;
}
@@ -163,12 +162,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
permAdminDefaults = null;
else
permAdminDefaults = new PermissionInfoCollection(permissions);
- try {
- permissionStorage.setPermissionData(null, getEncodedPermissionInfos(permissions));
- } catch (IOException e) {
- // log
- e.printStackTrace();
- }
+ permissionStorage.setPermissionData(null, getEncodedPermissionInfos(permissions));
}
}
@@ -191,18 +185,12 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
checkAllPermission();
synchronized (lock) {
permAdminTable.setPermissions(location, permissions);
- try {
- permissionStorage.setPermissionData(location, getEncodedPermissionInfos(permissions));
- } catch (IOException e) {
- // TODO log
- e.printStackTrace();
- }
+ permissionStorage.setPermissionData(location, getEncodedPermissionInfos(permissions));
}
}
void delete(SecurityRow securityRow, boolean firstTry) {
ConditionalPermissionUpdate update = newConditionalPermissionUpdate();
- @SuppressWarnings("unchecked")
List<ConditionalPermissionInfo> rows = update.getConditionalPermissionInfos();
for (Iterator<ConditionalPermissionInfo> iRows = rows.iterator(); iRows.hasNext();) {
ConditionalPermissionInfo info = iRows.next();
@@ -279,7 +267,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
private SecurityAdmin getSnapShot() {
SecurityAdmin sa;
synchronized (lock) {
- sa = new SecurityAdmin(supportedSecurityManager, framework, impliedPermissionInfos, permAdminDefaults);
+ sa = new SecurityAdmin(supportedSecurityManager, impliedPermissionInfos, permAdminDefaults);
SecurityRow[] rows = condAdminTable.getRows();
SecurityRow[] rowsSnapShot = new SecurityRow[rows.length];
for (int i = 0; i < rows.length; i++)
@@ -291,7 +279,6 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
private ConditionalPermissionInfo setConditionalPermissionInfo(String name, ConditionInfo[] conds, PermissionInfo[] perms, boolean firstTry) {
ConditionalPermissionUpdate update = newConditionalPermissionUpdate();
- @SuppressWarnings("unchecked")
List<ConditionalPermissionInfo> rows = update.getConditionalPermissionInfos();
ConditionalPermissionInfo newInfo = newConditionalPermissionInfo(name, conds, perms, ConditionalPermissionInfo.ALLOW);
int index = -1;
@@ -341,12 +328,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
newRows[i] = new SecurityRow(this, name, infoBaseRow.getConditionInfos(), infoBaseRow.getPermissionInfos(), infoBaseRow.getAccessDecision());
}
condAdminTable = new SecurityTable(this, newRows);
- try {
- permissionStorage.saveConditionalPermissionInfos(condAdminTable.getEncodedRows());
- } catch (IOException e) {
- // TODO log
- e.printStackTrace();
- }
+ permissionStorage.saveConditionalPermissionInfos(condAdminTable.getEncodedRows());
timeStamp += 1;
return true;
}
@@ -357,16 +339,16 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
return "generated_" + Long.toString(nextID++); //$NON-NLS-1$;
}
- public BundleProtectionDomain createProtectionDomain(Bundle bundle) {
+ public ProtectionDomain createProtectionDomain(Bundle bundle) {
return createProtectionDomain(bundle, this);
}
- private BundleProtectionDomain createProtectionDomain(Bundle bundle, SecurityAdmin sa) {
+ private ProtectionDomain createProtectionDomain(Bundle bundle, SecurityAdmin sa) {
PermissionInfoCollection impliedPermissions = getImpliedPermission(bundle);
- PermissionInfo[] restrictedInfos = getFileRelativeInfos(SecurityAdmin.getPermissionInfos(bundle.getEntry("OSGI-INF/permissions.perm"), framework), bundle); //$NON-NLS-1$
+ PermissionInfo[] restrictedInfos = getFileRelativeInfos(SecurityAdmin.getPermissionInfos(bundle.getEntry("OSGI-INF/permissions.perm")), bundle); //$NON-NLS-1$
PermissionInfoCollection restrictedPermissions = restrictedInfos == null ? null : new PermissionInfoCollection(restrictedInfos);
BundlePermissions bundlePermissions = new BundlePermissions(bundle, sa, impliedPermissions, restrictedPermissions);
- return new BundleProtectionDomain(bundlePermissions, null, bundle);
+ return new ProtectionDomain(null, bundlePermissions);
}
private PermissionInfoCollection getImpliedPermission(Bundle bundle) {
@@ -381,7 +363,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
}
private PermissionInfo[] getFileRelativeInfos(PermissionInfo[] permissionInfos, Bundle bundle) {
- if (permissionInfos == null || !(bundle instanceof AbstractBundle))
+ if (permissionInfos == null)
return permissionInfos;
PermissionInfo[] results = new PermissionInfo[permissionInfos.length];
for (int i = 0; i < permissionInfos.length; i++) {
@@ -390,7 +372,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
if (!"<<ALL FILES>>".equals(permissionInfos[i].getName())) { //$NON-NLS-1$
File file = new File(permissionInfos[i].getName());
if (!file.isAbsolute()) { // relative name
- File target = ((AbstractBundle) bundle).getBundleData().getDataFile(permissionInfos[i].getName());
+ File target = bundle.getDataFile(permissionInfos[i].getName());
if (target != null)
results[i] = new PermissionInfo(permissionInfos[i].getType(), target.getPath(), permissionInfos[i].getActions());
}
@@ -426,7 +408,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
}
}
- private static PermissionInfo[] getPermissionInfos(URL resource, Framework framework) {
+ private static PermissionInfo[] getPermissionInfos(URL resource) {
if (resource == null)
return null;
PermissionInfo[] info = EMPTY_PERM_INFO;
@@ -453,8 +435,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi
permissions.add(new PermissionInfo(line));
} catch (IllegalArgumentException iae) {
/* incorrectly encoded permission */
- if (framework != null)
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.getBundle(0), iae);
+ // TODO used to publish an event here
}
}
int size = permissions.size();
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityRow.java
index 25d269449..25d269449 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityRow.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRowSnapShot.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityRowSnapShot.java
index 79767716f..79767716f 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRowSnapShot.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityRowSnapShot.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityTable.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java
index 72d587d48..72d587d48 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityTable.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityTableUpdate.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTableUpdate.java
index 286e328cc..286e328cc 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityTableUpdate.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTableUpdate.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/implied.permissions b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions
index 1ddcfe994..1ddcfe994 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/implied.permissions
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEngine.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEngine.java
index 7cbb1effd..7cbb1effd 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEngine.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEngine.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEvent.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEvent.java
index 23fb3da0b..23fb3da0b 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEvent.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationEvent.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationListener.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationListener.java
index 9cc4f3fdd..9cc4f3fdd 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationListener.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationListener.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationStatus.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationStatus.java
index 0d7074d98..0d7074d98 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationStatus.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/service/security/AuthorizationStatus.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateChain.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateChain.java
index 5ea55579e..5ea55579e 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateChain.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateChain.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateTrustAuthority.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateTrustAuthority.java
index d418de8a3..d418de8a3 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateTrustAuthority.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateTrustAuthority.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifier.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifier.java
index 63e40fd15..63e40fd15 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifier.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifier.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifierFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifierFactory.java
index e36fb8198..e36fb8198 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifierFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/provisional/verifier/CertificateVerifierFactory.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/KeyStoreTrustEngine.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/service/security/KeyStoreTrustEngine.java
index 96b4bda67..27715c9fe 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/KeyStoreTrustEngine.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/service/security/KeyStoreTrustEngine.java
@@ -39,17 +39,20 @@ public class KeyStoreTrustEngine extends TrustEngine {
private final char[] password;
private final String name;
+ private final SignedBundleHook signedBundleHook;
+
/**
* Create a new KeyStoreTrustEngine that is backed by a KeyStore
* @param path - path to the keystore
* @param type - the type of keystore at the path location
* @param password - the password required to unlock the keystore
*/
- public KeyStoreTrustEngine(String path, String type, char[] password, String name) { //TODO: This should be a *CallbackHandler*
+ public KeyStoreTrustEngine(String path, String type, char[] password, String name, SignedBundleHook signedBundleHook) { //TODO: This should be a *CallbackHandler*
this.path = path;
this.type = type;
this.password = password;
this.name = name;
+ this.signedBundleHook = signedBundleHook;
}
/**
@@ -147,7 +150,7 @@ public class KeyStoreTrustEngine extends TrustEngine {
} catch (KeyStoreException e) {
throw (IOException) new IOException(e.getMessage()).initCause(e);
} catch (GeneralSecurityException e) {
- SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.WARNING, e);
+ signedBundleHook.log(e.getMessage(), FrameworkLogEntry.WARNING, e);
return null;
}
return null;
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
index 528d8d2e6..6bdcab5c3 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
@@ -11,9 +11,9 @@
package org.eclipse.osgi.internal.serviceregistry;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.BundleContextImpl;
-import org.eclipse.osgi.framework.internal.core.FilterImpl;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.BundleContextImpl;
+import org.eclipse.osgi.internal.framework.FilterImpl;
import org.osgi.framework.*;
import org.osgi.framework.hooks.service.ListenerHook;
@@ -35,6 +35,7 @@ class FilteredServiceListener implements ServiceListener, ListenerHook.ListenerI
private final String objectClass;
/** indicates whether the listener has been removed */
private volatile boolean removed;
+ private final Debug debug;
/**
* Constructor.
@@ -45,12 +46,13 @@ class FilteredServiceListener implements ServiceListener, ListenerHook.ListenerI
* @exception InvalidSyntaxException if the filter is invalid.
*/
FilteredServiceListener(final BundleContextImpl context, final ServiceListener listener, final String filterstring) throws InvalidSyntaxException {
+ this.debug = context.getContainer().getConfiguration().getDebug();
this.unfiltered = (listener instanceof UnfilteredServiceListener);
if (filterstring == null) {
this.filter = null;
this.objectClass = null;
} else {
- FilterImpl filterImpl = FilterImpl.newInstance(filterstring);
+ FilterImpl filterImpl = FilterImpl.newInstance(filterstring, context.getContainer().getConfiguration().getDebug().DEBUG_FILTER);
String clazz = filterImpl.getRequiredObjectClass();
if (unfiltered || (clazz == null)) {
this.objectClass = null;
@@ -89,7 +91,7 @@ class FilteredServiceListener implements ServiceListener, ListenerHook.ListenerI
if (!ServiceRegistry.hasListenServicePermission(event, context))
return;
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = this.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(this)); //$NON-NLS-1$
Debug.println("filterServiceEvent(" + listenerName + ", \"" + getFilter() + "\", " + reference.getRegistration().getProperties() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
@@ -99,7 +101,7 @@ class FilteredServiceListener implements ServiceListener, ListenerHook.ListenerI
return;
}
if (allservices || ServiceRegistry.isAssignableTo(context, reference)) {
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchFilteredServiceEvent(" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/HookContext.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java
index 74610341a..74610341a 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/HookContext.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ModifiedServiceEvent.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ModifiedServiceEvent.java
index b3e62c2af..b3e62c2af 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ModifiedServiceEvent.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ModifiedServiceEvent.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java
index a829d2697..a829d2697 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
index e6784ca0a..e6784ca0a 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
index 3821f9f53..3cc4de094 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
@@ -12,10 +12,11 @@
package org.eclipse.osgi.internal.serviceregistry;
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.BundleContextImpl;
+import org.eclipse.osgi.internal.loader.sources.PackageSource;
import org.osgi.framework.*;
-import org.osgi.framework.Constants;
/**
* A registered service.
@@ -35,9 +36,6 @@ import org.osgi.framework.Constants;
* @ThreadSafe
*/
public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Comparable<ServiceRegistrationImpl<?>> {
- /** Internal framework object. */
- private final Framework framework;
-
private final ServiceRegistry registry;
/** context which registered this service. */
@@ -92,7 +90,6 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
this.registry = registry;
this.context = context;
this.bundle = context.getBundleImpl();
- this.framework = context.getFramework();
this.clazzes = clazzes; /* must be set before calling createProperties. */
this.service = service;
this.serviceid = registry.getNextServiceId(); /* must be set before calling createProperties. */
@@ -120,7 +117,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
ref = reference; /* used to publish event outside sync */
this.properties = createProperties(props); /* must be valid after unregister is called. */
}
- if (Debug.DEBUG_SERVICES) {
+ if (registry.debug.DEBUG_SERVICES) {
Debug.println("registerService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
registry.addServiceRegistration(context, this);
@@ -210,7 +207,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
}
/* remove this object from the service registry */
- if (Debug.DEBUG_SERVICES) {
+ if (registry.debug.DEBUG_SERVICES) {
Debug.println("unregisterService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -233,7 +230,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
size = contextsUsing.size();
if (size > 0) {
- if (Debug.DEBUG_SERVICES) {
+ if (registry.debug.DEBUG_SERVICES) {
Debug.println("unregisterService: releasing users"); //$NON-NLS-1$
}
users = contextsUsing.toArray(new BundleContextImpl[size]);
@@ -424,7 +421,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
return null;
}
}
- if (Debug.DEBUG_SERVICES) {
+ if (registry.debug.DEBUG_SERVICES) {
Debug.println("getService[" + user.getBundleImpl() + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -497,7 +494,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
}
}
- if (Debug.DEBUG_SERVICES) {
+ if (registry.debug.DEBUG_SERVICES) {
Debug.println("ungetService[" + user.getBundleImpl() + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -540,7 +537,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
}
}
- if (Debug.DEBUG_SERVICES) {
+ if (registry.debug.DEBUG_SERVICES) {
Debug.println("releaseService[" + user.getBundleImpl() + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -587,7 +584,7 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa
}
boolean isAssignableTo(Bundle client, String className) {
- return framework.isServiceAssignableTo(bundle, client, className, service.getClass());
+ return PackageSource.isServiceAssignableTo(bundle, client, className, service.getClass(), context.getContainer());
}
/**
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
index a80b00b2e..3b4cbdc2f 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
@@ -13,12 +13,16 @@ package org.eclipse.osgi.internal.serviceregistry;
import java.security.*;
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.framework.eventmgr.*;
-import org.eclipse.osgi.framework.internal.core.*;
+import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.BundleContextImpl;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
-import org.osgi.framework.Constants;
import org.osgi.framework.hooks.service.*;
import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;
@@ -73,20 +77,25 @@ public class ServiceRegistry {
private static final int initialCapacity = 50;
/** initial capacity of the nested data structure */
private static final int initialSubCapacity = 10;
- /** framework which created this service registry */
- private final Framework framework;
+ /** container which created this service registry */
+ private final EquinoxContainer container;
+ private final BundleContextImpl systemBundleContext;
+ final Debug debug;
/**
* Initializes the internal data structures of this ServiceRegistry.
*
*/
- public ServiceRegistry(Framework framework) {
- this.framework = framework;
+ public ServiceRegistry(EquinoxContainer container) {
+ this.container = container;
+ this.debug = container.getConfiguration().getDebug();
serviceid = 1;
publishedServicesByClass = new HashMap<String, List<ServiceRegistrationImpl<?>>>(initialCapacity);
publishedServicesByContext = new HashMap<BundleContextImpl, List<ServiceRegistrationImpl<?>>>(initialCapacity);
allPublishedServices = new ArrayList<ServiceRegistrationImpl<?>>(initialCapacity);
serviceEventListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<ServiceListener, FilteredServiceListener>>(initialCapacity);
+ Module systemModule = container.getStorage().getModuleContainer().getModule(0);
+ systemBundleContext = (BundleContextImpl) systemModule.getBundle().getBundleContext();
}
/**
@@ -168,7 +177,7 @@ public class ServiceRegistry {
*/
public ServiceRegistrationImpl<?> registerService(BundleContextImpl context, String[] clazzes, Object service, Dictionary<String, ?> properties) {
if (service == null) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("Service object is null"); //$NON-NLS-1$
}
@@ -178,7 +187,7 @@ public class ServiceRegistry {
int size = clazzes.length;
if (size == 0) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("Classes array is empty"); //$NON-NLS-1$
}
@@ -203,7 +212,7 @@ public class ServiceRegistry {
if (!(service instanceof ServiceFactory<?>)) {
String invalidService = checkServiceClass(clazzes, service);
if (invalidService != null) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
}
throw new IllegalArgumentException(NLS.bind(Msg.SERVICE_NOT_INSTANCEOF_CLASS_EXCEPTION, invalidService));
@@ -292,7 +301,7 @@ public class ServiceRegistry {
* longer valid.
*/
public ServiceReferenceImpl<?>[] getServiceReferences(final BundleContextImpl context, final String clazz, final String filterstring, final boolean allservices, boolean callHooks) throws InvalidSyntaxException {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println((allservices ? "getAllServiceReferences(" : "getServiceReferences(") + clazz + ", \"" + filterstring + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
Filter filter = (filterstring == null) ? null : context.createFilter(filterstring);
@@ -380,7 +389,7 @@ public class ServiceRegistry {
* longer valid.
*/
public ServiceReferenceImpl<?> getServiceReference(BundleContextImpl context, String clazz) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("getServiceReference(" + clazz + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -393,7 +402,7 @@ public class ServiceRegistry {
return references[0];
}
} catch (InvalidSyntaxException e) {
- if (Debug.DEBUG_GENERAL) {
+ if (debug.DEBUG_GENERAL) {
Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(e);
}
@@ -658,7 +667,7 @@ public class ServiceRegistry {
}
registrations = new ArrayList<ServiceRegistrationImpl<?>>(servicesInUse.keySet());
}
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("Releasing services"); //$NON-NLS-1$
}
for (ServiceRegistrationImpl<?> registration : registrations) {
@@ -675,7 +684,7 @@ public class ServiceRegistry {
* @throws InvalidSyntaxException If the filter string is invalid.
*/
public void addServiceListener(BundleContextImpl context, ServiceListener listener, String filter) throws InvalidSyntaxException {
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("addServiceListener[" + context.getBundleImpl() + "](" + listenerName + ", \"" + filter + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
@@ -708,7 +717,7 @@ public class ServiceRegistry {
* @param listener Service Listener to be removed.
*/
public void removeServiceListener(BundleContextImpl context, ServiceListener listener) {
- if (Debug.DEBUG_EVENTS) {
+ if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("removeServiceListener[" + context.getBundleImpl() + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -809,7 +818,7 @@ public class ServiceRegistry {
}
/* deliver the event to the snapshot */
- ListenerQueue<ServiceListener, FilteredServiceListener, ServiceEvent> queue = framework.newListenerQueue();
+ ListenerQueue<ServiceListener, FilteredServiceListener, ServiceEvent> queue = container.newListenerQueue();
for (Map.Entry<BundleContextImpl, Set<Map.Entry<ServiceListener, FilteredServiceListener>>> entry : listenerSnapshot.entrySet()) {
@SuppressWarnings({"unchecked", "rawtypes"})
EventDispatcher<ServiceListener, FilteredServiceListener, ServiceEvent> dispatcher = (EventDispatcher) entry.getKey();
@@ -1043,7 +1052,11 @@ public class ServiceRegistry {
* Check for permission to listen to a service.
*/
static boolean hasListenServicePermission(ServiceEvent event, BundleContextImpl context) {
- ProtectionDomain domain = context.getBundleImpl().getProtectionDomain();
+ ModuleRevision revision = context.getBundleImpl().getModule().getCurrentRevision();
+ if (revision == null) {
+ return false;
+ }
+ ProtectionDomain domain = ((Generation) revision.getRevisionInfo()).getDomain();
if (domain == null) {
return true;
}
@@ -1125,7 +1138,7 @@ public class ServiceRegistry {
}
void notifyFindHooksPrivileged(final BundleContextImpl context, final String clazz, final String filterstring, final boolean allservices, final Collection<ServiceReference<?>> result) {
- if (Debug.DEBUG_HOOKS) {
+ if (debug.DEBUG_HOOKS) {
Debug.println("notifyServiceFindHooks(" + context.getBundleImpl() + "," + clazz + "," + filterstring + "," + allservices + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
}
notifyHooksPrivileged(new HookContext() {
@@ -1154,7 +1167,7 @@ public class ServiceRegistry {
* @param result The result to return to the caller which may have been shrunk by the EventHooks.
*/
private void notifyEventHooksPrivileged(final ServiceEvent event, final Collection<BundleContext> result) {
- if (Debug.DEBUG_HOOKS) {
+ if (debug.DEBUG_HOOKS) {
Debug.println("notifyServiceEventHooks(" + event.getType() + ":" + event.getServiceReference() + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
notifyHooksPrivileged(new HookContext() {
@@ -1183,7 +1196,7 @@ public class ServiceRegistry {
* @param result The result to return to the caller which may have been shrunk by the EventListenerHooks.
*/
private void notifyEventListenerHooksPrivileged(final ServiceEvent event, final Map<BundleContext, Collection<ListenerInfo>> result) {
- if (Debug.DEBUG_HOOKS) {
+ if (debug.DEBUG_HOOKS) {
Debug.println("notifyServiceEventListenerHooks(" + event.getType() + ":" + event.getServiceReference() + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
notifyHooksPrivileged(new HookContext() {
@@ -1209,11 +1222,6 @@ public class ServiceRegistry {
* @param hookContext Context to use when calling the hook services.
*/
public void notifyHooksPrivileged(HookContext hookContext) {
- BundleContextImpl systemBundleContext = framework.getSystemBundleContext();
- if (systemBundleContext == null) { // if no system bundle context, we are done!
- return;
- }
-
List<ServiceRegistrationImpl<?>> hooks = lookupServiceRegistrations(hookContext.getHookClassName(), null);
// Since the list is already sorted, we don't need to sort the list to call the hooks
// in the proper order.
@@ -1238,14 +1246,14 @@ public class ServiceRegistry {
try {
hookContext.call(hook, registration);
} catch (Throwable t) {
- if (Debug.DEBUG_HOOKS) {
+ if (debug.DEBUG_HOOKS) {
Debug.println(hook.getClass().getName() + "." + hookContext.getHookMethodName() + "() exception: " + t.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
Debug.printStackTrace(t);
}
// allow the adaptor to handle this unexpected error
- framework.getAdaptor().handleRuntimeError(t);
+ container.handleRuntimeError(t);
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, hook.getClass().getName(), hookContext.getHookMethodName()), t);
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
+ container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
} finally {
registration.ungetService(context);
}
@@ -1272,12 +1280,7 @@ public class ServiceRegistry {
}
void notifyNewListenerHookPrivileged(ServiceRegistrationImpl<?> registration) {
- BundleContextImpl systemBundleContext = framework.getSystemBundleContext();
- if (systemBundleContext == null) { // if no system bundle context, we are done!
- return;
- }
-
- if (Debug.DEBUG_HOOKS) {
+ if (debug.DEBUG_HOOKS) {
Debug.println("notifyServiceNewListenerHook(" + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -1335,7 +1338,7 @@ public class ServiceRegistry {
void notifyListenerHooksPrivileged(final Collection<ListenerInfo> listeners, final boolean added) {
assert !listeners.isEmpty();
- if (Debug.DEBUG_HOOKS) {
+ if (debug.DEBUG_HOOKS) {
Debug.println("notifyServiceListenerHooks(" + listeners + "," + (added ? "added" : "removed") + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java
index 2f0bab55c..bf5fc7221 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java
@@ -13,9 +13,9 @@ package org.eclipse.osgi.internal.serviceregistry;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.BundleContextImpl;
import org.eclipse.osgi.framework.internal.core.Msg;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.BundleContextImpl;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
@@ -35,6 +35,7 @@ public class ServiceUse<S> {
final BundleContextImpl context;
/** ServiceDescription of the registered service */
final ServiceRegistrationImpl<S> registration;
+ final Debug debug;
/** Service object either registered or that returned by
ServiceFactory.getService() */
@@ -58,6 +59,7 @@ public class ServiceUse<S> {
* @param registration ServiceRegistration of the service
*/
ServiceUse(BundleContextImpl context, ServiceRegistrationImpl<S> registration) {
+ this.debug = context.getContainer().getConfiguration().getDebug();
this.useCount = 0;
this.factoryInUse = false;
S service = registration.getServiceObject();
@@ -120,17 +122,17 @@ public class ServiceUse<S> {
return cachedService;
}
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("getService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
// check for recursive call
if (factoryInUse == true) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println(factory + ".getService() recursively called."); //$NON-NLS-1$
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_RECURSION, factory.getClass().getName(), "getService"), ServiceException.FACTORY_RECURSION); //$NON-NLS-1$
- context.getFramework().publishFrameworkEvent(FrameworkEvent.WARNING, registration.getBundle(), se);
+ context.getContainer().getEventPublisher().publishFrameworkEvent(FrameworkEvent.WARNING, registration.getBundle(), se);
return null;
}
factoryInUse = true;
@@ -142,37 +144,37 @@ public class ServiceUse<S> {
}
});
} catch (Throwable t) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println(factory + ".getService() exception: " + t.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(t);
}
// allow the adaptor to handle this unexpected error
- context.getFramework().getAdaptor().handleRuntimeError(t);
+ context.getContainer().handleRuntimeError(t);
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "getService"), ServiceException.FACTORY_EXCEPTION, t); //$NON-NLS-1$
- context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
+ context.getContainer().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
return null;
} finally {
factoryInUse = false;
}
if (service == null) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println(factory + ".getService() returned null."); //$NON-NLS-1$
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_OBJECT_NULL_EXCEPTION, factory.getClass().getName()), ServiceException.FACTORY_ERROR);
- context.getFramework().publishFrameworkEvent(FrameworkEvent.WARNING, registration.getBundle(), se);
+ context.getContainer().getEventPublisher().publishFrameworkEvent(FrameworkEvent.WARNING, registration.getBundle(), se);
return null;
}
String[] clazzes = registration.getClasses();
String invalidService = ServiceRegistry.checkServiceClass(clazzes, service);
if (invalidService != null) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_NOT_INSTANCEOF_CLASS_EXCEPTION, factory.getClass().getName(), invalidService), ServiceException.FACTORY_ERROR);
- context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
+ context.getContainer().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
return null;
}
@@ -229,7 +231,7 @@ public class ServiceUse<S> {
final S service = cachedService;
cachedService = null;
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("ungetService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
try {
@@ -240,13 +242,13 @@ public class ServiceUse<S> {
}
});
} catch (Throwable t) {
- if (Debug.DEBUG_GENERAL) {
+ if (debug.DEBUG_GENERAL) {
Debug.println(factory + ".ungetService() exception"); //$NON-NLS-1$
Debug.printStackTrace(t);
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "ungetService"), ServiceException.FACTORY_EXCEPTION, t); //$NON-NLS-1$
- context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
+ context.getContainer().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
}
return true;
@@ -271,7 +273,7 @@ public class ServiceUse<S> {
cachedService = null;
useCount = 0;
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println("releaseService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
try {
@@ -282,13 +284,13 @@ public class ServiceUse<S> {
}
});
} catch (Throwable t) {
- if (Debug.DEBUG_SERVICES) {
+ if (debug.DEBUG_SERVICES) {
Debug.println(factory + ".ungetService() exception"); //$NON-NLS-1$
Debug.printStackTrace(t);
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "ungetService"), ServiceException.FACTORY_EXCEPTION, t); //$NON-NLS-1$
- context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
+ context.getContainer().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
}
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java
index 2c2e6002f..2c2e6002f 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableEntrySetValueCollection.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableEntrySetValueCollection.java
index a98fdce71..a98fdce71 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableEntrySetValueCollection.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableEntrySetValueCollection.java
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableValueCollectionMap.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableValueCollectionMap.java
index d9992605d..d9992605d 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableValueCollectionMap.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ShrinkableValueCollectionMap.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java
index 57b985226..57b985226 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/Base64.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/Base64.java
index 32d09834f..32d09834f 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/Base64.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/Base64.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/DigestedInputStream.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/DigestedInputStream.java
index d244c1681..fe68bd3d9 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/DigestedInputStream.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/DigestedInputStream.java
@@ -14,10 +14,11 @@ package org.eclipse.osgi.internal.signedcontent;
import java.io.FilterInputStream;
import java.io.IOException;
import java.security.MessageDigest;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+import java.security.NoSuchAlgorithmException;
import org.eclipse.osgi.signedcontent.InvalidContentException;
import org.eclipse.osgi.signedcontent.SignerInfo;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;
/**
@@ -41,15 +42,16 @@ class DigestedInputStream extends FilterInputStream {
* @param signerInfos the signers.
* @param results the expected digest.
* @throws IOException
+ * @throws NoSuchAlgorithmException
*/
- DigestedInputStream(BundleEntry entry, BundleFile bundleFile, SignerInfo[] signerInfos, byte results[][], long size) throws IOException {
+ DigestedInputStream(BundleEntry entry, BundleFile bundleFile, SignerInfo[] signerInfos, byte results[][], long size) throws IOException, NoSuchAlgorithmException {
super(entry.getInputStream());
this.entry = entry;
this.bundleFile = bundleFile;
this.remaining = size;
this.digests = new MessageDigest[signerInfos.length];
for (int i = 0; i < signerInfos.length; i++)
- this.digests[i] = SignatureBlockProcessor.getMessageDigest(signerInfos[i].getMessageDigestAlgorithm());
+ this.digests[i] = MessageDigest.getInstance(signerInfos[i].getMessageDigestAlgorithm());
this.result = results;
}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/PKCS7DateParser.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/PKCS7DateParser.java
index 29a82bfa1..29a82bfa1 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/PKCS7DateParser.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/PKCS7DateParser.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/PKCS7Processor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/PKCS7Processor.java
index a1267a8e1..7650083bd 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/PKCS7Processor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/PKCS7Processor.java
@@ -16,7 +16,6 @@ import java.security.cert.Certificate;
import java.text.*;
import java.util.*;
import javax.security.auth.x500.X500Principal;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.util.NLS;
/**
@@ -30,7 +29,8 @@ public class PKCS7Processor implements SignedContentConstants {
try {
certFact = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
} catch (CertificateException e) {
- SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e);
+ // TODO this is bad and will lead to NPEs
+ // Should we just throw a runtime exception to fail <clinit>?
}
}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
index 8f9684147..dc20915ba 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
@@ -14,10 +14,10 @@ import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.signedcontent.SignerInfo;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;
public class SignatureBlockProcessor implements SignedContentConstants {
@@ -27,10 +27,12 @@ public class SignatureBlockProcessor implements SignedContentConstants {
// map of tsa singers keyed by SignerInfo -> {tsa_SignerInfo, signingTime}
private Map<SignerInfo, Object[]> tsaSignerInfos;
private final int supportFlags;
+ private final SignedBundleHook signedBundleHook;
- public SignatureBlockProcessor(SignedBundleFile signedContent, int supportFlags) {
+ public SignatureBlockProcessor(SignedBundleFile signedContent, int supportFlags, SignedBundleHook signedBundleHook) {
this.signedBundle = signedContent;
this.supportFlags = supportFlags;
+ this.signedBundleHook = signedBundleHook;
}
public SignedContentImpl process() throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
@@ -154,7 +156,7 @@ public class SignatureBlockProcessor implements SignedContentConstants {
// check if the the computed digest value of manifest file equals to the digest value in the .sf file
if (!digestValue.equals(manifestDigest)) {
SignatureException se = new SignatureException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] {signedBundle.getBaseFile().toString()}));
- SignedBundleHook.log(se.getMessage(), FrameworkLogEntry.ERROR, se);
+ signedBundleHook.log(se.getMessage(), FrameworkLogEntry.ERROR, se);
throw se;
}
}
@@ -308,11 +310,11 @@ public class SignatureBlockProcessor implements SignedContentConstants {
return new String(Base64.encode(digest.digest(bytes)));
}
- static synchronized MessageDigest getMessageDigest(String algorithm) {
+ synchronized MessageDigest getMessageDigest(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
- SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e);
+ signedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e);
}
return null;
}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
index a271261c4..010ce5b3c 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
@@ -15,14 +15,11 @@ import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.*;
-import java.security.cert.Certificate;
import java.util.Date;
import java.util.Enumeration;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.service.security.TrustEngine;
import org.eclipse.osgi.signedcontent.*;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;
/**
@@ -34,62 +31,25 @@ public class SignedBundleFile extends BundleFile implements SignedContentConstan
private BundleFile wrappedBundleFile;
SignedContentImpl signedContent;
private final int supportFlags;
+ private final SignedBundleHook signedBundleHook;
- SignedBundleFile(SignedContentImpl signedContent, int supportFlags) {
+ SignedBundleFile(SignedContentImpl signedContent, int supportFlags, SignedBundleHook signedBundleHook) {
+ super(null);
this.signedContent = signedContent;
this.supportFlags = supportFlags;
+ this.signedBundleHook = signedBundleHook;
}
void setBundleFile(BundleFile bundleFile) throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
wrappedBundleFile = bundleFile;
if (signedContent == null) {
- SignatureBlockProcessor signatureProcessor = new SignatureBlockProcessor(this, supportFlags);
+ SignatureBlockProcessor signatureProcessor = new SignatureBlockProcessor(this, supportFlags, signedBundleHook);
signedContent = signatureProcessor.process();
if (signedContent != null)
- determineTrust(signedContent, supportFlags);
+ signedBundleHook.determineTrust(signedContent, supportFlags);
}
}
- static void determineTrust(SignedContentImpl trustedContent, int supportFlags) {
- TrustEngine[] engines = null;
- SignerInfo[] signers = trustedContent.getSignerInfos();
- for (int i = 0; i < signers.length; i++) {
- // first check if we need to find an anchor
- if (signers[i].getTrustAnchor() == null) {
- // no anchor set ask the trust engines
- if (engines == null)
- engines = SignedBundleHook.getTrustEngines();
- // check trust of singer certs
- Certificate[] signerCerts = signers[i].getCertificateChain();
- ((SignerInfoImpl) signers[i]).setTrustAnchor(findTrustAnchor(signerCerts, engines, supportFlags));
- // if signer has a tsa check trust of tsa certs
- SignerInfo tsaSignerInfo = trustedContent.getTSASignerInfo(signers[i]);
- if (tsaSignerInfo != null) {
- Certificate[] tsaCerts = tsaSignerInfo.getCertificateChain();
- ((SignerInfoImpl) tsaSignerInfo).setTrustAnchor(findTrustAnchor(tsaCerts, engines, supportFlags));
- }
- }
- }
- }
-
- private static Certificate findTrustAnchor(Certificate[] certs, TrustEngine[] engines, int supportFlags) {
- if ((supportFlags & SignedBundleHook.VERIFY_TRUST) == 0)
- // we are not searching the engines; in this case we just assume the root cert is trusted
- return certs != null && certs.length > 0 ? certs[certs.length - 1] : null;
- for (int i = 0; i < engines.length; i++) {
- try {
- Certificate anchor = engines[i].findTrustAnchor(certs);
- if (anchor != null)
- // found an anchor
- return anchor;
- } catch (IOException e) {
- // log the exception and continue
- SignedBundleHook.log("TrustEngine failure: " + engines[i].getName(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
- }
- }
- return null;
- }
-
public File getFile(String path, boolean nativeCode) {
return wrappedBundleFile.getFile(path, nativeCode);
}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java
index 58e417df1..f2b89af1c 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java
@@ -12,90 +12,89 @@ package org.eclipse.osgi.internal.signedcontent;
import java.io.File;
import java.io.IOException;
-import java.net.*;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.security.*;
+import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.*;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.provisional.service.security.AuthorizationEngine;
-import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifierFactory;
-import org.eclipse.osgi.internal.service.security.DefaultAuthorizationEngine;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.hookregistry.*;
import org.eclipse.osgi.internal.service.security.KeyStoreTrustEngine;
+import org.eclipse.osgi.internal.signedcontent.SignedStorageHook.StorageHookImpl;
import org.eclipse.osgi.service.security.TrustEngine;
-import org.eclipse.osgi.signedcontent.SignedContent;
-import org.eclipse.osgi.signedcontent.SignedContentFactory;
+import org.eclipse.osgi.signedcontent.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.*;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
-import org.osgi.framework.Constants;
import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* Implements signed bundle hook support for the framework
*/
-public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHook, HookConfigurator, SignedContentFactory {
+public class SignedBundleHook implements ActivatorHookFactory, BundleFileWrapperFactoryHook, HookConfigurator, SignedContentFactory {
static final int VERIFY_CERTIFICATE = 0x01;
static final int VERIFY_TRUST = 0x02;
static final int VERIFY_RUNTIME = 0x04;
- static final int VERIFY_AUTHORITY = 0x08;
- static final int VERIFY_ALL = VERIFY_CERTIFICATE | VERIFY_TRUST | VERIFY_RUNTIME | VERIFY_AUTHORITY;
- private static String SUPPORT_CERTIFICATE = "certificate"; //$NON-NLS-1$
- private static String SUPPORT_TRUST = "trust"; //$NON-NLS-1$
- private static String SUPPORT_RUNTIME = "runtime"; //$NON-NLS-1$
- private static String SUPPORT_AUTHORITY = "authority"; //$NON-NLS-1$
- private static String SUPPORT_ALL = "all"; //$NON-NLS-1$
- private static String SUPPORT_TRUE = "true"; //$NON-NLS-1$
+ static final int VERIFY_ALL = VERIFY_CERTIFICATE | VERIFY_TRUST | VERIFY_RUNTIME;
+ private final static String SUPPORT_CERTIFICATE = "certificate"; //$NON-NLS-1$
+ private final static String SUPPORT_TRUST = "trust"; //$NON-NLS-1$
+ private final static String SUPPORT_RUNTIME = "runtime"; //$NON-NLS-1$
+ private final static String SUPPORT_ALL = "all"; //$NON-NLS-1$
+ private final static String SUPPORT_TRUE = "true"; //$NON-NLS-1$
//TODO: comes from configuration!;
- private static String CACERTS_PATH = System.getProperty("java.home") + File.separatorChar + "lib" + File.separatorChar + "security" + File.separatorChar + "cacerts"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$
- private static String CACERTS_TYPE = "JKS"; //$NON-NLS-1$
- private static ServiceTracker<TrustEngine, TrustEngine> trustEngineTracker;
- private static BaseAdaptor ADAPTOR;
- private static String SIGNED_BUNDLE_SUPPORT = "osgi.support.signature.verify"; //$NON-NLS-1$
- private static String SIGNED_CONTENT_SUPPORT = "osgi.signedcontent.support"; //$NON-NLS-1$
- private static String OSGI_KEYSTORE = "osgi.framework.keystore"; //$NON-NLS-1$
- private static int supportSignedBundles;
- private TrustEngineListener trustEngineListener;
- private BundleInstallListener installListener;
+ private final static String CACERTS_PATH = System.getProperty("java.home") + File.separatorChar + "lib" + File.separatorChar + "security" + File.separatorChar + "cacerts"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$
+ private final static String CACERTS_TYPE = "JKS"; //$NON-NLS-1$
+ private final static String SIGNED_BUNDLE_SUPPORT = "osgi.support.signature.verify"; //$NON-NLS-1$
+ private final static String SIGNED_CONTENT_SUPPORT = "osgi.signedcontent.support"; //$NON-NLS-1$
+ private final static String OSGI_KEYSTORE = "osgi.framework.keystore"; //$NON-NLS-1$
+ private int supportSignedBundles;
+ TrustEngineListener trustEngineListener;
+ private String trustEngineNameProp;
private ServiceRegistration<?> signedContentFactoryReg;
private ServiceRegistration<?> systemTrustEngineReg;
- private ServiceRegistration<?> defaultAuthEngineReg;
private List<ServiceRegistration<?>> osgiTrustEngineReg;
- private ServiceRegistration<?> legacyFactoryReg;
+ private ServiceTracker<TrustEngine, TrustEngine> trustEngineTracker;
+ private BundleContext context;
+ private EquinoxContainer container;
- public void initialize(BaseAdaptor adaptor) {
- SignedBundleHook.ADAPTOR = adaptor;
+ @Override
+ public BundleActivator createActivator() {
+ return new BundleActivator() {
+
+ @Override
+ public void start(BundleContext bc) throws Exception {
+ frameworkStart(bc);
+ }
+
+ @Override
+ public void stop(BundleContext bc) throws Exception {
+ frameworkStop(bc);
+ }
+ };
}
- /**
- * @throws BundleException
- */
- public void frameworkStart(BundleContext context) throws BundleException {
- // check if load time authority is enabled
- if ((supportSignedBundles & VERIFY_AUTHORITY) != 0) {
- // install the default bundle install listener
- installListener = new BundleInstallListener();
- context.addBundleListener(installListener);
- // register the default authorization engine
- Dictionary<String, Object> properties = new Hashtable<String, Object>(7);
- properties.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE));
- properties.put(SignedContentConstants.AUTHORIZATION_ENGINE, SignedContentConstants.DEFAULT_AUTHORIZATION_ENGINE);
- defaultAuthEngineReg = context.registerService(AuthorizationEngine.class.getName(), new DefaultAuthorizationEngine(context, ADAPTOR.getState()), properties);
- }
+ BundleContext getContext() {
+ return context;
+ }
+ void frameworkStart(BundleContext bc) {
+ this.context = bc;
+ if ((supportSignedBundles & VERIFY_TRUST) != 0)
+ // initialize the trust engine listener only if trust is being established with a trust engine
+ trustEngineListener = new TrustEngineListener(context, this);
// always register the trust engine
Dictionary<String, Object> trustEngineProps = new Hashtable<String, Object>(7);
trustEngineProps.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE));
trustEngineProps.put(SignedContentConstants.TRUST_ENGINE, SignedContentConstants.DEFAULT_TRUST_ENGINE);
- KeyStoreTrustEngine systemTrustEngine = new KeyStoreTrustEngine(CACERTS_PATH, CACERTS_TYPE, null, "System"); //$NON-NLS-1$
+ KeyStoreTrustEngine systemTrustEngine = new KeyStoreTrustEngine(CACERTS_PATH, CACERTS_TYPE, null, "System", this); //$NON-NLS-1$
systemTrustEngineReg = context.registerService(TrustEngine.class.getName(), systemTrustEngine, trustEngineProps);
String osgiTrustPath = context.getProperty(OSGI_KEYSTORE);
if (osgiTrustPath != null) {
@@ -105,10 +104,10 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
trustEngineProps.put(SignedContentConstants.TRUST_ENGINE, OSGI_KEYSTORE);
String path = url.getPath();
osgiTrustEngineReg = new ArrayList<ServiceRegistration<?>>(1);
- osgiTrustEngineReg.add(context.registerService(TrustEngine.class.getName(), new KeyStoreTrustEngine(path, CACERTS_TYPE, null, OSGI_KEYSTORE), trustEngineProps));
+ osgiTrustEngineReg.add(context.registerService(TrustEngine.class.getName(), new KeyStoreTrustEngine(path, CACERTS_TYPE, null, OSGI_KEYSTORE, this), trustEngineProps));
}
} catch (MalformedURLException e) {
- SignedBundleHook.log("Invalid setting for " + OSGI_KEYSTORE, FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
+ log("Invalid setting for " + OSGI_KEYSTORE, FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
}
} else {
String osgiTrustRepoPaths = context.getProperty(Constants.FRAMEWORK_TRUST_REPOSITORIES);
@@ -118,26 +117,15 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
osgiTrustEngineReg = new ArrayList<ServiceRegistration<?>>(1);
while (st.hasMoreTokens()) {
String trustRepoPath = st.nextToken();
- osgiTrustEngineReg.add(context.registerService(TrustEngine.class.getName(), new KeyStoreTrustEngine(trustRepoPath, CACERTS_TYPE, null, OSGI_KEYSTORE), trustEngineProps));
+ osgiTrustEngineReg.add(context.registerService(TrustEngine.class.getName(), new KeyStoreTrustEngine(trustRepoPath, CACERTS_TYPE, null, OSGI_KEYSTORE, this), trustEngineProps));
}
}
}
- if ((supportSignedBundles & VERIFY_TRUST) != 0)
- // initialize the trust engine listener only if trust is being established with a trust engine
- trustEngineListener = new TrustEngineListener(context);
// always register the signed content factory
signedContentFactoryReg = context.registerService(SignedContentFactory.class.getName(), this, null);
- legacyFactoryReg = context.registerService(CertificateVerifierFactory.class.getName(), new LegacyVerifierFactory(this), null);
}
- /**
- * @throws BundleException
- */
- public void frameworkStop(BundleContext context) throws BundleException {
- if (legacyFactoryReg != null) {
- legacyFactoryReg.unregister();
- legacyFactoryReg = null;
- }
+ void frameworkStop(BundleContext bc) {
if (signedContentFactoryReg != null) {
signedContentFactoryReg.unregister();
signedContentFactoryReg = null;
@@ -151,61 +139,26 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
it.next().unregister();
osgiTrustEngineReg = null;
}
- if (defaultAuthEngineReg != null) {
- defaultAuthEngineReg.unregister();
- defaultAuthEngineReg = null;
- }
- if (trustEngineListener != null) {
- trustEngineListener.stopTrustEngineListener();
- trustEngineListener = null;
- }
- if (installListener != null) {
- context.removeBundleListener(installListener);
- installListener = null;
- }
if (trustEngineTracker != null) {
trustEngineTracker.close();
trustEngineTracker = null;
}
}
- public void frameworkStopping(BundleContext context) {
- // do nothing
- }
-
- public void addProperties(Properties properties) {
- // do nothing
- }
-
- /**
- * @throws IOException
- */
- public URLConnection mapLocationToURLConnection(String location) throws IOException {
- return null;
- }
-
- public void handleRuntimeError(Throwable error) {
- // do nothing
- }
-
- public FrameworkLog createFrameworkLog() {
- return null;
- }
-
- public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) {
+ public BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base) {
try {
if (bundleFile != null) {
- SignedStorageHook hook = (SignedStorageHook) data.getStorageHook(SignedStorageHook.KEY);
+ StorageHookImpl hook = generation.getStorageHook(SignedStorageHook.class);
SignedBundleFile signedBaseFile;
if (base && hook != null) {
- signedBaseFile = new SignedBundleFile(hook.signedContent, supportSignedBundles);
+ signedBaseFile = new SignedBundleFile(hook.signedContent, supportSignedBundles, this);
if (hook.signedContent == null) {
signedBaseFile.setBundleFile(bundleFile);
SignedContentImpl signedContent = signedBaseFile.getSignedContent();
hook.signedContent = signedContent != null && signedContent.isSigned() ? signedContent : null;
}
} else
- signedBaseFile = new SignedBundleFile(null, supportSignedBundles);
+ signedBaseFile = new SignedBundleFile(null, supportSignedBundles, this);
signedBaseFile.setBundleFile(bundleFile);
SignedContentImpl signedContent = signedBaseFile.getSignedContent();
if (signedContent != null && signedContent.isSigned()) {
@@ -215,16 +168,17 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
}
}
} catch (IOException e) {
- SignedBundleHook.log("Bad bundle file: " + bundleFile.getBaseFile(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
+ log("Bad bundle file: " + bundleFile.getBaseFile(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
} catch (GeneralSecurityException e) {
- SignedBundleHook.log("Bad bundle file: " + bundleFile.getBaseFile(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
+ log("Bad bundle file: " + bundleFile.getBaseFile(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
}
return bundleFile;
}
public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addAdaptorHook(this);
- String[] support = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(SIGNED_CONTENT_SUPPORT, FrameworkProperties.getProperty(SIGNED_BUNDLE_SUPPORT)), ","); //$NON-NLS-1$
+ container = hookRegistry.getContainer();
+ hookRegistry.addActivatorHookFactory(this);
+ String[] support = ManifestElement.getArrayFromList(hookRegistry.getConfiguration().getConfiguration(SIGNED_CONTENT_SUPPORT, hookRegistry.getConfiguration().getConfiguration(SIGNED_BUNDLE_SUPPORT)), ","); //$NON-NLS-1$
for (int i = 0; i < support.length; i++) {
if (SUPPORT_CERTIFICATE.equals(support[i]))
supportSignedBundles |= VERIFY_CERTIFICATE;
@@ -232,13 +186,13 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
supportSignedBundles |= VERIFY_CERTIFICATE | VERIFY_TRUST;
else if (SUPPORT_RUNTIME.equals(support[i]))
supportSignedBundles |= VERIFY_CERTIFICATE | VERIFY_RUNTIME;
- else if (SUPPORT_AUTHORITY.equals(support[i]))
- supportSignedBundles |= VERIFY_CERTIFICATE | VERIFY_TRUST | VERIFY_AUTHORITY;
else if (SUPPORT_TRUE.equals(support[i]) || SUPPORT_ALL.equals(support[i]))
supportSignedBundles |= VERIFY_ALL;
}
+ trustEngineNameProp = hookRegistry.getConfiguration().getConfiguration(SignedContentConstants.TRUST_ENGINE);
+
if ((supportSignedBundles & VERIFY_CERTIFICATE) != 0) {
- hookRegistry.addStorageHook(new SignedStorageHook());
+ hookRegistry.addStorageHookFactory(new SignedStorageHook());
hookRegistry.addBundleFileWrapperFactoryHook(this);
}
}
@@ -250,8 +204,8 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
if (content.isDirectory())
contentBundleFile = new DirBundleFile(content);
else
- contentBundleFile = new ZipBundleFile(content, null);
- SignedBundleFile result = new SignedBundleFile(null, VERIFY_ALL);
+ contentBundleFile = new ZipBundleFile(content, null, null, container.getConfiguration().getDebug());
+ SignedBundleFile result = new SignedBundleFile(null, VERIFY_ALL, this);
try {
result.setBundleFile(contentBundleFile);
} catch (InvalidKeyException e) {
@@ -269,20 +223,18 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
}
public SignedContent getSignedContent(Bundle bundle) throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException, IllegalArgumentException {
- final BundleData data = ((AbstractBundle) bundle).getBundleData();
- if (!(data instanceof BaseData))
- throw new IllegalArgumentException("Invalid bundle object. No BaseData found."); //$NON-NLS-1$
- SignedStorageHook hook = (SignedStorageHook) ((BaseData) data).getStorageHook(SignedStorageHook.KEY);
+ final Generation generation = (Generation) ((EquinoxBundle) bundle).getModule().getCurrentRevision().getRevisionInfo();
+ StorageHookImpl hook = generation.getStorageHook(SignedStorageHook.class);
SignedContent result = hook != null ? hook.signedContent : null;
if (result != null)
return result; // just reuse the signed content the storage hook
// must create a new signed content using the raw file
if (System.getSecurityManager() == null)
- return getSignedContent(((BaseData) data).getBundleFile().getBaseFile());
+ return getSignedContent(generation.getBundleFile().getBaseFile());
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<SignedContent>() {
public SignedContent run() throws Exception {
- return getSignedContent(((BaseData) data).getBundleFile().getBaseFile());
+ return getSignedContent(generation.getBundleFile().getBaseFile());
}
});
} catch (PrivilegedActionException e) {
@@ -302,41 +254,27 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
}
}
- public static void log(String msg, int severity, Throwable t) {
- if (SignedBundleHook.ADAPTOR == null) {
- System.err.println(msg);
- t.printStackTrace();
- return;
- }
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, severity, 0, msg, 0, t, null);
- SignedBundleHook.ADAPTOR.getFrameworkLog().log(entry);
- }
-
- static BundleContext getContext() {
- if (ADAPTOR == null)
- return null;
- return ADAPTOR.getContext();
+ public void log(String msg, int severity, Throwable t) {
+ container.getLogServices().log(EquinoxContainer.NAME, severity, msg, t);
}
- static TrustEngine[] getTrustEngines() {
+ private TrustEngine[] getTrustEngines() {
// find all the trust engines available
- BundleContext context = SignedBundleHook.getContext();
if (context == null)
return new TrustEngine[0];
if (trustEngineTracker == null) {
// read the trust provider security property
- String trustEngineProp = FrameworkProperties.getProperty(SignedContentConstants.TRUST_ENGINE);
Filter filter = null;
- if (trustEngineProp != null)
+ if (trustEngineNameProp != null)
try {
- filter = FilterImpl.newInstance("(&(" + Constants.OBJECTCLASS + "=" + TrustEngine.class.getName() + ")(" + SignedContentConstants.TRUST_ENGINE + "=" + trustEngineProp + "))"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$
+ filter = context.createFilter("(&(" + Constants.OBJECTCLASS + "=" + TrustEngine.class.getName() + ")(" + SignedContentConstants.TRUST_ENGINE + "=" + trustEngineNameProp + "))"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$
} catch (InvalidSyntaxException e) {
- SignedBundleHook.log("Invalid trust engine filter", FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
+ log("Invalid trust engine filter", FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
}
if (filter != null) {
- trustEngineTracker = new ServiceTracker<TrustEngine, TrustEngine>(context, filter, null);
+ trustEngineTracker = new ServiceTracker<TrustEngine, TrustEngine>(context, filter, new TrustEngineCustomizer());
} else
- trustEngineTracker = new ServiceTracker<TrustEngine, TrustEngine>(context, TrustEngine.class.getName(), null);
+ trustEngineTracker = new ServiceTracker<TrustEngine, TrustEngine>(context, TrustEngine.class.getName(), new TrustEngineCustomizer());
trustEngineTracker.open();
}
Object[] services = trustEngineTracker.getServices();
@@ -347,4 +285,74 @@ public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHo
}
return new TrustEngine[0];
}
+
+ class TrustEngineCustomizer implements ServiceTrackerCustomizer<TrustEngine, TrustEngine> {
+
+ @Override
+ public TrustEngine addingService(ServiceReference<TrustEngine> reference) {
+ TrustEngine engine = getContext().getService(reference);
+ if (engine != null) {
+ try {
+ Field trustEngineListenerField = TrustEngine.class.getDeclaredField("trustEngineListener"); //$NON-NLS-1$
+ trustEngineListenerField.setAccessible(true);
+ trustEngineListenerField.set(engine, SignedBundleHook.this.trustEngineListener);
+ } catch (Exception e) {
+ log("Unable to set the trust engine listener.", FrameworkLogEntry.ERROR, e); //$NON-NLS-1$
+ }
+
+ }
+ return engine;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<TrustEngine> reference, TrustEngine service) {
+ // nothing
+ }
+
+ @Override
+ public void removedService(ServiceReference<TrustEngine> reference, TrustEngine service) {
+ // nothing
+ }
+
+ }
+
+ void determineTrust(SignedContentImpl trustedContent, int supportFlags) {
+ TrustEngine[] engines = null;
+ SignerInfo[] signers = trustedContent.getSignerInfos();
+ for (int i = 0; i < signers.length; i++) {
+ // first check if we need to find an anchor
+ if (signers[i].getTrustAnchor() == null) {
+ // no anchor set ask the trust engines
+ if (engines == null)
+ engines = getTrustEngines();
+ // check trust of singer certs
+ Certificate[] signerCerts = signers[i].getCertificateChain();
+ ((SignerInfoImpl) signers[i]).setTrustAnchor(findTrustAnchor(signerCerts, engines, supportFlags));
+ // if signer has a tsa check trust of tsa certs
+ SignerInfo tsaSignerInfo = trustedContent.getTSASignerInfo(signers[i]);
+ if (tsaSignerInfo != null) {
+ Certificate[] tsaCerts = tsaSignerInfo.getCertificateChain();
+ ((SignerInfoImpl) tsaSignerInfo).setTrustAnchor(findTrustAnchor(tsaCerts, engines, supportFlags));
+ }
+ }
+ }
+ }
+
+ private Certificate findTrustAnchor(Certificate[] certs, TrustEngine[] engines, int supportFlags) {
+ if ((supportFlags & SignedBundleHook.VERIFY_TRUST) == 0)
+ // we are not searching the engines; in this case we just assume the root cert is trusted
+ return certs != null && certs.length > 0 ? certs[certs.length - 1] : null;
+ for (int i = 0; i < engines.length; i++) {
+ try {
+ Certificate anchor = engines[i].findTrustAnchor(certs);
+ if (anchor != null)
+ // found an anchor
+ return anchor;
+ } catch (IOException e) {
+ // log the exception and continue
+ log("TrustEngine failure: " + engines[i].getName(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentConstants.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentConstants.java
index 115621a91..38302584e 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentConstants.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentConstants.java
@@ -59,10 +59,6 @@ public interface SignedContentConstants {
public static final String TRUST_ENGINE = "osgi.signedcontent.trust.engine"; //$NON-NLS-1$
public static final Object DEFAULT_TRUST_ENGINE = "org.eclipse.osgi"; //$NON-NLS-1$
- // constants for authorization engine service
- public static final String AUTHORIZATION_ENGINE = "osgi.signedcontent.authorization.engine"; //$NON-NLS-1$
- public static final Object DEFAULT_AUTHORIZATION_ENGINE = "org.eclipse.osgi"; //$NON-NLS-1$
-
// constant for the timestamp related
public static final int TIMESTAMP_OID[] = {1, 2, 840, 113549, 1, 9, 16, 2, 14};
public static final int TIMESTAMP_TST_OID[] = {1, 2, 840, 113549, 1, 9, 16, 1, 4};
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentFile.java
index fdf572cf7..fdf572cf7 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentFile.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java
index af03ea893..64f6a01e3 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java
@@ -10,11 +10,12 @@ package org.eclipse.osgi.internal.signedcontent;
import java.io.IOException;
import java.io.InputStream;
+import java.security.NoSuchAlgorithmException;
import java.security.cert.*;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.signedcontent.*;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;
public class SignedContentImpl implements SignedContent {
@@ -125,7 +126,11 @@ public class SignedContentImpl implements SignedContent {
Object[] mdResult = (Object[]) contentMDResults.get(nestedEntry.getName());
if (mdResult == null)
return null;
- return new DigestedInputStream(nestedEntry, content, (SignerInfo[]) mdResult[0], (byte[][]) mdResult[1], nestedEntry.getSize());
+ try {
+ return new DigestedInputStream(nestedEntry, content, (SignerInfo[]) mdResult[0], (byte[][]) mdResult[1], nestedEntry.getSize());
+ } catch (NoSuchAlgorithmException e) {
+ throw new IOException(e);
+ }
}
public class SignedContentEntryImpl implements SignedContentEntry {
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.java
index 28cab184d..28cab184d 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties
index 47dace892..47dace892 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java
new file mode 100644
index 000000000..df5cbbab7
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.osgi.internal.signedcontent;
+
+import java.io.*;
+import java.security.cert.*;
+import java.util.*;
+import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
+import org.eclipse.osgi.signedcontent.SignedContent;
+import org.eclipse.osgi.signedcontent.SignerInfo;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.osgi.framework.BundleException;
+
+public class SignedStorageHook extends StorageHookFactory<List<SignerInfo>, List<SignerInfo>, SignedStorageHook.StorageHookImpl> {
+ private static final int STORAGE_VERSION = 4;
+
+ public int getStorageVersion() {
+ return STORAGE_VERSION;
+ }
+
+ @Override
+ public List<SignerInfo> createSaveContext() {
+ return new ArrayList<SignerInfo>();
+ }
+
+ @Override
+ public List<SignerInfo> createLoadContext(int version) {
+ return new ArrayList<SignerInfo>();
+ }
+
+ @Override
+ public StorageHookImpl createStorageHook(Generation generation) {
+ return new StorageHookImpl(generation);
+ }
+
+ static class StorageHookImpl extends StorageHookFactory.StorageHook<List<SignerInfo>, List<SignerInfo>> {
+ SignedContentImpl signedContent;
+
+ public StorageHookImpl(Generation generation) {
+ super(generation, SignedStorageHook.class);
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ public void initialize(Dictionary<String, String> manifest) throws BundleException {
+ // do nothing
+ }
+
+ @Override
+ public void load(List<SignerInfo> loadContext, DataInputStream is) throws IOException {
+ boolean signed = is.readBoolean();
+ if (!signed)
+ return;
+ int numSigners = is.readInt();
+ SignerInfo[] signerInfos = new SignerInfo[numSigners];
+ for (int i = 0; i < numSigners; i++)
+ signerInfos[i] = readSignerInfo(is, loadContext);
+
+ int resultsSize = is.readInt();
+ Map<String, Object> contentMDResults = null;
+ if (resultsSize > 0) {
+ contentMDResults = new HashMap<String, Object>(resultsSize);
+ for (int i = 0; i < resultsSize; i++) {
+ String path = is.readUTF();
+ int numEntrySigners = is.readInt();
+ SignerInfo[] entrySigners = new SignerInfo[numEntrySigners];
+ byte[][] entryResults = new byte[numEntrySigners][];
+ for (int j = 0; j < numEntrySigners; j++) {
+ entrySigners[j] = readSignerInfo(is, loadContext);
+ int resultSize = is.readInt();
+ entryResults[j] = new byte[resultSize];
+ is.readFully(entryResults[j]);
+ }
+ contentMDResults.put(path, new Object[] {entrySigners, entryResults});
+ }
+ }
+ SignedContentImpl result = new SignedContentImpl(signerInfos, contentMDResults);
+ for (int i = 0; i < numSigners; i++) {
+ boolean hasTSA = is.readBoolean();
+ if (!hasTSA)
+ continue;
+ SignerInfo tsaSigner = readSignerInfo(is, loadContext);
+ Date signingDate = new Date(is.readLong());
+ result.addTSASignerInfo(signerInfos[i], tsaSigner, signingDate);
+ }
+ signedContent = result;
+ }
+
+ private SignerInfo readSignerInfo(DataInputStream is, List<SignerInfo> loadContext) throws IOException {
+ int index = is.readInt();
+ if (index >= 0)
+ return loadContext.get(index);
+ int numCerts = is.readInt();
+ Certificate[] certs = new Certificate[numCerts];
+ for (int i = 0; i < numCerts; i++) {
+ int certSize = is.readInt();
+ byte[] certBytes = new byte[certSize];
+ is.readFully(certBytes);
+ try {
+ certs[i] = PKCS7Processor.certFact.generateCertificate(new ByteArrayInputStream(certBytes));
+ } catch (CertificateException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ }
+ int anchorIdx = is.readInt();
+ SignerInfoImpl result = new SignerInfoImpl(certs, anchorIdx >= 0 ? certs[anchorIdx] : null, is.readUTF());
+ loadContext.add(result);
+ return result;
+ }
+
+ @Override
+ public void save(List<SignerInfo> saveContext, DataOutputStream os) throws IOException {
+ os.writeBoolean(signedContent != null);
+ if (signedContent == null)
+ return;
+ SignerInfo[] signerInfos = signedContent.getSignerInfos();
+ os.writeInt(signerInfos.length);
+ for (int i = 0; i < signerInfos.length; i++)
+ saveSignerInfo(signerInfos[i], os, saveContext);
+
+ // keyed by entry path -> {SignerInfo[] infos, byte[][] results)}
+ Map<String, Object> contentMDResults = signedContent.getContentMDResults();
+ os.writeInt(contentMDResults == null ? -1 : contentMDResults.size());
+ if (contentMDResults != null)
+ for (Map.Entry<String, Object> entry : contentMDResults.entrySet()) {
+ String path = entry.getKey();
+ os.writeUTF(path);
+ Object[] signerResults = (Object[]) entry.getValue();
+ SignerInfo[] entrySigners = (SignerInfo[]) signerResults[0];
+ byte[][] entryResults = (byte[][]) signerResults[1];
+ os.writeInt(entrySigners.length);
+ for (int i = 0; i < entrySigners.length; i++) {
+ saveSignerInfo(entrySigners[i], os, saveContext);
+ os.writeInt(entryResults[i].length);
+ os.write(entryResults[i]);
+ }
+ }
+
+ for (int i = 0; i < signerInfos.length; i++) {
+ SignerInfo tsaInfo = signedContent.getTSASignerInfo(signerInfos[i]);
+ os.writeBoolean(tsaInfo != null);
+ if (tsaInfo == null)
+ continue;
+ saveSignerInfo(tsaInfo, os, saveContext);
+ Date signingTime = signedContent.getSigningTime(signerInfos[i]);
+ os.writeLong(signingTime != null ? signingTime.getTime() : Long.MIN_VALUE);
+ }
+ }
+
+ private void saveSignerInfo(SignerInfo signerInfo, DataOutputStream os, List<SignerInfo> saveContext) throws IOException {
+ int cacheIdx = saveContext.indexOf(signerInfo);
+ os.writeInt(cacheIdx);
+ if (cacheIdx >= 0)
+ return;
+ Certificate[] certs = signerInfo.getCertificateChain();
+ int anchorIndex = -1;
+ os.writeInt(certs == null ? 0 : certs.length);
+ if (certs != null)
+ for (int i = 0; i < certs.length; i++) {
+ if (certs[i].equals(signerInfo.getTrustAnchor()))
+ anchorIndex = i;
+ byte[] certBytes;
+ try {
+ certBytes = certs[i].getEncoded();
+ } catch (CertificateEncodingException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ os.writeInt(certBytes.length);
+ os.write(certBytes);
+ }
+ os.writeInt(anchorIndex);
+ os.writeUTF(signerInfo.getMessageDigestAlgorithm());
+ saveContext.add(signerInfo);
+ }
+
+ public SignedContent getSignedContent() {
+ return signedContent;
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignerInfoImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignerInfoImpl.java
index 84673b14e..84673b14e 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignerInfoImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignerInfoImpl.java
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java
new file mode 100644
index 000000000..f5746e133
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.osgi.internal.signedcontent;
+
+import java.security.cert.Certificate;
+import java.util.*;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
+import org.eclipse.osgi.internal.signedcontent.SignedStorageHook.StorageHookImpl;
+import org.eclipse.osgi.signedcontent.SignerInfo;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class TrustEngineListener {
+ private final BundleContext context;
+ private final SignedBundleHook signedBundleHook;
+
+ TrustEngineListener(BundleContext context, SignedBundleHook signedBundleHook) {
+ this.context = context;
+ this.signedBundleHook = signedBundleHook;
+ }
+
+ public void addedTrustAnchor(Certificate anchor) {
+ // find any SignedContent with SignerInfos that do not have an anchor;
+ // re-evaluate trust and check authorization for these SignedContents
+ Bundle[] bundles = context.getBundles();
+ for (int i = 0; i < bundles.length; i++) {
+ SignedContentImpl signedContent = getSignedContent(bundles[i]);
+ if (signedContent != null && signedContent.isSigned()) {
+ // check the SignerInfos for this content
+ SignerInfo[] infos = signedContent.getSignerInfos();
+ for (int j = 0; j < infos.length; j++) {
+ if (infos[j].getTrustAnchor() == null) {
+ // one of the signers is not trusted
+ signedBundleHook.determineTrust(signedContent, SignedBundleHook.VERIFY_TRUST);
+ } else {
+ SignerInfo tsa = signedContent.getTSASignerInfo(infos[j]);
+ if (tsa != null && tsa.getTrustAnchor() == null)
+ // one of the tsa signers is not trusted
+ signedBundleHook.determineTrust(signedContent, SignedBundleHook.VERIFY_TRUST);
+ }
+ }
+ }
+ }
+ }
+
+ public void removedTrustAnchor(Certificate anchor) {
+ // find any signed content that has signerinfos with the supplied anchor
+ // re-evaluate trust and check authorization again.
+ Bundle[] bundles = context.getBundles();
+ Set<Bundle> usingAnchor = new HashSet<Bundle>();
+ Set<SignerInfo> untrustedSigners = new HashSet<SignerInfo>();
+ for (int i = 0; i < bundles.length; i++) {
+ SignedContentImpl signedContent = getSignedContent(bundles[i]);
+ if (signedContent != null && signedContent.isSigned()) {
+ // check signer infos for this content
+ SignerInfo[] infos = signedContent.getSignerInfos();
+ for (int j = 0; j < infos.length; j++) {
+ if (anchor.equals(infos[j].getTrustAnchor())) {
+ // one of the signers uses this anchor
+ untrustedSigners.add(infos[j]);
+ usingAnchor.add(bundles[i]);
+ }
+ SignerInfo tsa = signedContent.getTSASignerInfo(infos[j]);
+ if (tsa != null && anchor.equals(tsa.getTrustAnchor())) {
+ // one of the tsa signers uses this anchor
+ usingAnchor.add(bundles[i]);
+ untrustedSigners.add(tsa);
+ }
+ }
+ }
+ }
+ // remove trust anchors from untrusted signers
+ for (Iterator<SignerInfo> untrusted = untrustedSigners.iterator(); untrusted.hasNext();)
+ ((SignerInfoImpl) untrusted.next()).setTrustAnchor(null);
+ // re-establish trust
+ for (Iterator<Bundle> untrustedBundles = usingAnchor.iterator(); untrustedBundles.hasNext();) {
+ Bundle bundle = untrustedBundles.next();
+ SignedContentImpl signedContent = getSignedContent(bundle);
+ // found an signer using the anchor for this bundle re-evaluate trust
+ signedBundleHook.determineTrust(signedContent, SignedBundleHook.VERIFY_TRUST);
+ }
+ }
+
+ private SignedContentImpl getSignedContent(Bundle bundle) {
+ Generation generation = (Generation) ((EquinoxBundle) bundle).getModule().getCurrentRevision().getRevisionInfo();
+ StorageHookImpl hook = generation.getStorageHook(SignedStorageHook.class);
+ return hook != null ? hook.signedContent : null;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ContentHandlerFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/ContentHandlerFactoryImpl.java
index c84f76da1..5acc2ca26 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ContentHandlerFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/ContentHandlerFactoryImpl.java
@@ -9,15 +9,15 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.lang.reflect.Method;
import java.net.ContentHandler;
import java.net.URLConnection;
import java.util.*;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -31,21 +31,20 @@ import org.osgi.util.tracker.ServiceTracker;
* will search the service registry for a maching Content-Handler and, if found, return a
* proxy for that content handler.
*/
-// TODO rename this class!!! its really confusing to name the impl the same as the interface
-public class ContentHandlerFactory extends MultiplexingFactory implements java.net.ContentHandlerFactory {
+public class ContentHandlerFactoryImpl extends MultiplexingFactory implements java.net.ContentHandlerFactory {
private ServiceTracker<ContentHandler, ContentHandler> contentHandlerTracker;
private static final String contentHandlerClazz = "java.net.ContentHandler"; //$NON-NLS-1$
private static final String CONTENT_HANDLER_PKGS = "java.content.handler.pkgs"; //$NON-NLS-1$
private static final String DEFAULT_VM_CONTENT_HANDLERS = "sun.net.www.content"; //$NON-NLS-1$
- private static final List<Class<?>> ignoredClasses = Arrays.asList(new Class<?>[] {MultiplexingContentHandler.class, ContentHandlerFactory.class, URLConnection.class});
+ private static final List<Class<?>> ignoredClasses = Arrays.asList(new Class<?>[] {MultiplexingContentHandler.class, ContentHandlerFactoryImpl.class, URLConnection.class});
private Map<String, ContentHandlerProxy> proxies;
private java.net.ContentHandlerFactory parentFactory;
- public ContentHandlerFactory(BundleContext context, FrameworkAdaptor adaptor) {
- super(context, adaptor);
+ public ContentHandlerFactoryImpl(BundleContext context, EquinoxContainer container) {
+ super(context, container);
proxies = new Hashtable<String, ContentHandlerProxy>(5);
@@ -61,7 +60,7 @@ public class ContentHandlerFactory extends MultiplexingFactory implements java.n
public ContentHandler createContentHandler(String contentType) {
//first, we check to see if there exists a built in content handler for
//this content type. we can not overwrite built in ContentHandlers
- String builtInHandlers = StreamHandlerFactory.secureAction.getProperty(CONTENT_HANDLER_PKGS);
+ String builtInHandlers = URLStreamHandlerFactoryImpl.secureAction.getProperty(CONTENT_HANDLER_PKGS);
builtInHandlers = builtInHandlers == null ? DEFAULT_VM_CONTENT_HANDLERS : DEFAULT_VM_CONTENT_HANDLERS + '|' + builtInHandlers;
Class<?> clazz = null;
if (builtInHandlers != null) {
@@ -79,7 +78,7 @@ public class ContentHandlerFactory extends MultiplexingFactory implements java.n
name.append("."); //$NON-NLS-1$
name.append(convertedContentType);
try {
- clazz = StreamHandlerFactory.secureAction.loadSystemClass(name.toString());
+ clazz = URLStreamHandlerFactoryImpl.secureAction.loadSystemClass(name.toString());
if (clazz != null) {
return (null); //this class exists, it is a built in handler, let the JVM handle it
}
@@ -109,7 +108,7 @@ public class ContentHandlerFactory extends MultiplexingFactory implements java.n
prop = new String[] {(String) prop}; // TODO should this be a warning?
if (!(prop instanceof String[])) {
String message = NLS.bind(Msg.URL_HANDLER_INCORRECT_TYPE, new Object[] {URLConstants.URL_CONTENT_MIMETYPE, contentHandlerClazz, serviceReferences[i].getBundle()});
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, null, null));
+ container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, message, null);
continue;
}
String[] contentHandler = (String[]) prop;
@@ -147,7 +146,7 @@ public class ContentHandlerFactory extends MultiplexingFactory implements java.n
Method createInternalContentHandlerMethod = factory.getClass().getMethod("createInternalContentHandler", new Class[] {String.class}); //$NON-NLS-1$
return (ContentHandler) createInternalContentHandlerMethod.invoke(factory, new Object[] {contentType});
} catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(ContentHandlerFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "findAuthorizedContentHandler-loop", 0, e, null)); //$NON-NLS-1$
+ container.getLogServices().log(ContentHandlerFactoryImpl.class.getName(), FrameworkLogEntry.ERROR, "findAuthorizedContentHandler-loop", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/ContentHandlerProxy.java
index b60b7940c..94c568a7e 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/ContentHandlerProxy.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.io.IOException;
import java.net.ContentHandler;
@@ -49,7 +49,7 @@ public class ContentHandlerProxy extends ContentHandler implements ServiceTracke
setNewHandler(reference, getRank(reference));
contentHandlerServiceTracker = new ServiceTracker<ContentHandler, ServiceReference<ContentHandler>>(context, ContentHandler.class.getName(), this);
- StreamHandlerFactory.secureAction.open(contentHandlerServiceTracker);
+ URLStreamHandlerFactoryImpl.secureAction.open(contentHandlerServiceTracker);
}
private void setNewHandler(ServiceReference<ContentHandler> reference, int rank) {
@@ -62,7 +62,7 @@ public class ContentHandlerProxy extends ContentHandler implements ServiceTracke
if (reference == null)
realHandler = new DefaultContentHandler();
else
- realHandler = StreamHandlerFactory.secureAction.getService(reference, context);
+ realHandler = URLStreamHandlerFactoryImpl.secureAction.getService(reference, context);
}
/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java
new file mode 100644
index 000000000..90c98c0ec
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.url;
+
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.Hashtable;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.osgi.framework.BundleContext;
+
+public class EquinoxFactoryManager {
+ private final EquinoxContainer container;
+ // we need to hold these so that we can unregister them at shutdown
+ private volatile URLStreamHandlerFactoryImpl urlStreamHandlerFactory;
+ private volatile ContentHandlerFactoryImpl contentHandlerFactory;
+
+ public EquinoxFactoryManager(EquinoxContainer container) {
+ this.container = container;
+ }
+
+ public void installHandlerFactories(BundleContext context) {
+ installURLStreamHandlerFactory(context);
+ installContentHandlerFactory(context);
+ }
+
+ private void installURLStreamHandlerFactory(BundleContext context) {
+ URLStreamHandlerFactoryImpl shf = new URLStreamHandlerFactoryImpl(context, container);
+ try {
+ // first try the standard way
+ URL.setURLStreamHandlerFactory(shf);
+ } catch (Error err) {
+ try {
+ // ok we failed now use more drastic means to set the factory
+ forceURLStreamHandlerFactory(shf);
+ } catch (Exception ex) {
+ container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, ex.getMessage(), ex);
+ throw err;
+ }
+ }
+ urlStreamHandlerFactory = shf;
+ }
+
+ private static void forceURLStreamHandlerFactory(URLStreamHandlerFactoryImpl shf) throws Exception {
+ Field factoryField = getField(URL.class, URLStreamHandlerFactory.class, false);
+ if (factoryField == null)
+ throw new Exception("Could not find URLStreamHandlerFactory field"); //$NON-NLS-1$
+ // look for a lock to synchronize on
+ Object lock = getURLStreamHandlerFactoryLock();
+ synchronized (lock) {
+ URLStreamHandlerFactory factory = (URLStreamHandlerFactory) factoryField.get(null);
+ // doing a null check here just in case, but it would be really strange if it was null,
+ // because we failed to set the factory normally!!
+ if (factory != null) {
+ try {
+ factory.getClass().getMethod("isMultiplexing", (Class[]) null); //$NON-NLS-1$
+ Method register = factory.getClass().getMethod("register", new Class[] {Object.class}); //$NON-NLS-1$
+ register.invoke(factory, new Object[] {shf});
+ } catch (NoSuchMethodException e) {
+ // current factory does not support multiplexing, ok we'll wrap it
+ shf.setParentFactory(factory);
+ factory = shf;
+ }
+ }
+ factoryField.set(null, null);
+ // always attempt to clear the handlers cache
+ // This allows an optomization for the single framework use-case
+ resetURLStreamHandlers();
+ URL.setURLStreamHandlerFactory(factory);
+ }
+ }
+
+ private static void resetURLStreamHandlers() throws IllegalAccessException {
+ Field handlersField = getField(URL.class, Hashtable.class, false);
+ if (handlersField != null) {
+ @SuppressWarnings("rawtypes")
+ Hashtable<?, ?> handlers = (Hashtable) handlersField.get(null);
+ if (handlers != null)
+ handlers.clear();
+ }
+ }
+
+ private static Object getURLStreamHandlerFactoryLock() throws IllegalAccessException {
+ Object lock;
+ try {
+ Field streamHandlerLockField = URL.class.getDeclaredField("streamHandlerLock"); //$NON-NLS-1$
+ streamHandlerLockField.setAccessible(true);
+ lock = streamHandlerLockField.get(null);
+ } catch (NoSuchFieldException noField) {
+ // could not find the lock, lets sync on the class object
+ lock = URL.class;
+ }
+ return lock;
+ }
+
+ private void installContentHandlerFactory(BundleContext context) {
+ ContentHandlerFactoryImpl chf = new ContentHandlerFactoryImpl(context, container);
+ try {
+ // first try the standard way
+ URLConnection.setContentHandlerFactory(chf);
+ } catch (Error err) {
+ // ok we failed now use more drastic means to set the factory
+ try {
+ forceContentHandlerFactory(chf);
+ } catch (Exception ex) {
+ // this is unexpected, log the exception and throw the original error
+ container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, ex.getMessage(), ex);
+ throw err;
+ }
+ }
+ contentHandlerFactory = chf;
+ }
+
+ private static void forceContentHandlerFactory(ContentHandlerFactoryImpl chf) throws Exception {
+ Field factoryField = getField(URLConnection.class, java.net.ContentHandlerFactory.class, false);
+ if (factoryField == null)
+ throw new Exception("Could not find ContentHandlerFactory field"); //$NON-NLS-1$
+ synchronized (URLConnection.class) {
+ java.net.ContentHandlerFactory factory = (java.net.ContentHandlerFactory) factoryField.get(null);
+ // doing a null check here just in case, but it would be really strange if it was null,
+ // because we failed to set the factory normally!!
+
+ if (factory != null) {
+ try {
+ factory.getClass().getMethod("isMultiplexing", (Class[]) null); //$NON-NLS-1$
+ Method register = factory.getClass().getMethod("register", new Class[] {Object.class}); //$NON-NLS-1$
+ register.invoke(factory, new Object[] {chf});
+ } catch (NoSuchMethodException e) {
+ // current factory does not support multiplexing, ok we'll wrap it
+ chf.setParentFactory(factory);
+ factory = chf;
+ }
+ }
+ // null out the field so that we can successfully call setContentHandlerFactory
+ factoryField.set(null, null);
+ // always attempt to clear the handlers cache
+ // This allows an optomization for the single framework use-case
+ resetContentHandlers();
+ URLConnection.setContentHandlerFactory(factory);
+ }
+ }
+
+ private static void resetContentHandlers() throws IllegalAccessException {
+ Field handlersField = getField(URLConnection.class, Hashtable.class, false);
+ if (handlersField != null) {
+ @SuppressWarnings("rawtypes")
+ Hashtable<?, ?> handlers = (Hashtable) handlersField.get(null);
+ if (handlers != null)
+ handlers.clear();
+ }
+ }
+
+ public void uninstallHandlerFactories() {
+ uninstallURLStreamHandlerFactory();
+ uninstallContentHandlerFactory();
+ }
+
+ private void uninstallURLStreamHandlerFactory() {
+ try {
+ Field factoryField = getField(URL.class, URLStreamHandlerFactory.class, false);
+ if (factoryField == null)
+ return; // oh well, we tried
+ Object lock = getURLStreamHandlerFactoryLock();
+ synchronized (lock) {
+ URLStreamHandlerFactory factory = (URLStreamHandlerFactory) factoryField.get(null);
+ if (factory == urlStreamHandlerFactory) {
+ factory = (URLStreamHandlerFactory) urlStreamHandlerFactory.designateSuccessor();
+ } else {
+ Method unregister = factory.getClass().getMethod("unregister", new Class[] {Object.class}); //$NON-NLS-1$
+ unregister.invoke(factory, new Object[] {urlStreamHandlerFactory});
+ }
+ factoryField.set(null, null);
+ // always attempt to clear the handlers cache
+ // This allows an optimization for the single framework use-case
+ // Note that the call to setURLStreamHandlerFactory below may clear this cache
+ // but we want to be sure to clear it here just in case the parent is null.
+ // In this case the call below would not occur.
+ resetURLStreamHandlers();
+ if (factory != null)
+ URL.setURLStreamHandlerFactory(factory);
+ }
+ } catch (Exception e) {
+ // ignore and continue closing the framework
+ }
+ }
+
+ private void uninstallContentHandlerFactory() {
+ try {
+ Field factoryField = getField(URLConnection.class, java.net.ContentHandlerFactory.class, false);
+ if (factoryField == null)
+ return; // oh well, we tried.
+ synchronized (URLConnection.class) {
+ java.net.ContentHandlerFactory factory = (java.net.ContentHandlerFactory) factoryField.get(null);
+
+ if (factory == contentHandlerFactory) {
+ factory = (java.net.ContentHandlerFactory) contentHandlerFactory.designateSuccessor();
+ } else {
+ Method unregister = factory.getClass().getMethod("unregister", new Class[] {Object.class}); //$NON-NLS-1$
+ unregister.invoke(factory, new Object[] {contentHandlerFactory});
+ }
+ // null out the field so that we can successfully call setContentHandlerFactory
+ factoryField.set(null, null);
+ // always attempt to clear the handlers cache
+ // This allows an optomization for the single framework use-case
+ // Note that the call to setContentHandlerFactory below may clear this cache
+ // but we want to be sure to clear it here just incase the parent is null.
+ // In this case the call below would not occur.
+ // Also it appears most java libraries actually do not clear the cache
+ // when setContentHandlerFactory is called, go figure!!
+ resetContentHandlers();
+ if (factory != null)
+ URLConnection.setContentHandlerFactory(factory);
+ }
+ } catch (Exception e) {
+ // ignore and continue closing the framework
+ }
+ }
+
+ public static Field getField(Class<?> clazz, Class<?> type, boolean instance) {
+ Field[] fields = clazz.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ boolean isStatic = Modifier.isStatic(fields[i].getModifiers());
+ if (instance != isStatic && fields[i].getType().equals(type)) {
+ fields[i].setAccessible(true);
+ return fields[i];
+ }
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingContentHandler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingContentHandler.java
index 3a49caa9f..75add9f98 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingContentHandler.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingContentHandler.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.io.IOException;
import java.net.ContentHandler;
@@ -15,9 +15,9 @@ import java.net.URLConnection;
public class MultiplexingContentHandler extends ContentHandler {
private String contentType;
- private ContentHandlerFactory factory;
+ private ContentHandlerFactoryImpl factory;
- public MultiplexingContentHandler(String contentType, ContentHandlerFactory factory) {
+ public MultiplexingContentHandler(String contentType, ContentHandlerFactoryImpl factory) {
this.contentType = contentType;
this.factory = factory;
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java
index 648292324..516b5aae5 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java
@@ -1,34 +1,29 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Cognos Incorporated, IBM Corporation and others.
+ * Copyright (c) 2006, 2012 Cognos Incorporated, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.util.tracker.ServiceTracker;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.osgi.framework.*;
/*
* An abstract class for handler factory impls (Stream and Content) that can
* handle environments running multiple osgi frameworks with the same VM.
*/
public abstract class MultiplexingFactory {
-
- protected static final String PACKAGEADMINCLASS = "org.osgi.service.packageadmin.PackageAdmin"; //$NON-NLS-1$
+ protected EquinoxContainer container;
protected BundleContext context;
- protected FrameworkAdaptor adaptor;
private List<Object> factories; // list of multiplexed factories
- private ServiceTracker<ServiceReference<?>, PackageAdmin> packageAdminTracker;
// used to get access to the protected SecurityManager#getClassContext method
static class InternalSecurityManager extends SecurityManager {
@@ -39,11 +34,10 @@ public abstract class MultiplexingFactory {
private static InternalSecurityManager internalSecurityManager = new InternalSecurityManager();
- MultiplexingFactory(BundleContext context, FrameworkAdaptor adaptor) {
+ MultiplexingFactory(BundleContext context, EquinoxContainer container) {
this.context = context;
- this.adaptor = adaptor;
- packageAdminTracker = new ServiceTracker<ServiceReference<?>, PackageAdmin>(context, PACKAGEADMINCLASS, null);
- packageAdminTracker.open();
+ this.container = container;
+
}
abstract public void setParentFactory(Object parentFactory);
@@ -61,7 +55,7 @@ public abstract class MultiplexingFactory {
Method setParentFactory = clazz.getMethod("setParentFactory", new Class[] {Object.class}); //$NON-NLS-1$
setParentFactory.invoke(factory, new Object[] {getParentFactory()});
} catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "register", FrameworkLogEntry.ERROR, e, null)); //$NON-NLS-1$
+ container.getLogServices().log(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, "register", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
addFactory(factory);
@@ -76,7 +70,7 @@ public abstract class MultiplexingFactory {
closeTracker.setAccessible(true); // its a private method
closeTracker.invoke(factory, (Object[]) null);
} catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "unregister", FrameworkLogEntry.ERROR, e, null)); //$NON-NLS-1$
+ container.getLogServices().log(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, "unregister", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -101,7 +95,7 @@ public abstract class MultiplexingFactory {
register.invoke(successor, new Object[] {r});
}
} catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "designateSuccessor", FrameworkLogEntry.ERROR, e, null)); //$NON-NLS-1$
+ container.getLogServices().log(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, "designateSuccessor", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
closePackageAdminTracker(); // close tracker
@@ -109,7 +103,7 @@ public abstract class MultiplexingFactory {
}
private void closePackageAdminTracker() {
- packageAdminTracker.close();
+ // Do nothing, just here for posterity
}
public Object findAuthorizedFactory(List<Class<?>> ignoredClasses) {
@@ -130,7 +124,7 @@ public abstract class MultiplexingFactory {
return factory;
}
} catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "findAuthorizedURLStreamHandler-loop", FrameworkLogEntry.ERROR, e, null)); //$NON-NLS-1$
+ container.getLogServices().log(MultiplexingFactory.class.getName(), FrameworkLogEntry.ERROR, "findAuthorizedURLStreamHandler-loop", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -139,11 +133,11 @@ public abstract class MultiplexingFactory {
}
public boolean hasAuthority(Class<?> clazz) {
- PackageAdmin packageAdminService = packageAdminTracker.getService();
- if (packageAdminService != null) {
- return packageAdminService.getBundle(clazz) != null;
+ Bundle b = FrameworkUtil.getBundle(clazz);
+ if (!(b instanceof EquinoxBundle)) {
+ return false;
}
- return false;
+ return (container.getStorage().getModuleContainer() == ((EquinoxBundle) b).getModule().getContainer());
}
private synchronized List<Object> getFactories() {
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingURLStreamHandler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java
index e3bb90f89..e6eff45f3 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/MultiplexingURLStreamHandler.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java
@@ -6,12 +6,11 @@
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.io.IOException;
import java.lang.reflect.*;
import java.net.*;
-import org.eclipse.osgi.framework.internal.core.Framework;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
public class MultiplexingURLStreamHandler extends URLStreamHandler {
@@ -28,11 +27,11 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
private static Field handlerField;
private static boolean methodsInitialized = false;
- private final String protocol;
- private final StreamHandlerFactory factory;
+ private String protocol;
+ private URLStreamHandlerFactoryImpl factory;
private final URLStreamHandler authorized;
- private static synchronized void initializeMethods(StreamHandlerFactory factory) {
+ private static synchronized void initializeMethods(URLStreamHandlerFactoryImpl factory) {
if (methodsInitialized)
return;
try {
@@ -69,19 +68,19 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
try {
handlerField = URL.class.getDeclaredField("handler"); //$NON-NLS-1$
} catch (NoSuchFieldException e) {
- handlerField = Framework.getField(URL.class, URLStreamHandler.class, true);
+ handlerField = EquinoxFactoryManager.getField(URL.class, URLStreamHandler.class, true);
if (handlerField == null)
throw e;
}
handlerField.setAccessible(true);
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "initializeMethods", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "initializeMethods", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
methodsInitialized = true;
}
- public MultiplexingURLStreamHandler(String protocol, StreamHandlerFactory factory, URLStreamHandler authorized) {
+ public MultiplexingURLStreamHandler(String protocol, URLStreamHandlerFactoryImpl factory, URLStreamHandler authorized) {
this.protocol = protocol;
this.factory = factory;
this.authorized = authorized;
@@ -98,7 +97,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
throw (IOException) e.getTargetException();
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "openConnection", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "openConnection", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -113,7 +112,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "equals", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "equals", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -128,7 +127,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "getDefaultPort", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "getDefaultPort", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -143,7 +142,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "hashCode", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "hashCode", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -158,7 +157,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "hashCode", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "hashCode", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -173,7 +172,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "hostsEqual", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "hostsEqual", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -191,7 +190,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "parseURL", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "parseURL", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -206,7 +205,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "sameFile", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "sameFile", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -224,7 +223,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "setURL", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "setURL", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
@@ -239,7 +238,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler {
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
- factory.adaptor.getFrameworkLog().log(new FrameworkLogEntry(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, 0, "toExternalForm", 0, e, null)); //$NON-NLS-1$
+ factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "toExternalForm", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/NullURLStreamHandlerService.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/NullURLStreamHandlerService.java
index 4cca4f943..a9b12cb9d 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/NullURLStreamHandlerService.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/NullURLStreamHandlerService.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.io.IOException;
import java.net.*;
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/StreamHandlerFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerFactoryImpl.java
index 0c4677539..96de07e46 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/StreamHandlerFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerFactoryImpl.java
@@ -9,17 +9,18 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.lang.reflect.Method;
import java.net.*;
import java.security.AccessController;
import java.util.*;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.util.SecureAction;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.location.EquinoxLocations;
+import org.eclipse.osgi.storage.url.BundleResourceHandler;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -30,26 +31,15 @@ import org.osgi.util.tracker.ServiceTracker;
/**
* This class contains the URL stream handler factory for the OSGi framework.
*/
-public class StreamHandlerFactory extends MultiplexingFactory implements URLStreamHandlerFactory {
+public class URLStreamHandlerFactoryImpl extends MultiplexingFactory implements URLStreamHandlerFactory {
+ protected static final String URLSTREAMHANDLERCLASS = "org.osgi.service.url.URLStreamHandlerService"; //$NON-NLS-1$
+ protected static final String PROTOCOL_HANDLER_PKGS = "java.protocol.handler.pkgs"; //$NON-NLS-1$
+ private static final String PROTOCOL_REFERENCE = "reference"; //$NON-NLS-1$
static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
private ServiceTracker<URLStreamHandlerService, URLStreamHandlerService> handlerTracker;
- protected static final String URLSTREAMHANDLERCLASS = "org.osgi.service.url.URLStreamHandlerService"; //$NON-NLS-1$
- protected static final String PROTOCOL_HANDLER_PKGS = "java.protocol.handler.pkgs"; //$NON-NLS-1$
- protected static final String INTERNAL_PROTOCOL_HANDLER_PKG = "org.eclipse.osgi.framework.internal.protocol"; //$NON-NLS-1$
-
- private static final List<Class<?>> ignoredClasses = Arrays.asList(new Class<?>[] {MultiplexingURLStreamHandler.class, StreamHandlerFactory.class, URL.class});
- private static final boolean useNetProxy;
- static {
- Class<?> clazz = null;
- try {
- clazz = Class.forName("java.net.Proxy"); //$NON-NLS-1$
- } catch (ClassNotFoundException e) {
- // expected on JRE < 1.5
- }
- useNetProxy = clazz != null;
- }
+ private static final List<Class<?>> ignoredClasses = Arrays.asList(new Class<?>[] {MultiplexingURLStreamHandler.class, URLStreamHandlerFactoryImpl.class, URL.class});
private Map<String, URLStreamHandler> proxies;
private URLStreamHandlerFactory parentFactory;
private ThreadLocal<List<String>> creatingProtocols = new ThreadLocal<List<String>>();
@@ -59,8 +49,8 @@ public class StreamHandlerFactory extends MultiplexingFactory implements URLStre
*
* @param context BundleContext for the system bundle
*/
- public StreamHandlerFactory(BundleContext context, FrameworkAdaptor adaptor) {
- super(context, adaptor);
+ public URLStreamHandlerFactoryImpl(BundleContext context, EquinoxContainer container) {
+ super(context, container);
proxies = new Hashtable<String, URLStreamHandler>(15);
handlerTracker = new ServiceTracker<URLStreamHandlerService, URLStreamHandlerService>(context, URLSTREAMHANDLERCLASS, null);
@@ -122,7 +112,7 @@ public class StreamHandlerFactory extends MultiplexingFactory implements URLStre
result = parentFactory.createURLStreamHandler(protocol);
return result; //result may be null; let the VM handle it (consider sun.net.protocol.www.*)
} catch (Throwable t) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(StreamHandlerFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "Unexpected error in factory.", 0, t, null)); //$NON-NLS-1$
+ container.getLogServices().log(URLStreamHandlerFactoryImpl.class.getName(), FrameworkLogEntry.ERROR, "Unexpected error in factory.", t); //$NON-NLS-1$
return null;
} finally {
releaseRecursive(protocol);
@@ -146,54 +136,52 @@ public class StreamHandlerFactory extends MultiplexingFactory implements URLStre
protocols.remove(protocol);
}
+ private URLStreamHandler getFrameworkHandler(String protocol) {
+ if (BundleResourceHandler.OSGI_ENTRY_URL_PROTOCOL.equals(protocol)) {
+ return new org.eclipse.osgi.storage.url.bundleentry.Handler(container.getStorage().getModuleContainer(), null);
+ } else if (BundleResourceHandler.OSGI_RESOURCE_URL_PROTOCOL.equals(protocol)) {
+ return new org.eclipse.osgi.storage.url.bundleresource.Handler(container.getStorage().getModuleContainer(), null);
+ } else if (PROTOCOL_REFERENCE.equals(protocol)) {
+ return new org.eclipse.osgi.storage.url.reference.Handler(container.getConfiguration().getConfiguration(EquinoxLocations.PROP_INSTALL_AREA));
+ }
+ return null;
+ }
+
public URLStreamHandler createInternalURLStreamHandler(String protocol) {
//internal protocol handlers
- String internalHandlerPkgs = secureAction.getProperty(Constants.INTERNAL_HANDLER_PKGS);
- internalHandlerPkgs = internalHandlerPkgs == null ? INTERNAL_PROTOCOL_HANDLER_PKG : internalHandlerPkgs + '|' + INTERNAL_PROTOCOL_HANDLER_PKG;
- Class<?> clazz = getBuiltIn(protocol, internalHandlerPkgs, true);
-
- if (clazz == null) {
- //Now we check the service registry
- //first check to see if the handler is in the cache
- URLStreamHandlerProxy handler = (URLStreamHandlerProxy) proxies.get(protocol);
- if (handler != null)
- return (handler);
- //look through the service registry for a URLStramHandler registered for this protocol
- ServiceReference<URLStreamHandlerService>[] serviceReferences = handlerTracker.getServiceReferences();
- if (serviceReferences == null)
- return null;
- for (int i = 0; i < serviceReferences.length; i++) {
- Object prop = serviceReferences[i].getProperty(URLConstants.URL_HANDLER_PROTOCOL);
- if (prop instanceof String)
- prop = new String[] {(String) prop}; // TODO should this be a warning?
- if (!(prop instanceof String[])) {
- String message = NLS.bind(Msg.URL_HANDLER_INCORRECT_TYPE, new Object[] {URLConstants.URL_HANDLER_PROTOCOL, URLSTREAMHANDLERCLASS, serviceReferences[i].getBundle()});
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, null, null));
- continue;
- }
- String[] protocols = (String[]) prop;
- for (int j = 0; j < protocols.length; j++)
- if (protocols[j].equals(protocol)) {
- handler = useNetProxy ? new URLStreamHandlerFactoryProxyFor15(protocol, serviceReferences[i], context) : new URLStreamHandlerProxy(protocol, serviceReferences[i], context);
- proxies.put(protocol, handler);
- return (handler);
- }
- }
- return null;
+ URLStreamHandler frameworkHandler = getFrameworkHandler(protocol);
+ if (frameworkHandler != null) {
+ return frameworkHandler;
}
- // must be a built-in handler
- try {
- URLStreamHandler handler = (URLStreamHandler) clazz.newInstance();
-
- if (handler instanceof ProtocolActivator) {
- ((ProtocolActivator) handler).start(context, adaptor);
- }
-
- return handler;
- } catch (Exception e) {
+ //Now we check the service registry
+ //first check to see if the handler is in the cache
+ URLStreamHandlerProxy handler = (URLStreamHandlerProxy) proxies.get(protocol);
+ if (handler != null)
+ return (handler);
+ //look through the service registry for a URLStramHandler registered for this protocol
+ ServiceReference<URLStreamHandlerService>[] serviceReferences = handlerTracker.getServiceReferences();
+ if (serviceReferences == null)
return null;
+ for (int i = 0; i < serviceReferences.length; i++) {
+ Object prop = serviceReferences[i].getProperty(URLConstants.URL_HANDLER_PROTOCOL);
+ if (prop instanceof String)
+ prop = new String[] {(String) prop}; // TODO should this be a warning?
+ if (!(prop instanceof String[])) {
+ String message = NLS.bind(Msg.URL_HANDLER_INCORRECT_TYPE, new Object[] {URLConstants.URL_HANDLER_PROTOCOL, URLSTREAMHANDLERCLASS, serviceReferences[i].getBundle()});
+ container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, message, null);
+ continue;
+ }
+ String[] protocols = (String[]) prop;
+ for (int j = 0; j < protocols.length; j++) {
+ if (protocols[j].equals(protocol)) {
+ handler = new URLStreamHandlerProxy(protocol, serviceReferences[i], context);
+ proxies.put(protocol, handler);
+ return (handler);
+ }
+ }
}
+ return null;
}
protected URLStreamHandler findAuthorizedURLStreamHandler(String protocol) {
@@ -208,7 +196,7 @@ public class StreamHandlerFactory extends MultiplexingFactory implements URLStre
Method createInternalURLStreamHandlerMethod = factory.getClass().getMethod("createInternalURLStreamHandler", new Class[] {String.class}); //$NON-NLS-1$
return (URLStreamHandler) createInternalURLStreamHandlerMethod.invoke(factory, new Object[] {protocol});
} catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(StreamHandlerFactory.class.getName(), FrameworkLogEntry.ERROR, 0, "findAuthorizedURLStreamHandler-loop", 0, e, null)); //$NON-NLS-1$
+ container.getLogServices().log(URLStreamHandlerFactoryImpl.class.getName(), FrameworkLogEntry.ERROR, "findAuthorizedURLStreamHandler-loop", e); //$NON-NLS-1$
throw new RuntimeException(e.getMessage(), e);
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerProxy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java
index cb0dc57ae..be66a49fd 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerProxy.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java
@@ -9,9 +9,11 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.*;
import org.osgi.framework.*;
import org.osgi.service.url.URLConstants;
@@ -53,8 +55,8 @@ public class URLStreamHandlerProxy extends URLStreamHandler implements ServiceTr
//set the handler and ranking
setNewHandler(reference, getRank(reference));
- urlStreamHandlerServiceTracker = new ServiceTracker<URLStreamHandlerService, ServiceReference<URLStreamHandlerService>>(context, StreamHandlerFactory.URLSTREAMHANDLERCLASS, this);
- StreamHandlerFactory.secureAction.open(urlStreamHandlerServiceTracker);
+ urlStreamHandlerServiceTracker = new ServiceTracker<URLStreamHandlerService, ServiceReference<URLStreamHandlerService>>(context, URLStreamHandlerFactoryImpl.URLSTREAMHANDLERCLASS, this);
+ URLStreamHandlerFactoryImpl.secureAction.open(urlStreamHandlerServiceTracker);
}
private void setNewHandler(ServiceReference<URLStreamHandlerService> reference, int rank) {
@@ -67,7 +69,7 @@ public class URLStreamHandlerProxy extends URLStreamHandler implements ServiceTr
if (reference == null)
realHandlerService = new NullURLStreamHandlerService();
else
- realHandlerService = StreamHandlerFactory.secureAction.getService(reference, context);
+ realHandlerService = URLStreamHandlerFactoryImpl.secureAction.getService(reference, context);
}
/**
@@ -215,4 +217,17 @@ public class URLStreamHandlerProxy extends URLStreamHandler implements ServiceTr
return (property instanceof Integer) ? ((Integer) property).intValue() : 0;
}
+ protected URLConnection openConnection(URL u, Proxy p) throws IOException {
+ try {
+ Method openConn = realHandlerService.getClass().getMethod("openConnection", new Class[] {URL.class, Proxy.class}); //$NON-NLS-1$
+ return (URLConnection) openConn.invoke(realHandlerService, new Object[] {u, p});
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof IOException)
+ throw (IOException) e.getTargetException();
+ throw (RuntimeException) e.getTargetException();
+ } catch (Exception e) {
+ // expected on JRE < 1.5
+ throw (UnsupportedOperationException) new UnsupportedOperationException().initCause(e);
+ }
+ }
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerSetter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerSetter.java
index c576b5a2b..336ff003c 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerSetter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/URLStreamHandlerSetter.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol;
+package org.eclipse.osgi.internal.url;
import java.net.URL;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/DynamicImportList.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/DynamicImportList.java
index 789beae53..0a425e3dd 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/DynamicImportList.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/DynamicImportList.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,11 +8,9 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor.weaving;
+package org.eclipse.osgi.internal.weaving;
import java.util.*;
-import org.eclipse.osgi.internal.resolver.StateBuilder;
-import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.Constants;
@@ -63,16 +61,8 @@ public class DynamicImportList extends AbstractList<String> implements RandomAcc
private void validateSyntax(String imported) {
// validate the syntax of imports that are added.
- ManifestElement[] importElements;
try {
- importElements = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, imported);
-
- // validate the syntax is correct
- StateBuilder.checkImportExportSyntax(Constants.IMPORT_PACKAGE, importElements, false, false, false);
- // validate we can create an import spec out of it.
- List<ImportPackageSpecification> dynamicImportSpecs = new ArrayList<ImportPackageSpecification>(importElements.length);
- for (ManifestElement dynamicImportElement : importElements)
- StateBuilder.addImportPackages(dynamicImportElement, dynamicImportSpecs, 2, true);
+ ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, imported);
} catch (Throwable t) {
IllegalArgumentException exception = new IllegalArgumentException();
exception.initCause(t);
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WeavingHookConfigurator.java
index 9f43d0ec4..00740bd43 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WeavingHookConfigurator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,53 +8,41 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor.weaving;
+package org.eclipse.osgi.internal.weaving;
-import java.net.URL;
-import java.security.ProtectionDomain;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
-import org.eclipse.osgi.framework.internal.core.Framework;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.osgi.framework.*;
-public class WeavingHookConfigurator implements HookConfigurator, ClassLoadingHook, ClassLoadingStatsHook {
- private BaseAdaptor adaptor;
+public class WeavingHookConfigurator extends ClassLoaderHook {
// holds the map of black listed hooks. Use weak map to avoid pinning and simplify cleanup.
private final Map<ServiceRegistration<?>, Boolean> blackList = Collections.synchronizedMap(new WeakHashMap<ServiceRegistration<?>, Boolean>());
// holds the stack of WovenClass objects currently being used to define classes
private final ThreadLocal<List<WovenClassImpl>> wovenClassStack = new ThreadLocal<List<WovenClassImpl>>();
- public void addHooks(HookRegistry hookRegistry) {
- this.adaptor = hookRegistry.getAdaptor();
- hookRegistry.addClassLoadingHook(this);
- hookRegistry.addClassLoadingStatsHook(this);
+ private final EquinoxContainer container;
+
+ public WeavingHookConfigurator(EquinoxContainer container) {
+ this.container = container;
}
private ServiceRegistry getRegistry() {
- return ((Framework) adaptor.getEventPublisher()).getServiceRegistry();
+ return container.getServiceRegistry();
}
public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
ServiceRegistry registry = getRegistry();
if (registry == null)
return null; // no registry somehow we are loading classes before the registry has been created
- ClassLoaderDelegate delegate = manager.getBaseClassLoader().getDelegate();
- BundleLoader loader;
- if (delegate instanceof BundleLoader) {
- loader = (BundleLoader) delegate;
- } else {
- Throwable e = new IllegalStateException("Could not obtain loader"); //$NON-NLS-1$
- adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, manager.getBaseData().getBundle(), e);
- return null;
- }
+ ModuleClassLoader classLoader = manager.getClassLoader();
+ BundleLoader loader = classLoader.getBundleLoader();
// create a woven class object and add it to the thread local stack
WovenClassImpl wovenClass = new WovenClassImpl(name, classbytes, entry, classpathEntry.getDomain(), loader, registry, blackList);
List<WovenClassImpl> wovenClasses = wovenClassStack.get();
@@ -68,8 +56,8 @@ public class WeavingHookConfigurator implements HookConfigurator, ClassLoadingHo
return wovenClass.callHooks();
} catch (Throwable t) {
ServiceRegistration<?> errorHook = wovenClass.getErrorHook();
- Bundle errorBundle = errorHook != null ? errorHook.getReference().getBundle() : manager.getBaseData().getBundle();
- adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, errorBundle, t);
+ Bundle errorBundle = errorHook != null ? errorHook.getReference().getBundle() : manager.getGeneration().getRevision().getBundle();
+ container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, errorBundle, t);
// fail hard with a class loading error
ClassFormatError error = new ClassFormatError("Unexpected error from weaving hook."); //$NON-NLS-1$
error.initCause(t);
@@ -77,42 +65,6 @@ public class WeavingHookConfigurator implements HookConfigurator, ClassLoadingHo
}
}
- public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) {
- return false;
- }
-
- public String findLibrary(BaseData data, String libName) {
- return null;
- }
-
- public ClassLoader getBundleClassLoaderParent() {
- return null;
- }
-
- public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) {
- return null;
- }
-
- public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
- // nothing
- }
-
- public void preFindLocalClass(String name, ClasspathManager manager) {
- // nothing
- }
-
- public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) {
- // nothing
- }
-
- public void preFindLocalResource(String name, ClasspathManager manager) {
- // nothing
- }
-
- public void postFindLocalResource(String name, URL resource, ClasspathManager manager) {
- // nothing
- }
-
public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
// here we assume the stack contans a woven class with the same name as the class we are defining.
List<WovenClassImpl> wovenClasses = wovenClassStack.get();
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java
index e7e27a37c..8858e754b 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,15 +8,15 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor.weaving;
+package org.eclipse.osgi.internal.weaving;
import java.security.*;
import java.util.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.serviceregistry.HookContext;
import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;
import org.osgi.framework.hooks.weaving.*;
@@ -79,7 +79,7 @@ public final class WovenClassImpl implements WovenClass, HookContext {
void checkPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
- sm.checkPermission(new AdminPermission(loader.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(loader.getWiring().getBundle(), AdminPermission.WEAVE));
}
public List<String> getDynamicImports() {
@@ -120,7 +120,7 @@ public final class WovenClassImpl implements WovenClass, HookContext {
}
public BundleWiring getBundleWiring() {
- return loader.getLoaderProxy().getBundleDescription().getWiring();
+ return loader.getWiring();
}
public void call(final Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java
new file mode 100644
index 000000000..834bb571f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.launch;
+
+import java.io.*;
+import java.net.URL;
+import java.security.cert.X509Certificate;
+import java.util.*;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.osgi.framework.*;
+import org.osgi.framework.launch.Framework;
+
+/**
+ * The System Bundle implementation for the Equinox Framework.
+ *
+ * @since 3.5
+ */
+public class Equinox implements Framework {
+
+ private final Framework systemBundle;
+
+ public Equinox(Map<String, String> configuration) {
+ EquinoxContainer container = new EquinoxContainer(configuration);
+ systemBundle = (Framework) container.getStorage().getModuleContainer().getModule(0).getBundle();
+ }
+
+ @Override
+ public int getState() {
+ return systemBundle.getState();
+ }
+
+ @Override
+ public Dictionary<String, String> getHeaders() {
+ return systemBundle.getHeaders();
+ }
+
+ @Override
+ public ServiceReference<?>[] getRegisteredServices() {
+ return systemBundle.getRegisteredServices();
+ }
+
+ @Override
+ public ServiceReference<?>[] getServicesInUse() {
+ return systemBundle.getServicesInUse();
+ }
+
+ @Override
+ public boolean hasPermission(Object permission) {
+ return systemBundle.hasPermission(permission);
+ }
+
+ @Override
+ public URL getResource(String name) {
+ return systemBundle.getResource(name);
+ }
+
+ @Override
+ public Dictionary<String, String> getHeaders(String locale) {
+ return systemBundle.getHeaders(locale);
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return systemBundle.loadClass(name);
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ return systemBundle.getResources(name);
+ }
+
+ @Override
+ public long getLastModified() {
+ return systemBundle.getLastModified();
+ }
+
+ @Override
+ public BundleContext getBundleContext() {
+ return systemBundle.getBundleContext();
+ }
+
+ @Override
+ public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
+ return systemBundle.getSignerCertificates(signersType);
+ }
+
+ @Override
+ public Version getVersion() {
+ return systemBundle.getVersion();
+ }
+
+ @Override
+ public File getDataFile(String filename) {
+ return systemBundle.getDataFile(filename);
+ }
+
+ @Override
+ public int compareTo(Bundle o) {
+ return systemBundle.compareTo(o);
+ }
+
+ public void start(int options) throws BundleException {
+ systemBundle.start(options);
+ }
+
+ public void start() throws BundleException {
+ systemBundle.start();
+ }
+
+ public void stop(int options) throws BundleException {
+ systemBundle.stop(options);
+ }
+
+ public void stop() throws BundleException {
+ systemBundle.stop();
+ }
+
+ public void update(InputStream input) throws BundleException {
+ systemBundle.update(input);
+ }
+
+ public void update() throws BundleException {
+ systemBundle.update();
+ }
+
+ public void uninstall() throws BundleException {
+ systemBundle.uninstall();
+ }
+
+ public long getBundleId() {
+ return systemBundle.getBundleId();
+ }
+
+ public String getLocation() {
+ return systemBundle.getLocation();
+ }
+
+ public String getSymbolicName() {
+ return systemBundle.getSymbolicName();
+ }
+
+ public Enumeration<String> getEntryPaths(String path) {
+ return systemBundle.getEntryPaths(path);
+ }
+
+ public URL getEntry(String path) {
+ return systemBundle.getEntry(path);
+ }
+
+ public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
+ return systemBundle.findEntries(path, filePattern, recurse);
+ }
+
+ public <A> A adapt(Class<A> type) {
+ return systemBundle.adapt(type);
+ }
+
+ @Override
+ public void init() throws BundleException {
+ systemBundle.init();
+ }
+
+ @Override
+ public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
+ return systemBundle.waitForStop(timeout);
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java
index 389f07a7a..e38c74c89 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/package.html
index b2d671be0..b2d671be0 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/package.html
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/osgi/service/pluginconversion/PluginConversionException.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/pluginconversion/PluginConversionException.java
index 6aa16c032..6aa16c032 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/osgi/service/pluginconversion/PluginConversionException.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/pluginconversion/PluginConversionException.java
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/osgi/service/pluginconversion/PluginConverter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/pluginconversion/PluginConverter.java
index a5be77a3a..a5be77a3a 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/osgi/service/pluginconversion/PluginConverter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/pluginconversion/PluginConverter.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BaseDescription.java
index 3c70068a9..3c70068a9 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BaseDescription.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDelta.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleDelta.java
index f343f1d49..f343f1d49 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDelta.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleDelta.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleDescription.java
index b7acfcc21..b7acfcc21 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleDescription.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleSpecification.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleSpecification.java
index bb5d4ac23..bb5d4ac23 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleSpecification.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/BundleSpecification.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/DisabledInfo.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/DisabledInfo.java
index 9f79ddbda..9f79ddbda 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/DisabledInfo.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/DisabledInfo.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ExportPackageDescription.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ExportPackageDescription.java
index c8575762d..c8575762d 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ExportPackageDescription.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ExportPackageDescription.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/GenericDescription.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/GenericDescription.java
index 8f091aee0..8f091aee0 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/GenericDescription.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/GenericDescription.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/GenericSpecification.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/GenericSpecification.java
index 3ebc34a54..3ebc34a54 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/GenericSpecification.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/GenericSpecification.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/HostSpecification.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/HostSpecification.java
index 3f6a46fe7..3f6a46fe7 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/HostSpecification.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/HostSpecification.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ImportPackageSpecification.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ImportPackageSpecification.java
index 09da758b1..09da758b1 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ImportPackageSpecification.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ImportPackageSpecification.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/NativeCodeDescription.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/NativeCodeDescription.java
index bb6741447..bb6741447 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/NativeCodeDescription.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/NativeCodeDescription.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/NativeCodeSpecification.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/NativeCodeSpecification.java
index 1c37fd3e0..1c37fd3e0 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/NativeCodeSpecification.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/NativeCodeSpecification.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/PlatformAdmin.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/PlatformAdmin.java
index e7b1684ac..e7b1684ac 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/PlatformAdmin.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/PlatformAdmin.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/Resolver.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/Resolver.java
index 24bed1c85..24bed1c85 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/Resolver.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/Resolver.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ResolverError.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ResolverError.java
index ee823eefc..ee823eefc 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ResolverError.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ResolverError.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ResolverHookException.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ResolverHookException.java
index 3feb596ac..3feb596ac 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/ResolverHookException.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/ResolverHookException.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/State.java
index ab13c3fd1..ab13c3fd1 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/State.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateDelta.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateDelta.java
index 33690806b..33690806b 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateDelta.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateDelta.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateHelper.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateHelper.java
index a5156ebc1..a5156ebc1 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateHelper.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateHelper.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateObjectFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateObjectFactory.java
index c0f6701bc..371c7558f 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateObjectFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateObjectFactory.java
@@ -12,7 +12,6 @@ package org.eclipse.osgi.service.resolver;
import java.io.*;
import java.util.*;
-import org.eclipse.osgi.internal.resolver.StateObjectFactoryImpl;
import org.osgi.framework.*;
/**
@@ -30,7 +29,7 @@ public interface StateObjectFactory {
* states. This is particularly useful when using the resolver outside the context
* of a running Equinox framework.
*/
- public static final StateObjectFactory defaultFactory = new StateObjectFactoryImpl();
+ public static final StateObjectFactory defaultFactory = new StateObjectFactoryProxy();
/**
* Creates an empty state. The returned state does not have an
@@ -484,4 +483,220 @@ public interface StateObjectFactory {
*/
public State readState(File stateDirectory) throws IOException;
+ static class StateObjectFactoryProxy implements StateObjectFactory {
+ private static final String IMPL_NAME = "org.eclipse.osgi.internal.resolver.StateObjectFactoryImpl"; //$NON-NLS-1$
+ private Object monitor = new Object();
+ private StateObjectFactory implementation;
+
+ private StateObjectFactory getImplementation() {
+ synchronized (this.monitor) {
+ if (implementation == null) {
+ Exception error = null;
+ try {
+ Class<?> implClass = Class.forName(IMPL_NAME);
+ implementation = (StateObjectFactory) implClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ error = e;
+ } catch (InstantiationException e) {
+ error = e;
+ } catch (IllegalAccessException e) {
+ error = e;
+ }
+ if (error != null) {
+ throw new UnsupportedOperationException("Not able to create StateObjectFactory implementation: " + IMPL_NAME, error);
+ }
+ }
+ return implementation;
+ }
+ }
+
+ @Deprecated
+ @Override
+ public State createState() {
+ return getImplementation().createState();
+ }
+
+ @Override
+ public State createState(boolean resolver) {
+ return getImplementation().createState(resolver);
+ }
+
+ @Override
+ public State createState(State state) {
+ return getImplementation().createState(state);
+ }
+
+ @Deprecated
+ @Override
+ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, String[] providedPackages, boolean singleton) {
+ return getImplementation().createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, providedPackages, singleton);
+ }
+
+ @Deprecated
+ @Override
+ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, String[] providedPackages, boolean singleton, boolean attachFragments, boolean dynamicFragments, String platformFilter, String executionEnvironment, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities) {
+ return getImplementation().createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, providedPackages, singleton, attachFragments, dynamicFragments, platformFilter, executionEnvironment, genericRequires, genericCapabilities);
+ }
+
+ @Override
+ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, boolean singleton, boolean attachFragments, boolean dynamicFragments, String platformFilter, String[] executionEnvironments, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities) {
+ return getImplementation().createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, singleton, attachFragments, dynamicFragments, platformFilter, executionEnvironments, genericRequires, genericCapabilities);
+ }
+
+ @Override
+ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, boolean singleton, boolean attachFragments, boolean dynamicFragments, String platformFilter, String[] executionEnvironments, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities, NativeCodeSpecification nativeCode) {
+ return getImplementation().createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, singleton, attachFragments, dynamicFragments, platformFilter, executionEnvironments, genericRequires, genericCapabilities, nativeCode);
+ }
+
+ @Override
+ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, String platformFilter, String[] executionEnvironments, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities, NativeCodeSpecification nativeCode) {
+ return getImplementation().createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, platformFilter, executionEnvironments, genericRequires, genericCapabilities, nativeCode);
+ }
+
+ @Override
+ public BundleDescription createBundleDescription(State state, Dictionary<String, String> manifest, String location, long id) throws BundleException {
+ return getImplementation().createBundleDescription(state, manifest, location, id);
+ }
+
+ @Deprecated
+ @Override
+ public BundleDescription createBundleDescription(Dictionary<String, String> manifest, String location, long id) throws BundleException {
+ return getImplementation().createBundleDescription(manifest, location, id);
+ }
+
+ @Override
+ public BundleDescription createBundleDescription(BundleDescription original) {
+ return getImplementation().createBundleDescription(original);
+ }
+
+ @Override
+ public BundleSpecification createBundleSpecification(String requiredSymbolicName, VersionRange requiredVersionRange, boolean export, boolean optional) {
+ return getImplementation().createBundleSpecification(requiredSymbolicName, requiredVersionRange, export, optional);
+ }
+
+ @Override
+ public BundleSpecification createBundleSpecification(BundleSpecification original) {
+ return getImplementation().createBundleSpecification(original);
+ }
+
+ @Override
+ public List<BundleSpecification> createBundleSpecifications(String declaration) {
+ return getImplementation().createBundleSpecifications(declaration);
+ }
+
+ @Override
+ public HostSpecification createHostSpecification(String hostSymbolicName, VersionRange hostVersionRange) {
+ return getImplementation().createHostSpecification(hostSymbolicName, hostVersionRange);
+ }
+
+ @Override
+ public List<HostSpecification> createHostSpecifications(String declaration) {
+ return getImplementation().createHostSpecifications(declaration);
+ }
+
+ @Override
+ public HostSpecification createHostSpecification(HostSpecification original) {
+ return getImplementation().createHostSpecification(original);
+ }
+
+ @Override
+ public ImportPackageSpecification createImportPackageSpecification(String packageName, VersionRange versionRange, String bundleSymbolicName, VersionRange bundleVersionRange, Map<String, ?> directives, Map<String, ?> attributes, BundleDescription importer) {
+ return getImplementation().createImportPackageSpecification(packageName, versionRange, bundleSymbolicName, bundleVersionRange, directives, attributes, importer);
+ }
+
+ @Override
+ public ImportPackageSpecification createImportPackageSpecification(ImportPackageSpecification original) {
+ return getImplementation().createImportPackageSpecification(original);
+ }
+
+ @Override
+ public List<ImportPackageSpecification> createImportPackageSpecifications(String declaration) {
+ return getImplementation().createImportPackageSpecifications(declaration);
+ }
+
+ @Override
+ public ExportPackageDescription createExportPackageDescription(String packageName, Version version, Map<String, ?> directives, Map<String, ?> attributes, boolean root, BundleDescription exporter) {
+ return getImplementation().createExportPackageDescription(packageName, version, directives, attributes, root, exporter);
+ }
+
+ @Deprecated
+ @Override
+ public GenericDescription createGenericDescription(String name, String type, Version version, Map<String, ?> attributes) {
+ return getImplementation().createGenericDescription(name, type, version, attributes);
+ }
+
+ @Override
+ public GenericDescription createGenericDescription(String type, Map<String, ?> attributes, Map<String, String> directives, BundleDescription supplier) {
+ return getImplementation().createGenericDescription(type, attributes, directives, supplier);
+ }
+
+ @Override
+ public List<GenericDescription> createGenericDescriptions(String declaration) {
+ return getImplementation().createGenericDescriptions(declaration);
+ }
+
+ @Override
+ public GenericSpecification createGenericSpecification(String name, String type, String matchingFilter, boolean optional, boolean multiple) throws InvalidSyntaxException {
+ return getImplementation().createGenericSpecification(name, type, matchingFilter, optional, multiple);
+ }
+
+ @Override
+ public List<GenericSpecification> createGenericSpecifications(String declaration) {
+ return getImplementation().createGenericSpecifications(declaration);
+ }
+
+ @Override
+ public NativeCodeSpecification createNativeCodeSpecification(NativeCodeDescription[] nativeCodeDescriptions, boolean optional) {
+ return getImplementation().createNativeCodeSpecification(nativeCodeDescriptions, optional);
+ }
+
+ @Override
+ public NativeCodeDescription createNativeCodeDescription(String[] nativePaths, String[] processors, String[] osNames, VersionRange[] osVersions, String[] languages, String filter) throws InvalidSyntaxException {
+ return getImplementation().createNativeCodeDescription(nativePaths, processors, osNames, osVersions, languages, filter);
+ }
+
+ @Override
+ public ExportPackageDescription createExportPackageDescription(ExportPackageDescription original) {
+ return getImplementation().createExportPackageDescription(original);
+ }
+
+ @Override
+ public List<ExportPackageDescription> createExportPackageDescriptions(String declaration) {
+ return getImplementation().createExportPackageDescriptions(declaration);
+ }
+
+ @Deprecated
+ @Override
+ public void writeState(State state, OutputStream stream) throws IOException {
+ getImplementation().writeState(state, stream);
+ }
+
+ @Deprecated
+ @Override
+ public void writeState(State state, DataOutputStream stream) throws IOException {
+ getImplementation().writeState(state, stream);
+ }
+
+ @Override
+ public void writeState(State state, File stateDirectory) throws IOException {
+ getImplementation().writeState(state, stateDirectory);
+ }
+
+ @Deprecated
+ @Override
+ public State readState(InputStream stream) throws IOException {
+ return getImplementation().readState(stream);
+ }
+
+ @Deprecated
+ @Override
+ public State readState(DataInputStream stream) throws IOException {
+ return getImplementation().readState(stream);
+ }
+
+ @Override
+ public State readState(File stateDirectory) throws IOException {
+ return getImplementation().readState(stateDirectory);
+ }
+ }
}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateWire.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateWire.java
index 2b2afdf4b..2b2afdf4b 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateWire.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/StateWire.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/VersionConstraint.java
index 2f15515f8..2f15515f8 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/VersionConstraint.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionRange.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/VersionRange.java
index 3b1c6506b..3b1c6506b 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionRange.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/VersionRange.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/package.html
index 04babd03f..04babd03f 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/resolver/package.html
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/service/security/TrustEngine.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/security/TrustEngine.java
index e4c9c977e..f142c8ecd 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/service/security/TrustEngine.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/security/TrustEngine.java
@@ -48,7 +48,7 @@ public abstract class TrustEngine {
*/
public String addTrustAnchor(Certificate anchor, String alias) throws IOException, GeneralSecurityException {
String storedAlias = doAddTrustAnchor(anchor, alias);
- TrustEngineListener listener = TrustEngineListener.getInstance();
+ TrustEngineListener listener = trustEngineListener;
if (listener != null)
listener.addedTrustAnchor(anchor);
return storedAlias;
@@ -76,7 +76,7 @@ public abstract class TrustEngine {
*/
public final void removeTrustAnchor(Certificate anchor) throws IOException, GeneralSecurityException {
doRemoveTrustAnchor(anchor);
- TrustEngineListener listener = TrustEngineListener.getInstance();
+ TrustEngineListener listener = trustEngineListener;
if (listener != null)
listener.removedTrustAnchor(anchor);
}
@@ -99,7 +99,7 @@ public abstract class TrustEngine {
Certificate existing = getTrustAnchor(alias);
doRemoveTrustAnchor(alias);
if (existing != null) {
- TrustEngineListener listener = TrustEngineListener.getInstance();
+ TrustEngineListener listener = trustEngineListener;
if (listener != null)
listener.removedTrustAnchor(existing);
}
@@ -143,4 +143,6 @@ public abstract class TrustEngine {
* @return a string
*/
public abstract String getName();
+
+ private volatile TrustEngineListener trustEngineListener;
}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/service/security/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/security/package.html
index de7f5c952..de7f5c952 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/service/security/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/service/security/package.html
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/InvalidContentException.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/InvalidContentException.java
index 846c307df..846c307df 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/InvalidContentException.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/InvalidContentException.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContent.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContent.java
index 918f1a03c..918f1a03c 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContent.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContent.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContentEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContentEntry.java
index 27f154b48..27f154b48 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContentEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContentEntry.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContentFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContentFactory.java
index bfd405dac..bfd405dac 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignedContentFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignedContentFactory.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignerInfo.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignerInfo.java
index c5bc14dd8..c5bc14dd8 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/SignerInfo.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/SignerInfo.java
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/package.html
index 79563e3b7..79563e3b7 100644
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/signedcontent/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/signedcontent/package.html
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java
new file mode 100644
index 000000000..9dc2ab263
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java
@@ -0,0 +1,461 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.storage;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import org.eclipse.osgi.container.ModuleRevision;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.framework.util.Headers;
+import org.eclipse.osgi.internal.container.LockSet;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
+import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.url.BundleResourceHandler;
+import org.eclipse.osgi.storage.url.bundleentry.Handler;
+import org.osgi.framework.BundleException;
+
+public final class BundleInfo {
+ public static final String OSGI_BUNDLE_MANIFEST = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
+
+ public final class Generation {
+ private final long generationId;
+ private final Object genMonitor = new Object();
+ private final Dictionary<String, String> cachedHeaders;
+ private File content;
+ private boolean isDirectory;
+ private boolean hasPackageInfo;
+ private BundleFile bundleFile;
+ private Dictionary<String, String> rawHeaders;
+ private ModuleRevision revision;
+ private ManifestLocalization headerLocalization;
+ private ProtectionDomain domain;
+ private NativeCodeFinder nativeCodeFinder;
+ private List<StorageHook<?, ?>> storageHooks;
+
+ Generation(long generationId) {
+ this.generationId = generationId;
+ this.cachedHeaders = new CachedManifest(this, Collections.<String, String> emptyMap());
+ }
+
+ Generation(long generationId, File content, boolean isDirectory, boolean hasPackageInfo, Map<String, String> cached) {
+ this.generationId = generationId;
+ this.content = content;
+ this.isDirectory = isDirectory;
+ this.hasPackageInfo = hasPackageInfo;
+ this.cachedHeaders = new CachedManifest(this, cached);
+ }
+
+ public BundleFile getBundleFile() {
+ synchronized (genMonitor) {
+ if (bundleFile == null) {
+ if (getBundleId() == 0 && content == null) {
+ bundleFile = new SystemBundleFile();
+ } else {
+ bundleFile = getStorage().createBundleFile(content, this, isDirectory, true);
+ }
+ }
+ return bundleFile;
+ }
+ }
+
+ public void close() {
+ synchronized (genMonitor) {
+ if (bundleFile != null) {
+ try {
+ bundleFile.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ public Dictionary<String, String> getHeaders() {
+ return cachedHeaders;
+ }
+
+ Dictionary<String, String> getRawHeaders() {
+ synchronized (genMonitor) {
+ if (rawHeaders == null) {
+ BundleEntry manifest = getBundleFile().getEntry(OSGI_BUNDLE_MANIFEST);
+ try {
+ rawHeaders = Headers.parseManifest(manifest.getInputStream());
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new RuntimeException("Error occurred getting the bundle manifest.", e); //$NON-NLS-1$
+ }
+ }
+ return rawHeaders;
+ }
+ }
+
+ public Dictionary<String, String> getHeaders(String locale) {
+ ManifestLocalization current = getManifestLocalization();
+ return current.getHeaders(locale);
+ }
+
+ public ResourceBundle getResourceBundle(String locale) {
+ ManifestLocalization current = getManifestLocalization();
+ String defaultLocale = Locale.getDefault().toString();
+ if (locale == null) {
+ locale = defaultLocale;
+ }
+ return current.getResourceBundle(locale, defaultLocale.equals(locale));
+ }
+
+ private ManifestLocalization getManifestLocalization() {
+ synchronized (genMonitor) {
+ if (headerLocalization == null) {
+ headerLocalization = new ManifestLocalization(this, getHeaders(), getStorage().getConfiguration().getConfiguration(EquinoxConfiguration.PROP_ROOT_LOCALE, "en")); //$NON-NLS-1$
+ }
+ return headerLocalization;
+ }
+ }
+
+ public void clearManifestCache() {
+ synchronized (genMonitor) {
+ if (headerLocalization != null) {
+ headerLocalization.clearCache();
+ }
+ }
+ }
+
+ public long getGenerationId() {
+ return this.generationId;
+ }
+
+ public boolean isDirectory() {
+ synchronized (this.genMonitor) {
+ return this.isDirectory;
+ }
+ }
+
+ public boolean hasPackageInfo() {
+ synchronized (this.genMonitor) {
+ return this.hasPackageInfo;
+ }
+ }
+
+ public File getContent() {
+ synchronized (this.genMonitor) {
+ return this.content;
+ }
+ }
+
+ void setContent(File content) {
+ synchronized (this.genMonitor) {
+ this.content = content;
+ this.isDirectory = content == null ? false : Storage.secureAction.isDirectory(content);
+ }
+ }
+
+ void setStorageHooks(List<StorageHook<?, ?>> storageHooks, boolean install) {
+ synchronized (this.genMonitor) {
+ this.storageHooks = storageHooks;
+ if (install) {
+ this.hasPackageInfo = BundleInfo.hasPackageInfo(getBundleFile());
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <S, L, H extends StorageHook<S, L>> H getStorageHook(Class<? extends StorageHookFactory<S, L, H>> factoryClass) {
+ synchronized (this.genMonitor) {
+ if (this.storageHooks == null)
+ return null;
+ for (StorageHook<?, ?> hook : storageHooks) {
+ if (hook.getFactoryClass().equals(factoryClass)) {
+ return (H) hook;
+ }
+ }
+ }
+ return null;
+ }
+
+ public ModuleRevision getRevision() {
+ synchronized (this.genMonitor) {
+ return this.revision;
+ }
+ }
+
+ public void setRevision(ModuleRevision revision) {
+ synchronized (this.genMonitor) {
+ this.revision = revision;
+ }
+ }
+
+ public ProtectionDomain getDomain() {
+ if (getBundleId() == 0) {
+ return null;
+ }
+ synchronized (this.genMonitor) {
+ if (domain == null && System.getSecurityManager() != null) {
+ if (revision == null) {
+ throw new IllegalStateException("The revision is not yet set for this generation."); //$NON-NLS-1$
+ }
+ domain = getStorage().getSecurityAdmin().createProtectionDomain(revision.getBundle());
+ }
+ return domain;
+ }
+ }
+
+ /**
+ * Gets called by BundleFile during {@link BundleFile#getFile(String, boolean)}. This method
+ * will allocate a File object where content of the specified path may be
+ * stored for this generation. The returned File object may
+ * not exist if the content has not previously been stored.
+ * @param path the path to the content to extract from the generation
+ * @return a file object where content of the specified path may be stored.
+ */
+ public File getExtractFile(String path) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(getBundleId()).append('/').append(getGenerationId());
+ if (path.length() > 0 && path.charAt(0) != '/') {
+ builder.append('/');
+ }
+ builder.append(path);
+ return getStorage().getFile(builder.toString(), true);
+ }
+
+ public BundleInfo getBundleInfo() {
+ return BundleInfo.this;
+ }
+
+ public void delete() {
+ synchronized (this.genMonitor) {
+ // make sure the bundle file is closed
+ if (bundleFile != null) {
+ try {
+ bundleFile.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ getBundleInfo().delete(this);
+ }
+
+ public URL getEntry(String path) {
+ BundleEntry entry = getBundleFile().getEntry(path);
+ if (entry == null)
+ return null;
+ path = BundleFile.fixTrailingSlash(path, entry);
+ try {
+ //use the constant string for the protocol to prevent duplication
+ return Storage.secureAction.getURL(BundleResourceHandler.OSGI_ENTRY_URL_PROTOCOL, Long.toString(getBundleId()) + BundleResourceHandler.BID_FWKID_SEPARATOR + Integer.toString(getStorage().getModuleContainer().hashCode()), 0, path, new Handler(getStorage().getModuleContainer(), entry));
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ public String findLibrary(String libname) {
+ NativeCodeFinder currentFinder;
+ synchronized (this.genMonitor) {
+ if (nativeCodeFinder == null) {
+ nativeCodeFinder = new NativeCodeFinder(this);
+ }
+ currentFinder = nativeCodeFinder;
+ }
+ return currentFinder.findLibrary(libname);
+ }
+ }
+
+ private final Storage storage;
+ private final long bundleId;
+ private long nextGenerationId;
+ private final Object infoMonitor = new Object();
+ private LockSet<Long> generationLocks;
+
+ public BundleInfo(Storage storage, long bundleId, long nextGenerationId) {
+ this.storage = storage;
+ this.bundleId = bundleId;
+ this.nextGenerationId = nextGenerationId;
+ }
+
+ public long getBundleId() {
+ return bundleId;
+ }
+
+ Generation createGeneration() throws BundleException {
+ synchronized (this.infoMonitor) {
+ if (generationLocks == null) {
+ generationLocks = new LockSet<Long>();
+ }
+ boolean lockedID;
+ try {
+ lockedID = generationLocks.tryLock(nextGenerationId, 5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new BundleException("Failed to obtain id locks for generation.", BundleException.STATECHANGE_ERROR, e); //$NON-NLS-1$
+ }
+ if (!lockedID) {
+ throw new BundleException("Failed to obtain id locks for generation.", BundleException.STATECHANGE_ERROR); //$NON-NLS-1$
+ }
+ Generation newGeneration = new Generation(nextGenerationId++);
+ return newGeneration;
+ }
+ }
+
+ void unlockGeneration(Generation generation) {
+ synchronized (this.infoMonitor) {
+ if (generationLocks == null) {
+ throw new IllegalStateException("The generation id was not locked."); //$NON-NLS-1$
+ }
+ generationLocks.unlock(generation.getGenerationId());
+ }
+ }
+
+ Generation restoreGeneration(long generationId, File content, boolean isDirectory, boolean hasPackageInfo, Map<String, String> cached) {
+ synchronized (this.infoMonitor) {
+ Generation restoredGeneration = new Generation(generationId, content, isDirectory, hasPackageInfo, cached);
+ return restoredGeneration;
+ }
+ }
+
+ public Storage getStorage() {
+ return storage;
+ }
+
+ public void delete() {
+ try {
+ getStorage().delete(getStorage().getFile(Long.toString(getBundleId()), false));
+ } catch (IOException e) {
+ storage.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Error deleting bunlde info.", e); //$NON-NLS-1$
+ }
+ }
+
+ void delete(Generation generation) {
+ try {
+ getStorage().delete(getStorage().getFile(getBundleId() + "/" + generation.getGenerationId(), false)); //$NON-NLS-1$
+ } catch (IOException e) {
+ storage.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Error deleting generation.", e); //$NON-NLS-1$
+ }
+ }
+
+ public long getNextGenerationId() {
+ synchronized (this.infoMonitor) {
+ return nextGenerationId;
+ }
+ }
+
+ public File getDataFile(String path) {
+ File dataRoot = getStorage().getFile(getBundleId() + "/" + Storage.BUNDLE_DATA_DIR, false); //$NON-NLS-1$
+ if (!Storage.secureAction.exists(dataRoot) && (storage.isReadOnly() || !Storage.secureAction.mkdirs(dataRoot))) {
+ if (getStorage().getConfiguration().getDebug().DEBUG_GENERAL)
+ Debug.println("Unable to create bundle data directory: " + dataRoot.getAbsolutePath()); //$NON-NLS-1$
+ return null;
+ }
+ return path == null ? dataRoot : new File(dataRoot, path);
+ }
+
+ // Used to check the bundle manifest file for any package information.
+ // This is used when '.' is on the Bundle-ClassPath to prevent reading
+ // the bundle manifest for package information when loading classes.
+ static boolean hasPackageInfo(BundleFile bundleFile) {
+ if (bundleFile == null) {
+ return false;
+ }
+ BundleEntry manifest = bundleFile.getEntry(OSGI_BUNDLE_MANIFEST);
+ if (manifest == null) {
+ return false;
+ }
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new InputStreamReader(manifest.getInputStream()));
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (line.length() < 20)
+ continue;
+ switch (line.charAt(0)) {
+ case 'S' :
+ if (line.charAt(1) == 'p')
+ if (line.startsWith("Specification-Title: ") || line.startsWith("Specification-Version: ") || line.startsWith("Specification-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
+ return true;
+ break;
+ case 'I' :
+ if (line.startsWith("Implementation-Title: ") || line.startsWith("Implementation-Version: ") || line.startsWith("Implementation-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
+ return true;
+ break;
+ }
+ }
+ } catch (IOException ioe) {
+ // do nothing
+ } finally {
+ if (br != null)
+ try {
+ br.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ return false;
+ }
+
+ static class CachedManifest extends Dictionary<String, String> {
+ private final Map<String, String> cached;
+ private final Generation generation;
+
+ CachedManifest(Generation generation, Map<String, String> cached) {
+ this.generation = generation;
+ this.cached = cached;
+ }
+
+ @Override
+ public Enumeration<String> elements() {
+ return generation.getRawHeaders().elements();
+ }
+
+ @Override
+ public String get(Object key) {
+ if (cached.containsKey(key)) {
+ return cached.get(key);
+ }
+ return generation.getRawHeaders().get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return generation.getRawHeaders().isEmpty();
+ }
+
+ @Override
+ public Enumeration<String> keys() {
+ return generation.getRawHeaders().keys();
+ }
+
+ @Override
+ public String put(String key, String value) {
+ return generation.getRawHeaders().put(key, value);
+ }
+
+ @Override
+ public String remove(Object key) {
+ return generation.getRawHeaders().remove(key);
+ }
+
+ @Override
+ public int size() {
+ return generation.getRawHeaders().size();
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/BundleLocalizationImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleLocalizationImpl.java
index e2eb1d829..c9c0303b5 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/BundleLocalizationImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleLocalizationImpl.java
@@ -8,10 +8,14 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.storage;
import java.util.ResourceBundle;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleRevision;
+import org.eclipse.osgi.internal.framework.EquinoxBundle;
import org.eclipse.osgi.service.localization.BundleLocalization;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.osgi.framework.Bundle;
/**
@@ -30,6 +34,9 @@ public class BundleLocalizationImpl implements BundleLocalization {
* If null is passed for the locale parameter, the default locale is used.
*/
public ResourceBundle getLocalization(Bundle bundle, String locale) {
- return ((org.eclipse.osgi.framework.internal.core.AbstractBundle) (bundle)).getResourceBundle(locale);
+ Module m = ((EquinoxBundle) bundle).getModule();
+ ModuleRevision r = m.getCurrentRevision();
+ Generation g = (Generation) r.getRevisionInfo();
+ return g.getResourceBundle(locale);
}
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
new file mode 100644
index 000000000..e1b2f26f0
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.storage;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.*;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.osgi.container.ModuleCapability;
+import org.eclipse.osgi.container.ModuleRevision;
+import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
+import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.osgi.framework.BundleException;
+
+public class FrameworkExtensionInstaller {
+ private static final ClassLoader CL = FrameworkExtensionInstaller.class.getClassLoader();
+ private static final Method ADD_FWK_URL_METHOD = findAddURLMethod(CL, "addURL"); //$NON-NLS-1$
+
+ private static Method findAddURLMethod(ClassLoader cl, String name) {
+ if (cl == null)
+ return null;
+ return findMethod(cl.getClass(), name, new Class[] {URL.class});
+ }
+
+ // recursively searches a class and it's superclasses for a (potentially inaccessable) method
+ private static Method findMethod(Class<?> clazz, String name, Class<?>[] args) {
+ if (clazz == null)
+ return null; // ends the recursion when getSuperClass returns null
+ try {
+ Method result = clazz.getDeclaredMethod(name, args);
+ result.setAccessible(true);
+ return result;
+ } catch (NoSuchMethodException e) {
+ // do nothing look in super class below
+ } catch (SecurityException e) {
+ // if we do not have the permissions then we will not find the method
+ }
+ return findMethod(clazz.getSuperclass(), name, args);
+ }
+
+ private static void callAddURLMethod(URL arg) throws InvocationTargetException {
+ try {
+ ADD_FWK_URL_METHOD.invoke(CL, new Object[] {arg});
+ } catch (Throwable t) {
+ throw new InvocationTargetException(t);
+ }
+ }
+
+ private final EquinoxConfiguration configuration;
+
+ public FrameworkExtensionInstaller(EquinoxConfiguration configuraiton) {
+ this.configuration = configuraiton;
+ }
+
+ public void addExtensionContent(final ModuleRevision revision) throws BundleException {
+ if (System.getSecurityManager() == null) {
+ addExtensionContent0(revision);
+ } else {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws BundleException {
+ addExtensionContent0(revision);
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (BundleException) e.getCause();
+ }
+ }
+ }
+
+ void addExtensionContent0(ModuleRevision revision) throws BundleException {
+ if (CL == null || ADD_FWK_URL_METHOD == null) {
+ return;
+ }
+
+ File[] files = getExtensionFiles(revision);
+ if (files == null) {
+ return;
+ }
+ for (int i = 0; i < files.length; i++) {
+ if (files[i] == null)
+ continue;
+ try {
+ callAddURLMethod(AdaptorUtil.encodeFileURL(files[i]));
+ } catch (InvocationTargetException e) {
+ throw new BundleException("Error adding extension content.", e);
+ } catch (MalformedURLException e) {
+ throw new BundleException("Error adding extension content.", e);
+ }
+ }
+ try {
+ // initialize the new urls
+ CL.loadClass("thisIsNotAClass"); //$NON-NLS-1$
+ } catch (ClassNotFoundException e) {
+ // do nothing
+ }
+ }
+
+ /**
+ * Returns a list of classpath files for an extension bundle
+ * @param revision revision for the extension bundle
+ * @return a list of classpath files for an extension bundle
+ */
+ private File[] getExtensionFiles(ModuleRevision revision) {
+ List<ModuleCapability> metaDatas = revision.getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
+ @SuppressWarnings("unchecked")
+ List<String> paths = metaDatas.isEmpty() ? null : (List<String>) metaDatas.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_CLASSPATH);
+ if (paths == null) {
+ paths = new ArrayList<String>(1);
+ paths.add("."); //$NON-NLS-1$
+ }
+ if (configuration.inDevelopmentMode()) {
+ String[] devPaths = configuration.getDevClassPath(revision.getSymbolicName());
+ for (String devPath : devPaths) {
+ paths.add(devPath);
+ }
+ }
+ List<File> results = new ArrayList<File>(paths.size());
+ for (String path : paths) {
+ if (".".equals(path)) { //$NON-NLS-1$
+ results.add(((Generation) revision.getRevisionInfo()).getBundleFile().getBaseFile());
+ } else {
+ File result = ((Generation) revision.getRevisionInfo()).getBundleFile().getFile(path, false);
+ if (result != null)
+ results.add(result);
+ }
+ }
+ return results.toArray(new File[results.size()]);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ManifestLocalization.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/ManifestLocalization.java
index 5212b1733..ac57d6a58 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ManifestLocalization.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/ManifestLocalization.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * Copyright (c) 2004, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,32 +8,45 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.storage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
+import org.eclipse.osgi.container.*;
import org.eclipse.osgi.framework.util.Headers;
-import org.osgi.framework.Bundle;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.osgi.framework.Constants;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.wiring.BundleRevision;
/**
- * This class is used by the Bundle Class to localize manifest headers.
+ * This class is used to localize manifest headers for a revision.
*/
public class ManifestLocalization {
- final static String DEFAULT_ROOT = FrameworkProperties.getProperty("equinox.root.locale", "en"); //$NON-NLS-1$ //$NON-NLS-2$
- private final AbstractBundle bundle;
+ final String defaultRoot;
+ private final Generation generation;
private final Dictionary<String, String> rawHeaders;
- private Dictionary<String, String> defaultLocaleHeaders = null;
+ private volatile Dictionary<String, String> defaultLocaleHeaders = null;
private final Hashtable<String, BundleResourceBundle> cache = new Hashtable<String, BundleResourceBundle>(5);
- public ManifestLocalization(AbstractBundle bundle, Dictionary<String, String> rawHeaders) {
- this.bundle = bundle;
+ public ManifestLocalization(Generation generation, Dictionary<String, String> rawHeaders, String defaultRoot) {
+ this.generation = generation;
this.rawHeaders = rawHeaders;
+ this.defaultRoot = defaultRoot;
+ }
+
+ public void clearCache() {
+ synchronized (cache) {
+ cache.clear();
+ defaultLocaleHeaders = null;
+ }
}
Dictionary<String, String> getHeaders(String localeString) {
+ if (localeString == null)
+ localeString = Locale.getDefault().toString();
if (localeString.length() == 0)
return rawHeaders;
boolean isDefaultLocale = localeString.equals(Locale.getDefault().toString());
@@ -41,19 +54,17 @@ public class ManifestLocalization {
if (isDefaultLocale && currentDefault != null) {
return currentDefault;
}
- try {
- bundle.checkValid();
- } catch (IllegalStateException ex) {
+ if (generation.getRevision().getRevisions().getModule().getState().equals(Module.State.UNINSTALLED)) {
// defaultLocaleHeaders should have been initialized on uninstall
if (currentDefault != null)
return currentDefault;
return rawHeaders;
}
ResourceBundle localeProperties = getResourceBundle(localeString, isDefaultLocale);
- Enumeration<String> e = this.rawHeaders.keys();
+ Enumeration<String> eKeys = this.rawHeaders.keys();
Headers<String, String> localeHeaders = new Headers<String, String>(this.rawHeaders.size());
- while (e.hasMoreElements()) {
- String key = e.nextElement();
+ while (eKeys.hasMoreElements()) {
+ String key = eKeys.nextElement();
String value = this.rawHeaders.get(key);
if (value.startsWith("%") && (value.length() > 1)) { //$NON-NLS-1$
String propertiesKey = value.substring(1);
@@ -147,34 +158,33 @@ public class ManifestLocalization {
}
private URL findResource(String resource) {
- AbstractBundle searchBundle = bundle;
- if (bundle.isResolved()) {
- if (bundle.isFragment() && bundle.getHosts() != null) {
- //if the bundle is a fragment, look in the host first
- searchBundle = bundle.getHosts()[0];
- if (searchBundle.getState() == Bundle.UNINSTALLED)
- searchBundle = bundle;
+ ModuleWiring searchWiring = generation.getRevision().getWiring();
+ if (searchWiring != null) {
+ if ((generation.getRevision().getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ List<ModuleWire> hostWires = searchWiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ searchWiring = null;
+ Long lowestHost = Long.MAX_VALUE;
+ if (hostWires != null) {
+ // search for the host with the highest ID
+ for (ModuleWire hostWire : hostWires) {
+ Long hostID = hostWire.getProvider().getRevisions().getModule().getId();
+ if (hostID.compareTo(lowestHost) <= 0) {
+ lowestHost = hostID;
+ searchWiring = hostWire.getProviderWiring();
+ }
+ }
+ }
}
- return findInResolved(resource, searchBundle);
}
- return searchBundle.getEntry0(resource);
- }
-
- private static URL findInResolved(String filePath, AbstractBundle bundleHost) {
- URL result = bundleHost.getEntry0(filePath);
- if (result != null)
- return result;
- return findInFragments(filePath, bundleHost);
- }
-
- private static URL findInFragments(String filePath, AbstractBundle searchBundle) {
- BundleFragment[] fragments = searchBundle.getFragments();
- URL fileURL = null;
- for (int i = 0; fragments != null && i < fragments.length && fileURL == null; i++) {
- if (fragments[i].getState() != Bundle.UNINSTALLED)
- fileURL = fragments[i].getEntry0(filePath);
+ if (searchWiring != null) {
+ int lastSlash = resource.lastIndexOf('/');
+ String path = lastSlash > 0 ? resource.substring(0, lastSlash) : "/"; //$NON-NLS-1$
+ String fileName = lastSlash != -1 ? resource.substring(lastSlash + 1) : resource;
+ List<URL> result = searchWiring.findEntries(path, fileName, 0);
+ return (result == null || result.isEmpty()) ? null : result.get(0);
}
- return fileURL;
+ // search the raw bundle file for the generation
+ return generation.getEntry(resource);
}
private interface BundleResourceBundle {
@@ -231,7 +241,7 @@ public class ManifestLocalization {
}
public boolean isStemEmpty() {
- if (DEFAULT_ROOT.equals(localeString))
+ if (defaultRoot.equals(localeString))
return false;
if (parent == null)
return true;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/NativeCodeFinder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/NativeCodeFinder.java
new file mode 100644
index 000000000..2ffbc3043
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/NativeCodeFinder.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.storage;
+
+import java.io.File;
+import java.util.*;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.namespaces.EquinoxNativeCodeNamespace;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class NativeCodeFinder {
+ private static final String[] EMPTY_STRINGS = new String[0];
+ public static final String EXTERNAL_LIB_PREFIX = "external:"; //$NON-NLS-1$
+ private final Generation generation;
+ private final Debug debug;
+ // This is only used to keep track of when the same native library is loaded more than once
+ private final Collection<String> loadedNativeCode = new ArrayList<String>(1);
+
+ public NativeCodeFinder(Generation generation) {
+ this.generation = generation;
+ this.debug = generation.getBundleInfo().getStorage().getConfiguration().getDebug();
+ }
+
+ /*
+ * Maps an already mapped library name to additional library file extensions.
+ * This is needed on platforms like AIX where .a and .so can be used as library file
+ * extensions, but System.mapLibraryName only returns a single string.
+ */
+ public String[] mapLibraryNames(String mappedLibName) {
+ int extIndex = mappedLibName.lastIndexOf('.');
+ List<String> LIB_EXTENSIONS = generation.getBundleInfo().getStorage().getConfiguration().LIB_EXTENSIONS;
+ if (LIB_EXTENSIONS.isEmpty() || extIndex < 0)
+ return EMPTY_STRINGS;
+ String libNameBase = mappedLibName.substring(0, extIndex);
+ String[] results = new String[LIB_EXTENSIONS.size()];
+ for (int i = 0; i < results.length; i++)
+ results[i] = libNameBase + LIB_EXTENSIONS.get(i);
+ return results;
+ }
+
+ String findLibrary(String libname) {
+ String path = findLibrary0(libname);
+ if (path != null) {
+ synchronized (loadedNativeCode) {
+ if (loadedNativeCode.contains(path) || generation.getBundleInfo().getStorage().getConfiguration().COPY_NATIVES) {
+ // we must copy the library to a temp space to allow another class loader to load the library
+ String temp = generation.getBundleInfo().getStorage().copyToTempLibrary(generation, path);
+ if (temp != null)
+ path = temp;
+ } else {
+ loadedNativeCode.add(path);
+ }
+ }
+ }
+ return path;
+ }
+
+ private String findLibrary0(String libname) {
+ String path = null;
+ List<ClassLoaderHook> hooks = generation.getBundleInfo().getStorage().getConfiguration().getHookRegistry().getClassLoaderHooks();
+ for (ClassLoaderHook hook : hooks) {
+ path = hook.findLocalLibrary(generation, libname);
+ if (path != null) {
+ return path;
+ }
+ }
+ String mappedName = System.mapLibraryName(libname);
+ String[] altMappedNames = mapLibraryNames(mappedName);
+
+ // first check Bundle-NativeCode header
+ path = findBundleNativeCode(libname, mappedName, altMappedNames);
+ // next check eclipse specific support
+ return path != null ? path : findEclipseNativeCode(libname, mappedName, altMappedNames);
+ }
+
+ private String findEclipseNativeCode(String libname, String mappedName, String[] altMappedNames) {
+ if (libname.length() == 0)
+ return null;
+ if (libname.charAt(0) == '/' || libname.charAt(0) == '\\')
+ libname = libname.substring(1);
+ String result = searchEclipseVariants(mappedName);
+ if (result != null)
+ return result;
+ for (int i = 0; i < altMappedNames.length && result == null; i++)
+ result = searchEclipseVariants(altMappedNames[i]);
+ return result;
+ }
+
+ private String searchEclipseVariants(String path) {
+ List<String> ECLIPSE_LIB_VARIANTS = generation.getBundleInfo().getStorage().getConfiguration().ECLIPSE_LIB_VARIANTS;
+ for (String variant : ECLIPSE_LIB_VARIANTS) {
+ BundleFile baseBundleFile = generation.getBundleFile();
+ BundleEntry libEntry = baseBundleFile.getEntry(variant + path);
+ if (libEntry != null) {
+ File libFile = baseBundleFile.getFile(variant + path, true);
+ if (libFile == null)
+ return null;
+ // see bug 88697 - HP requires libraries to have executable permissions
+ if (org.eclipse.osgi.service.environment.Constants.OS_HPUX.equals(generation.getBundleInfo().getStorage().getConfiguration().getOS())) {
+ try {
+ // use the string array method in case there is a space in the path
+ Runtime.getRuntime().exec(new String[] {"chmod", "755", libFile.getAbsolutePath()}).waitFor(); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return libFile.getAbsolutePath();
+ }
+ }
+ return null;
+ }
+
+ private String findBundleNativeCode(String libname, String mappedName, String[] altMappedNames) {
+ String path = null;
+ if (debug.DEBUG_LOADER)
+ Debug.println(" mapped library name: " + mappedName); //$NON-NLS-1$
+ List<String> nativePaths = getNativePaths();
+ if (nativePaths.isEmpty()) {
+ return null;
+ }
+ path = findNativePath(nativePaths, mappedName);
+ if (path == null) {
+ for (int i = 0; i < altMappedNames.length && path == null; i++)
+ path = findNativePath(nativePaths, altMappedNames[i]);
+ }
+ if (path == null) {
+ if (debug.DEBUG_LOADER)
+ Debug.println(" library does not exist: " + mappedName); //$NON-NLS-1$
+ path = findNativePath(nativePaths, libname);
+ }
+ if (debug.DEBUG_LOADER)
+ Debug.println(" returning library: " + path); //$NON-NLS-1$
+ return path;
+ }
+
+ private List<String> getNativePaths() {
+ ModuleRevision revision = generation.getRevision();
+ ModuleWiring wiring = revision.getWiring();
+ if (wiring == null) {
+ // unresolved? should not be possible
+ return Collections.emptyList();
+ }
+ if ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ List<ModuleWire> hosts = wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE);
+ if (!hosts.isEmpty()) {
+ // just use the first host wiring
+ wiring = hosts.get(0).getProviderWiring();
+ }
+ }
+
+ List<ModuleWire> nativeCode = wiring.getRequiredModuleWires(EquinoxNativeCodeNamespace.EQUINOX_NATIVECODE_NAMESPACE);
+ if (nativeCode.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // TODO just taking the first paths for the revision, need to sort correctly
+ for (ModuleWire moduleWire : nativeCode) {
+ if (moduleWire.getRequirement().getRevision().equals(revision)) {
+ @SuppressWarnings("unchecked")
+ List<String> result = (List<String>) nativeCode.get(0).getRequirement().getAttributes().get(EquinoxNativeCodeNamespace.REQUIREMENT_NATIVE_PATHS_ATTRIBUTE);
+ if (result != null)
+ return result;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private String findNativePath(List<String> nativePaths, String libname) {
+ int slash = libname.lastIndexOf('/');
+ if (slash >= 0)
+ libname = libname.substring(slash + 1);
+ for (String nativePath : nativePaths) {
+ slash = nativePath.lastIndexOf('/');
+ String path = slash < 0 ? nativePath : nativePath.substring(slash + 1);
+ if (path.equals(libname)) {
+ if (nativePath.startsWith(NativeCodeFinder.EXTERNAL_LIB_PREFIX)) {
+ // references an external library; do variable substitution
+ String externalPath = generation.getBundleInfo().getStorage().getConfiguration().substituteVars(nativePath.substring(NativeCodeFinder.EXTERNAL_LIB_PREFIX.length()));
+ File nativeFile = new File(externalPath);
+ return nativeFile.getAbsolutePath();
+ }
+ // this is a normal library contained within the bundle
+ File nativeFile = generation.getBundleFile().getFile(nativePath, true);
+ if (nativeFile != null)
+ return nativeFile.getAbsolutePath();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/PermissionData.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/PermissionData.java
new file mode 100644
index 000000000..b45e3ee7f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/PermissionData.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.storage;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Permission Storage interface for managing a persistent storage of
+ * bundle permissions.
+ *
+ * <p>This class is used to provide methods to manage
+ * persistent storage of bundle permissions.
+ */
+public class PermissionData {
+ private static final int PERMDATA_VERSION = 1;
+ private final Map<String, String[]> locations = new HashMap<String, String[]>();
+ private String[] defaultInfos;
+ private String[] condPermInfos;
+ private boolean dirty;
+
+ /**
+ * Returns the locations that have permission data assigned to them,
+ * that is, locations for which permission data
+ * exists in persistent storage.
+ *
+ * @return The locations that have permission data in
+ * persistent storage, or <tt>null</tt> if there is no permission data
+ * in persistent storage.
+ */
+ public String[] getLocations() {
+ synchronized (locations) {
+ String[] result = new String[locations.size()];
+ int i = 0;
+ for (Iterator<String> iLocs = locations.keySet().iterator(); iLocs.hasNext(); i++)
+ result[i] = iLocs.next();
+ return result;
+ }
+ }
+
+ /**
+ * Gets the permission data assigned to the specified
+ * location.
+ *
+ * @param location The location whose permission data is to
+ * be returned.
+ * The location can be <tt>null</tt> for the default permission data.
+ *
+ * @return The permission data assigned to the specified
+ * location, or <tt>null</tt> if that location has not been assigned any
+ * permission data.
+ */
+ public String[] getPermissionData(String location) {
+ if (location == null)
+ return defaultInfos;
+ synchronized (locations) {
+ if (locations.size() == 0)
+ return null;
+ return locations.get(location);
+ }
+ }
+
+ /**
+ * Assigns the specified permission data to the specified
+ * location.
+ *
+ * @param location The location that will be assigned the
+ * permissions.
+ * The location can be <tt>null</tt> for the default permission data.
+ * @param data The permission data to be assigned, or <tt>null</tt>
+ * if the specified location is to be removed from persistent storaqe.
+ */
+ public void setPermissionData(String location, String[] data) {
+ if (location == null) {
+ defaultInfos = data;
+ return;
+ }
+ synchronized (locations) {
+ if (data == null)
+ locations.remove(location);
+ else
+ locations.put(location, data);
+ }
+ setDirty(true);
+ }
+
+ /**
+ * Persists the array of encoded ConditionalPermissionInfo strings
+ * @param infos an array of encoded ConditionalPermissionInfo strings
+ */
+ public void saveConditionalPermissionInfos(String[] infos) {
+ condPermInfos = infos;
+ setDirty(true);
+ }
+
+ /**
+ * Returns the persistent array of encoded ConditionalPermissionInfo strings
+ * @return an array of encoded ConditionalPermissionInfo strings or null
+ * if none exist in persistent storage.
+ */
+ public String[] getConditionalPermissionInfos() {
+ return condPermInfos;
+ }
+
+ boolean isDirty() {
+ return dirty;
+ }
+
+ private void setDirty(boolean dirty) {
+ this.dirty = dirty;
+ }
+
+ void readPermissionData(DataInputStream in) throws IOException {
+ int version = in.readInt();
+ int dataSize = in.readInt();
+ byte[] bytes = new byte[dataSize];
+ in.readFully(bytes);
+ if (PERMDATA_VERSION == version) {
+ DataInputStream temp = new DataInputStream(new ByteArrayInputStream(bytes));
+ try {
+ // read the default permissions first
+ int numPerms = temp.readInt();
+ if (numPerms > 0) {
+ String[] perms = new String[numPerms];
+ for (int i = 0; i < numPerms; i++)
+ perms[i] = temp.readUTF();
+ setPermissionData(null, perms);
+ }
+ int numLocs = temp.readInt();
+ if (numLocs > 0) {
+ for (int i = 0; i < numLocs; i++) {
+ String loc = temp.readUTF();
+ numPerms = temp.readInt();
+ String[] perms = new String[numPerms];
+ for (int j = 0; j < numPerms; j++)
+ perms[j] = temp.readUTF();
+ setPermissionData(loc, perms);
+ }
+ }
+ int numCondPerms = temp.readInt();
+ if (numCondPerms > 0) {
+ String[] condPerms = new String[numCondPerms];
+ for (int i = 0; i < numCondPerms; i++) {
+ condPerms[i] = temp.readUTF();
+ }
+ saveConditionalPermissionInfos(condPerms);
+ }
+
+ } finally {
+ setDirty(false);
+ temp.close();
+ }
+ }
+ }
+
+ void savePermissionData(DataOutputStream out) throws IOException {
+ out.writeInt(PERMDATA_VERSION);
+ // create a temporary in memory stream so we can figure out the length
+ ByteArrayOutputStream tempBytes = new ByteArrayOutputStream();
+ DataOutputStream temp = new DataOutputStream(tempBytes);
+ // always write the default permissions first
+ String[] defaultPerms = getPermissionData(null);
+ temp.writeInt(defaultPerms == null ? 0 : defaultPerms.length);
+ if (defaultPerms != null)
+ for (int i = 0; i < defaultPerms.length; i++)
+ temp.writeUTF(defaultPerms[i]);
+ String[] locs = getLocations();
+ temp.writeInt(locs == null ? 0 : locs.length);
+ if (locs != null)
+ for (int i = 0; i < locs.length; i++) {
+ temp.writeUTF(locs[i]);
+ String[] perms = getPermissionData(locs[i]);
+ temp.writeInt(perms == null ? 0 : perms.length);
+ if (perms != null)
+ for (int j = 0; j < perms.length; j++)
+ temp.writeUTF(perms[j]);
+ }
+ String[] condPerms = getConditionalPermissionInfos();
+ temp.writeInt(condPerms == null ? 0 : condPerms.length);
+ if (condPerms != null)
+ for (int i = 0; i < condPerms.length; i++)
+ temp.writeUTF(condPerms[i]);
+ temp.close();
+
+ out.writeInt(tempBytes.size());
+ out.write(tempBytes.toByteArray());
+ setDirty(false);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
new file mode 100644
index 000000000..a1e901de3
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
@@ -0,0 +1,1540 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.storage;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.container.ModuleRevisionBuilder.GenericInfo;
+import org.eclipse.osgi.container.builders.OSGiManifestBuilderFactory;
+import org.eclipse.osgi.container.namespaces.EclipsePlatformNamespace;
+import org.eclipse.osgi.container.namespaces.EquinoxNativeCodeNamespace;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.framework.util.*;
+import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
+import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
+import org.eclipse.osgi.internal.container.LockSet;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.*;
+import org.eclipse.osgi.internal.hookregistry.*;
+import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
+import org.eclipse.osgi.internal.log.EquinoxLogServices;
+import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.*;
+import org.eclipse.osgi.storage.url.reference.ReferenceInputStream;
+import org.eclipse.osgi.util.ManifestElement;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.*;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.wiring.BundleWiring;
+
+public class Storage {
+ public static final int VERSION = 1;
+ public static final String BUNDLE_DATA_DIR = "data"; //$NON-NLS-1$
+ public static final String BUNDLE_FILE_NAME = "bundleFile"; //$NON-NLS-1$
+ public static final String FRAMEWORK_INFO = "framework.info"; //$NON-NLS-1$
+ public static final String ECLIPSE_SYSTEMBUNDLE = "Eclipse-SystemBundle"; //$NON-NLS-1$
+ public static final String DELETE_FLAG = ".delete"; //$NON-NLS-1$
+ public static final String LIB_TEMP = "libtemp"; //$NON-NLS-1$
+
+ private static final String J2SE = "J2SE-"; //$NON-NLS-1$
+ private static final String JAVASE = "JavaSE-"; //$NON-NLS-1$
+ private static final String PROFILE_EXT = ".profile"; //$NON-NLS-1$
+ private static final String NUL = new String(new byte[] {0});
+
+ static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
+
+ private final EquinoxContainer equinoxContainer;
+ private final String installPath;
+ private final Location osgiLocation;
+ private final File childRoot;
+ private final File parentRoot;
+ private final PermissionData permissionData;
+ private final SecurityAdmin securityAdmin;
+ private final ModuleContainerAdaptor adaptor;
+ private final ModuleDatabase moduleDatabase;
+ private final ModuleContainer moduleContainer;
+ private final Object saveMonitor = new Object();
+ private long lastSavedTimestamp = -1;
+ private final LockSet<Long> idLocks = new LockSet<Long>();
+ private final MRUBundleFileList mruList;
+ private final FrameworkExtensionInstaller extensionInstaller;
+ private final List<String> cachedHeaderKeys = Arrays.asList(Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_ACTIVATIONPOLICY, "Service-Component"); //$NON-NLS-1$
+
+ public Storage(EquinoxContainer container) throws IOException, BundleException {
+ mruList = new MRUBundleFileList(getBundleFileLimit(container.getConfiguration()));
+ equinoxContainer = container;
+ extensionInstaller = new FrameworkExtensionInstaller(container.getConfiguration());
+
+ // we need to set the install path as soon as possible so we can determine
+ // the absolute location of install relative URLs
+ Location installLoc = container.getLocations().getInstallLocation();
+ URL installURL = installLoc.getURL();
+ // assume install URL is file: based
+ installPath = installURL.getPath();
+
+ Location configLocation = container.getLocations().getConfigurationLocation();
+ Location parentConfigLocation = configLocation.getParentLocation();
+ Location osgiParentLocation = null;
+ if (parentConfigLocation != null) {
+ osgiParentLocation = parentConfigLocation.createLocation(null, parentConfigLocation.getDataArea(EquinoxContainer.NAME), true);
+ }
+ this.osgiLocation = configLocation.createLocation(osgiParentLocation, configLocation.getDataArea(EquinoxContainer.NAME), configLocation.isReadOnly());
+ this.childRoot = new File(osgiLocation.getURL().getFile());
+
+ if (Boolean.valueOf(container.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_CLEAN)).booleanValue()) {
+ cleanOSGiStorage(osgiLocation, childRoot);
+ }
+ if (!this.osgiLocation.isReadOnly()) {
+ this.childRoot.mkdirs();
+ }
+ Location parent = this.osgiLocation.getParentLocation();
+ parentRoot = parent == null ? null : new File(osgiLocation.getURL().getFile(), EquinoxContainer.NAME);
+
+ File frameworkInfo = getFile(FRAMEWORK_INFO, true);
+ DataInputStream in = null;
+ if (frameworkInfo.exists()) {
+ try {
+ in = new DataInputStream(new BufferedInputStream(new FileInputStream(frameworkInfo)));
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ try {
+ Map<Long, Generation> generations = loadGenerations(in);
+ this.permissionData = loadPermissionData(in);
+ this.securityAdmin = new SecurityAdmin(null, this.permissionData);
+ this.adaptor = new EquinoxContainerAdaptor(equinoxContainer, this, generations);
+ this.moduleDatabase = new ModuleDatabase(adaptor);
+ this.moduleContainer = new ModuleContainer(this.adaptor, this.moduleDatabase);
+ if (in != null) {
+ moduleDatabase.load(in);
+ lastSavedTimestamp = moduleDatabase.getTimestamp();
+ }
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // just move on
+ }
+ }
+ }
+ checkSystemBundle();
+ installExtensions();
+ // TODO hack to make sure all bundles are in UNINSTALLED state before system bundle init is called
+ this.moduleContainer.setInitialModuleStates();
+ }
+
+ private int getBundleFileLimit(EquinoxConfiguration configuration) {
+ int propValue = 100; // enable to 100 open files by default
+ try {
+ String prop = configuration.getConfiguration(EquinoxConfiguration.PROP_FILE_LIMIT);
+ if (prop != null)
+ propValue = Integer.parseInt(prop);
+ } catch (NumberFormatException e) {
+ // use default of 100
+ }
+ return propValue;
+ }
+
+ private void installExtensions() {
+ Module systemModule = moduleContainer.getModule(0);
+ ModuleRevision systemRevision = systemModule == null ? null : systemModule.getCurrentRevision();
+ ModuleWiring systemWiring = systemRevision == null ? null : systemRevision.getWiring();
+ if (systemWiring == null) {
+ return;
+ }
+ for (ModuleWire hostWire : systemWiring.getProvidedModuleWires(HostNamespace.HOST_NAMESPACE)) {
+ try {
+ getExtensionInstaller().addExtensionContent(hostWire.getRequirer());
+ } catch (BundleException e) {
+ getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, e.getMessage(), e);
+ }
+ }
+ }
+
+ private static PermissionData loadPermissionData(DataInputStream in) throws IOException {
+ PermissionData permData = new PermissionData();
+ if (in != null) {
+ permData.readPermissionData(in);
+ }
+ return permData;
+ }
+
+ private void checkSystemBundle() {
+ Module systemModule = moduleContainer.getModule(0);
+ Generation newGeneration = null;
+ try {
+ if (systemModule == null) {
+ BundleInfo info = new BundleInfo(this, 0, 0);
+ newGeneration = info.createGeneration();
+
+ File contentFile = getSystemContent();
+ newGeneration.setContent(contentFile);
+
+ ModuleRevisionBuilder builder = getBuilder(newGeneration);
+ systemModule = moduleContainer.install(null, Constants.SYSTEM_BUNDLE_LOCATION, builder, newGeneration);
+ moduleContainer.resolve(Arrays.asList(systemModule), false);
+ } else {
+ ModuleRevision currentRevision = systemModule.getCurrentRevision();
+ Generation currentGeneration = currentRevision == null ? null : (Generation) currentRevision.getRevisionInfo();
+ if (currentGeneration == null) {
+ throw new IllegalStateException("No current revision for system bundle."); //$NON-NLS-1$
+ }
+ try {
+ ModuleRevisionBuilder newBuilder = getBuilder(currentGeneration);
+ if (needUpdate(currentRevision, newBuilder)) {
+ newGeneration = currentGeneration.getBundleInfo().createGeneration();
+ File contentFile = getSystemContent();
+ newGeneration.setContent(contentFile);
+ moduleContainer.update(systemModule, newBuilder, newGeneration);
+ moduleContainer.refresh(Arrays.asList(systemModule));
+ }
+ } catch (BundleException e) {
+ throw new IllegalStateException("Could not create a builder for the system bundle.", e); //$NON-NLS-1$
+ }
+ }
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new RuntimeException("Error occurred while checking the system module.", e); //$NON-NLS-1$
+ } finally {
+ if (newGeneration != null) {
+ newGeneration.getBundleInfo().unlockGeneration(newGeneration);
+ }
+ }
+ }
+
+ public void close() {
+ try {
+ save();
+ } catch (IOException e) {
+ getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error saving on shutdown", e);
+ }
+
+ // close all the generations
+ List<Module> modules = moduleContainer.getModules();
+ for (Module module : modules) {
+ for (ModuleRevision revision : module.getRevisions().getModuleRevisions()) {
+ Generation generation = (Generation) revision.getRevisionInfo();
+ if (generation != null) {
+ generation.close();
+ }
+ }
+ }
+ mruList.shutdown();
+ }
+
+ private boolean needUpdate(ModuleRevision currentRevision, ModuleRevisionBuilder newBuilder) {
+ if (!currentRevision.getVersion().equals(newBuilder.getVersion())) {
+ return true;
+ }
+ // only do this advanced check if in dev mode
+ if (!equinoxContainer.getConfiguration().inDevelopmentMode()) {
+ return false;
+ }
+ List<ModuleCapability> currentCapabilities = currentRevision.getModuleCapabilities(null);
+ List<GenericInfo> newCapabilities = newBuilder.getCapabilities();
+ if (currentCapabilities.size() != newCapabilities.size()) {
+ return true;
+ }
+
+ int size = currentCapabilities.size();
+ for (int i = 0; i < size; i++) {
+ if (!equivilant(currentCapabilities.get(i), newCapabilities.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean equivilant(ModuleCapability moduleCapability, GenericInfo genericInfo) {
+ if (!moduleCapability.getNamespace().equals(genericInfo.getNamespace())) {
+ return false;
+ }
+ if (!moduleCapability.getAttributes().equals(genericInfo.getAttributes())) {
+ return false;
+ }
+ if (!moduleCapability.getDirectives().equals(genericInfo.getDirectives())) {
+ return false;
+ }
+ return true;
+ }
+
+ private void cleanOSGiStorage(Location location, File root) {
+ if (location.isReadOnly() || !AdaptorUtil.rm(root)) {
+ equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "The -clean (osgi.clean) option was not successful. Unable to clean the storage area: " + root.getAbsolutePath(), null); //$NON-NLS-1$
+ }
+ }
+
+ public ModuleDatabase getModuleDatabase() {
+ return moduleDatabase;
+ }
+
+ public ModuleContainerAdaptor getAdaptor() {
+ return adaptor;
+ }
+
+ public ModuleContainer getModuleContainer() {
+ return moduleContainer;
+ }
+
+ public EquinoxConfiguration getConfiguration() {
+ return equinoxContainer.getConfiguration();
+ }
+
+ public EquinoxLogServices getLogServices() {
+ return equinoxContainer.getLogServices();
+ }
+
+ public FrameworkExtensionInstaller getExtensionInstaller() {
+ return extensionInstaller;
+ }
+
+ public boolean isReadOnly() {
+ return osgiLocation.isReadOnly();
+ }
+
+ public URLConnection getContentConnection(Module module, String bundleLocation, final InputStream in) throws IOException {
+ if (in != null) {
+ return new URLConnection(null) {
+ /**
+ * @throws IOException
+ */
+ public void connect() throws IOException {
+ connected = true;
+ }
+
+ /**
+ * @throws IOException
+ */
+ public InputStream getInputStream() throws IOException {
+ return (in);
+ }
+ };
+ }
+ if (module == null) {
+ if (bundleLocation == null) {
+ throw new IllegalArgumentException("Module and location cannot be null"); //$NON-NLS-1$
+ }
+ return getContentConnection(bundleLocation);
+ }
+ return getContentConnection(getUpdateLocation(module));
+ }
+
+ private String getUpdateLocation(final Module module) {
+ if (System.getSecurityManager() == null)
+ return getUpdateLocation0(module);
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return getUpdateLocation0(module);
+ }
+ });
+ }
+
+ String getUpdateLocation0(Module module) {
+ ModuleRevision current = module.getCurrentRevision();
+ Generation generation = (Generation) current.getRevisionInfo();
+ String updateLocation = generation.getHeaders().get(Constants.BUNDLE_UPDATELOCATION);
+ return updateLocation == null ? module.getLocation() : updateLocation;
+ }
+
+ private URLConnection getContentConnection(final String spec) throws IOException {
+ if (System.getSecurityManager() == null) {
+ return new URL(spec).openConnection();
+ }
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<URLConnection>() {
+ @Override
+ public URLConnection run() throws IOException {
+ return new URL(spec).openConnection();
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof IOException)
+ throw (IOException) e.getException();
+ throw (RuntimeException) e.getException();
+ }
+ }
+
+ public Generation install(Module origin, String bundleLocation, URLConnection content) throws BundleException {
+ if (osgiLocation.isReadOnly()) {
+ throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
+ }
+ URL sourceURL = content.getURL();
+ InputStream in;
+ try {
+ in = content.getInputStream();
+ } catch (IOException e) {
+ throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
+ }
+ boolean isReference = in instanceof ReferenceInputStream;
+ File staged = stageContent(in, sourceURL);
+ Generation generation = null;
+ Long lockedID = getNextRootID();
+ try {
+ BundleInfo info = new BundleInfo(this, lockedID, 0);
+ generation = info.createGeneration();
+
+ File contentFile = getContentFile(staged, isReference, lockedID, generation.getGenerationId());
+ generation.setContent(contentFile);
+ setStorageHooks(generation);
+
+ ModuleRevisionBuilder builder = getBuilder(generation);
+ Module m = moduleContainer.install(origin, bundleLocation, builder, generation);
+ if (!lockedID.equals(m.getId())) {
+ // this revision is already installed. delete the generation
+ generation.delete();
+ return (Generation) m.getCurrentRevision().getRevisionInfo();
+ }
+ return generation;
+ } catch (Throwable t) {
+ if (!isReference) {
+ try {
+ delete(staged);
+ } catch (IOException e) {
+ // tried our best
+ }
+ }
+ if (generation != null) {
+ generation.delete();
+ generation.getBundleInfo().delete();
+ }
+ if (t instanceof SecurityException) {
+ // TODO hack from ModuleContainer
+ // if the cause is a bundle exception then throw that
+ if (t.getCause() instanceof BundleException) {
+ throw (BundleException) t.getCause();
+ }
+ throw (SecurityException) t;
+ }
+ if (t instanceof BundleException) {
+ throw (BundleException) t;
+ }
+ throw new BundleException("Error occurred installing a bundle.", t); //$NON-NLS-1$
+ } finally {
+ if (generation != null) {
+ generation.getBundleInfo().unlockGeneration(generation);
+ }
+ idLocks.unlock(lockedID);
+ }
+ }
+
+ private void setStorageHooks(Generation generation) throws BundleException {
+ if (generation.getBundleInfo().getBundleId() == 0) {
+ return; // ignore system bundle
+ }
+ List<StorageHookFactory<?, ?, ?>> factories = new ArrayList<StorageHookFactory<?, ?, ?>>(getConfiguration().getHookRegistry().getStorageHookFactories());
+ List<StorageHook<?, ?>> hooks = new ArrayList<StorageHook<?, ?>>(factories.size());
+ for (Iterator<StorageHookFactory<?, ?, ?>> iFactories = factories.iterator(); iFactories.hasNext();) {
+ @SuppressWarnings("unchecked")
+ StorageHookFactory<Object, Object, StorageHook<Object, Object>> next = (StorageHookFactory<Object, Object, StorageHook<Object, Object>>) iFactories.next();
+ StorageHook<Object, Object> hook = next.createStorageHook(generation);
+ hooks.add(hook);
+ }
+ generation.setStorageHooks(Collections.unmodifiableList(hooks), true);
+ for (StorageHook<?, ?> hook : hooks) {
+ hook.initialize(generation.getHeaders());
+ }
+ }
+
+ public ModuleRevisionBuilder getBuilder(Generation generation) throws BundleException {
+ Dictionary<String, String> headers = generation.getHeaders();
+ Map<String, String> mapHeaders;
+ if (headers instanceof Map) {
+ @SuppressWarnings("unchecked")
+ Map<String, String> unchecked = (Map<String, String>) headers;
+ mapHeaders = unchecked;
+ } else {
+ mapHeaders = new HashMap<String, String>();
+ for (Enumeration<String> eKeys = headers.keys(); eKeys.hasMoreElements();) {
+ String key = eKeys.nextElement();
+ mapHeaders.put(key, headers.get(key));
+ }
+ }
+ if (generation.getBundleInfo().getBundleId() != 0) {
+ return OSGiManifestBuilderFactory.createBuilder(mapHeaders);
+ }
+ // First we must make sure the VM profile has been loaded
+ loadVMProfile(generation);
+ // dealing with system bundle find the extra capabilities and exports
+ String extraCapabilities = getSystemExtraCapabilities();
+ String extraExports = getSystemExtraPackages();
+ return OSGiManifestBuilderFactory.createBuilder(mapHeaders, Constants.SYSTEM_BUNDLE_SYMBOLICNAME, extraExports, extraCapabilities);
+ }
+
+ private String getSystemExtraCapabilities() {
+ EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration();
+ StringBuilder result = new StringBuilder();
+
+ String systemCapabilities = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
+ if (systemCapabilities != null) {
+ result.append(systemCapabilities).append(", "); //$NON-NLS-1$
+ }
+
+ String extraSystemCapabilities = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);
+ if (extraSystemCapabilities != null) {
+ result.append(extraSystemCapabilities).append(", "); //$NON-NLS-1$
+ }
+
+ result.append(EclipsePlatformNamespace.ECLIPSE_PLATFORM_NAMESPACE).append("; "); //$NON-NLS-1$
+ result.append(EquinoxConfiguration.PROP_OSGI_OS).append("=").append(equinoxConfig.getOS()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
+ result.append(EquinoxConfiguration.PROP_OSGI_WS).append("=").append(equinoxConfig.getWS()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
+ result.append(EquinoxConfiguration.PROP_OSGI_ARCH).append("=").append(equinoxConfig.getOSArch()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
+ result.append(EquinoxConfiguration.PROP_OSGI_NL).append("=").append(equinoxConfig.getNL()); //$NON-NLS-1$
+
+ String osName = equinoxConfig.getConfiguration(Constants.FRAMEWORK_OS_NAME);
+ osName = osName == null ? null : osName.toLowerCase();
+ String processor = equinoxConfig.getConfiguration(Constants.FRAMEWORK_PROCESSOR);
+ processor = processor == null ? null : processor.toLowerCase();
+ String osVersion = equinoxConfig.getConfiguration(Constants.FRAMEWORK_OS_VERSION);
+ osVersion = osVersion == null ? null : osVersion.toLowerCase();
+ String language = equinoxConfig.getConfiguration(Constants.FRAMEWORK_LANGUAGE);
+ language = language == null ? null : language.toLowerCase();
+
+ result.append(", "); //$NON-NLS-1$
+ result.append(EquinoxNativeCodeNamespace.EQUINOX_NATIVECODE_NAMESPACE).append("; "); //$NON-NLS-1$
+ result.append(EquinoxNativeCodeNamespace.CAPABILITY_OS_NAME_ATTRIBUTE).append("=").append(osName).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
+ result.append(EquinoxNativeCodeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE).append("=").append(processor).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
+ result.append(EquinoxNativeCodeNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE + ":Version").append("=").append(osVersion).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ result.append(EquinoxNativeCodeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE).append("=").append(language); //$NON-NLS-1$
+ // TODO need a way to configure in arbitrary native code matching attributes
+
+ return result.toString();
+ }
+
+ private String getSystemExtraPackages() {
+ EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration();
+ StringBuilder result = new StringBuilder();
+
+ String systemPackages = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES);
+ if (systemPackages != null) {
+ result.append(systemPackages);
+ }
+
+ String extraSystemPackages = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+ if (extraSystemPackages != null) {
+ if (result.length() > 0) {
+ result.append(", "); //$NON-NLS-1$
+ }
+ result.append(extraSystemPackages);
+ }
+
+ return result.toString();
+ }
+
+ public Generation update(Module module, URLConnection content) throws BundleException {
+ if (osgiLocation.isReadOnly()) {
+ throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
+ }
+ URL sourceURL = content.getURL();
+ InputStream in;
+ try {
+ in = content.getInputStream();
+ } catch (IOException e) {
+ throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
+ }
+ boolean isReference = in instanceof ReferenceInputStream;
+ File staged = stageContent(in, sourceURL);
+
+ ModuleRevision current = module.getCurrentRevision();
+ Generation currentGen = (Generation) current.getRevisionInfo();
+
+ BundleInfo bundleInfo = currentGen.getBundleInfo();
+ Generation newGen = bundleInfo.createGeneration();
+
+ try {
+ File contentFile = getContentFile(staged, isReference, bundleInfo.getBundleId(), newGen.getGenerationId());
+ newGen.setContent(contentFile);
+ setStorageHooks(newGen);
+
+ ModuleRevisionBuilder builder = getBuilder(newGen);
+ moduleContainer.update(module, builder, newGen);
+ } catch (Throwable t) {
+ if (!isReference) {
+ try {
+ delete(staged);
+ } catch (IOException e) {
+ // tried our best
+ }
+ }
+ newGen.delete();
+ if (t instanceof SecurityException) {
+ // TODO hack from ModuleContainer
+ // if the cause is a bundle exception then throw that
+ if (t.getCause() instanceof BundleException) {
+ throw (BundleException) t.getCause();
+ }
+ throw (SecurityException) t;
+ }
+ if (t instanceof BundleException) {
+ throw (BundleException) t;
+ }
+ throw new BundleException("Error occurred installing a bundle.", t); //$NON-NLS-1$
+ } finally {
+ bundleInfo.unlockGeneration(newGen);
+ }
+ return newGen;
+ }
+
+ private File getContentFile(final File staged, final boolean isReference, final long bundleID, final long generationID) throws BundleException {
+ if (System.getSecurityManager() == null)
+ return getContentFile0(staged, isReference, bundleID, generationID);
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
+ public File run() throws BundleException {
+ return getContentFile0(staged, isReference, bundleID, generationID);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof BundleException)
+ throw (BundleException) e.getException();
+ throw (RuntimeException) e.getException();
+ }
+ }
+
+ File getContentFile0(File staged, boolean isReference, long bundleID, long generationID) throws BundleException {
+ File contentFile;
+ if (!isReference) {
+ File generationRoot = new File(childRoot, bundleID + "/" + generationID); //$NON-NLS-1$
+ if (!generationRoot.mkdirs()) {
+ throw new BundleException("Could not create generation directory: " + generationRoot.getAbsolutePath()); //$NON-NLS-1$
+ }
+ contentFile = new File(generationRoot, BUNDLE_FILE_NAME);
+ if (!staged.renameTo(contentFile)) {
+ throw new BundleException("Error while renaming bundle file to final location: " + contentFile); //$NON-NLS-1$
+ }
+ } else {
+ contentFile = staged;
+ }
+ return contentFile;
+ }
+
+ public File getFile(String path, boolean checkParent) {
+ // first check the child location
+ File childPath = new File(childRoot, path);
+ // now check the parent
+ if (checkParent && parentRoot != null) {
+ if (childPath.exists()) {
+ return childPath;
+ }
+ File parentPath = new File(parentRoot, path);
+ if (parentPath.exists()) {
+ // only use the parent file only if it exists;
+ return parentPath;
+ }
+ }
+ // did not exist in both locations; use the child path
+ return childPath;
+ }
+
+ private File stageContent(final InputStream in, final URL sourceURL) throws BundleException {
+ if (System.getSecurityManager() == null)
+ return stageContent0(in, sourceURL);
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
+ public File run() throws BundleException {
+ return stageContent0(in, sourceURL);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof BundleException)
+ throw (BundleException) e.getException();
+ throw (RuntimeException) e.getException();
+ }
+ }
+
+ File stageContent0(InputStream in, URL sourceURL) throws BundleException {
+ File outFile = null;
+ try {
+ if (in instanceof ReferenceInputStream) {
+ URL reference = ((ReferenceInputStream) in).getReference();
+ if (!"file".equals(reference.getProtocol())) //$NON-NLS-1$
+ throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, reference));
+ return new File(reference.getPath());
+ }
+
+ outFile = File.createTempFile(BUNDLE_FILE_NAME, ".tmp", childRoot); //$NON-NLS-1$
+ String protocol = sourceURL == null ? null : sourceURL.getProtocol();
+
+ if ("file".equals(protocol)) { //$NON-NLS-1$
+ File inFile = new File(sourceURL.getPath());
+ if (inFile.isDirectory()) {
+ // need to delete the outFile because it is not a directory
+ outFile.delete();
+ AdaptorUtil.copyDir(inFile, outFile);
+ } else {
+ AdaptorUtil.readFile(in, outFile);
+ }
+ } else {
+ AdaptorUtil.readFile(in, outFile);
+ }
+ return outFile;
+ } catch (IOException e) {
+ if (outFile != null) {
+ outFile.delete();
+ }
+ throw new BundleException(AdaptorMsg.BUNDLE_READ_EXCEPTION, BundleException.READ_ERROR, e);
+ }
+ }
+
+ private Long getNextRootID() throws BundleException {
+ moduleDatabase.lockRead();
+ try {
+ Long nextID = moduleDatabase.getNextId();
+ boolean lockedID;
+ try {
+ lockedID = idLocks.tryLock(nextID, 5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR, e); //$NON-NLS-1$
+ }
+ if (!lockedID) {
+ throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR); //$NON-NLS-1$
+ }
+ return nextID;
+ } finally {
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ /**
+ * Attempts to set the permissions of the file in a system dependent way.
+ * @param file the file to set the permissions on
+ */
+ public void setPermissions(File file) {
+ String commandProp = getConfiguration().getConfiguration(EquinoxConfiguration.PROP_SETPERMS_CMD);
+ if (commandProp == null)
+ commandProp = getConfiguration().getConfiguration(Constants.FRAMEWORK_EXECPERMISSION);
+ if (commandProp == null)
+ return;
+ String[] temp = ManifestElement.getArrayFromList(commandProp, " "); //$NON-NLS-1$
+ List<String> command = new ArrayList<String>(temp.length + 1);
+ boolean foundFullPath = false;
+ for (int i = 0; i < temp.length; i++) {
+ if ("[fullpath]".equals(temp[i]) || "${abspath}".equals(temp[i])) { //$NON-NLS-1$ //$NON-NLS-2$
+ command.add(file.getAbsolutePath());
+ foundFullPath = true;
+ } else
+ command.add(temp[i]);
+ }
+ if (!foundFullPath)
+ command.add(file.getAbsolutePath());
+ try {
+ Runtime.getRuntime().exec(command.toArray(new String[command.size()])).waitFor();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public BundleFile createBundleFile(File content, Generation generation, boolean isDirectory, boolean isBase) {
+ BundleFile result;
+ try {
+ if (isDirectory) {
+ result = new DirBundleFile(content);
+ } else {
+ result = new ZipBundleFile(content, generation, mruList, getConfiguration().getDebug());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Could not create bundle file.", e); //$NON-NLS-1$
+ }
+ return wrapBundleFile(result, generation, isBase);
+ }
+
+ public BundleFile createNestedBundleFile(String nestedDir, BundleFile bundleFile, Generation generation) {
+ // here we assume the content is a path offset into the base bundle file; create a NestedDirBundleFile
+ return wrapBundleFile(new NestedDirBundleFile(bundleFile, nestedDir), generation, false);
+ }
+
+ public BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean isBase) {
+ // try creating a wrapper bundlefile out of it.
+ List<BundleFileWrapperFactoryHook> wrapperFactories = getConfiguration().getHookRegistry().getBundleFileWrapperFactoryHooks();
+ BundleFileWrapperChain wrapped = wrapperFactories.isEmpty() ? null : new BundleFileWrapperChain(bundleFile, null);
+ for (BundleFileWrapperFactoryHook wrapperFactory : wrapperFactories) {
+ BundleFile wrapperBundle = wrapperFactory.wrapBundleFile(bundleFile, generation, isBase);
+ if (wrapperBundle != null && wrapperBundle != bundleFile)
+ bundleFile = wrapped = new BundleFileWrapperChain(wrapperBundle, wrapped);
+ }
+
+ return bundleFile;
+ }
+
+ public void compact() {
+ if (!osgiLocation.isReadOnly()) {
+ compact(childRoot);
+ }
+ }
+
+ private void compact(File directory) {
+ if (getConfiguration().getDebug().DEBUG_GENERAL)
+ Debug.println("compact(" + directory.getPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ String list[] = directory.list();
+ if (list == null)
+ return;
+
+ int len = list.length;
+ for (int i = 0; i < len; i++) {
+ if (BUNDLE_DATA_DIR.equals(list[i]))
+ continue; /* do not examine the bundles data dir. */
+ File target = new File(directory, list[i]);
+ // if the file is a directory
+ if (!target.isDirectory())
+ continue;
+ File delete = new File(target, DELETE_FLAG);
+ // and the directory is marked for delete
+ if (delete.exists()) {
+ // if rm fails to delete the directory and .delete was removed
+ if (!AdaptorUtil.rm(target) && !delete.exists()) {
+ try {
+ // recreate .delete
+ FileOutputStream out = new FileOutputStream(delete);
+ out.close();
+ } catch (IOException e) {
+ if (getConfiguration().getDebug().DEBUG_GENERAL)
+ Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ } else {
+ compact(target); /* descend into directory */
+ }
+ }
+ }
+
+ void delete(final File delete) throws IOException {
+ if (System.getSecurityManager() == null) {
+ delete0(delete);
+ } else {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ public Object run() throws IOException {
+ delete0(delete);
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof IOException)
+ throw (IOException) e.getException();
+ throw (RuntimeException) e.getException();
+ }
+ }
+ }
+
+ void delete0(File delete) throws IOException {
+ if (!AdaptorUtil.rm(delete)) {
+ /* create .delete */
+ FileOutputStream out = new FileOutputStream(new File(delete, DELETE_FLAG));
+ out.close();
+ }
+ }
+
+ public void save() throws IOException {
+ if (isReadOnly()) {
+ return;
+ }
+ if (System.getSecurityManager() == null) {
+ save0();
+ } else {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ public Object run() throws IOException {
+ save0();
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof IOException)
+ throw (IOException) e.getException();
+ throw (RuntimeException) e.getException();
+ }
+ }
+ }
+
+ void save0() throws IOException {
+ DataOutputStream out = null;
+ boolean lockedLocation = false;
+ moduleDatabase.lockRead();
+ try {
+ lockedLocation = osgiLocation.lock();
+ synchronized (this.saveMonitor) {
+ if (lastSavedTimestamp == moduleDatabase.getTimestamp())
+ return;
+ out = new DataOutputStream(new FileOutputStream(getFile(FRAMEWORK_INFO, false)));
+ saveGenerations(out);
+ savePermissionData(out);
+ moduleDatabase.store(out, true);
+ lastSavedTimestamp = moduleDatabase.getTimestamp();
+ }
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // tried our best
+ }
+ }
+ if (lockedLocation) {
+ osgiLocation.release();
+ }
+ moduleDatabase.unlockRead();
+ }
+ }
+
+ private void savePermissionData(DataOutputStream out) throws IOException {
+ permissionData.savePermissionData(out);
+ }
+
+ private void saveGenerations(DataOutputStream out) throws IOException {
+ List<Module> modules = moduleContainer.getModules();
+ List<Generation> generations = new ArrayList<Generation>();
+ for (Module module : modules) {
+ ModuleRevision revision = module.getCurrentRevision();
+ if (revision != null) {
+ Generation generation = (Generation) revision.getRevisionInfo();
+ if (generation != null) {
+ generations.add(generation);
+ }
+ }
+ }
+ out.writeInt(VERSION);
+
+ out.writeInt(cachedHeaderKeys.size());
+ for (String headerKey : cachedHeaderKeys) {
+ out.writeUTF(headerKey);
+ }
+
+ out.writeInt(generations.size());
+ for (Generation generation : generations) {
+ BundleInfo bundleInfo = generation.getBundleInfo();
+ out.writeLong(bundleInfo.getBundleId());
+ out.writeLong(bundleInfo.getNextGenerationId());
+ out.writeLong(generation.getGenerationId());
+ out.writeBoolean(generation.isDirectory());
+ out.writeBoolean(generation.hasPackageInfo());
+ if (bundleInfo.getBundleId() == 0) {
+ // just write empty string for system bundle content in this case
+ out.writeUTF(""); //$NON-NLS-1$
+ } else {
+ out.writeUTF(new FilePath(installPath).makeRelative(new FilePath(generation.getContent().getAbsolutePath())));
+ }
+
+ Dictionary<String, String> headers = generation.getHeaders();
+ for (String headerKey : cachedHeaderKeys) {
+ String value = headers.get(headerKey);
+ if (value != null) {
+ out.writeUTF(value);
+ } else {
+ out.writeUTF(NUL);
+ }
+ }
+ }
+
+ saveStorageHookData(out, generations);
+ }
+
+ private void saveStorageHookData(DataOutputStream out, List<Generation> generations) throws IOException {
+ List<StorageHookFactory<?, ?, ?>> factories = getConfiguration().getHookRegistry().getStorageHookFactories();
+ out.writeInt(factories.size());
+ for (StorageHookFactory<?, ?, ?> factory : factories) {
+ out.writeUTF(factory.getKey());
+ out.writeInt(factory.getStorageVersion());
+
+ // create a temporary in memory stream so we can figure out the length
+ ByteArrayOutputStream tempBytes = new ByteArrayOutputStream();
+ DataOutputStream temp = new DataOutputStream(tempBytes);
+ try {
+ Object saveContext = factory.createSaveContext();
+ for (Generation generation : generations) {
+ if (generation.getBundleInfo().getBundleId() == 0) {
+ continue; // ignore system bundle
+ }
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ StorageHook<Object, Object> hook = generation.getStorageHook((Class) factory.getClass());
+ hook.save(saveContext, temp);
+ }
+ } finally {
+ temp.close();
+ }
+ out.writeInt(tempBytes.size());
+ out.write(tempBytes.toByteArray());
+ }
+ }
+
+ private Map<Long, Generation> loadGenerations(DataInputStream in) throws IOException {
+ if (in == null) {
+ return new HashMap<Long, Generation>(0);
+ }
+ int version = in.readInt();
+ if (version < VERSION)
+ throw new IOException("Perstence version is not correct for loading: " + version + " expecting: " + VERSION); //$NON-NLS-1$ //$NON-NLS-2$
+
+ int numCachedHeaders = in.readInt();
+ List<String> storedCachedHeaderKeys = new ArrayList<String>(numCachedHeaders);
+ for (int i = 0; i < numCachedHeaders; i++) {
+ storedCachedHeaderKeys.add((String) ObjectPool.intern(in.readUTF()));
+ }
+
+ int numInfos = in.readInt();
+ Map<Long, Generation> result = new HashMap<Long, Generation>(numInfos);
+ List<Generation> generations = new ArrayList<BundleInfo.Generation>(numInfos);
+ for (int i = 0; i < numInfos; i++) {
+ long infoId = in.readLong();
+ long nextGenId = in.readLong();
+ long generationId = in.readLong();
+ boolean isDirectory = in.readBoolean();
+ boolean hasPackageInfo = in.readBoolean();
+ String contentPath = in.readUTF();
+
+ Map<String, String> cachedHeaders = new HashMap<String, String>(storedCachedHeaderKeys.size());
+ for (String headerKey : storedCachedHeaderKeys) {
+ String value = in.readUTF();
+ if (NUL.equals(value)) {
+ value = null;
+ } else {
+ value = (String) ObjectPool.intern(value);
+ }
+ cachedHeaders.put(headerKey, value);
+ }
+
+ File content;
+ if (infoId == 0) {
+ content = getSystemContent();
+ isDirectory = content != null ? content.isDirectory() : false;
+ } else {
+ content = new File(contentPath);
+ }
+
+ if (content != null && !content.isAbsolute()) {
+ // make sure it has the absolute location instead
+ content = new File(installPath, contentPath);
+ }
+
+ BundleInfo info = new BundleInfo(this, infoId, nextGenId);
+ Generation generation = info.restoreGeneration(generationId, content, isDirectory, hasPackageInfo, cachedHeaders);
+ result.put(infoId, generation);
+ generations.add(generation);
+ }
+
+ loadStorageHookData(generations, in);
+ return result;
+ }
+
+ private void loadStorageHookData(List<Generation> generations, DataInputStream in) throws IOException {
+ List<StorageHookFactory<?, ?, ?>> factories = new ArrayList<StorageHookFactory<?, ?, ?>>(getConfiguration().getHookRegistry().getStorageHookFactories());
+ Map<Generation, List<StorageHook<?, ?>>> hookMap = new HashMap<Generation, List<StorageHook<?, ?>>>();
+ int numFactories = in.readInt();
+ for (int i = 0; i < numFactories; i++) {
+ String factoryName = in.readUTF();
+ int version = in.readInt();
+ StorageHookFactory<Object, Object, StorageHook<Object, Object>> factory = null;
+ for (Iterator<StorageHookFactory<?, ?, ?>> iFactories = factories.iterator(); iFactories.hasNext();) {
+ @SuppressWarnings("unchecked")
+ StorageHookFactory<Object, Object, StorageHook<Object, Object>> next = (StorageHookFactory<Object, Object, StorageHook<Object, Object>>) iFactories.next();
+ if (next.getKey().equals(factoryName)) {
+ factory = next;
+ iFactories.remove();
+ break;
+ }
+ }
+ int dataSize = in.readInt();
+ byte[] bytes = new byte[dataSize];
+ in.readFully(bytes);
+ if (factory != null) {
+ DataInputStream temp = new DataInputStream(new ByteArrayInputStream(bytes));
+ try {
+ if (factory.isCompatibleWith(version)) {
+ Object loadContext = factory.createLoadContext(version);
+ for (Generation generation : generations) {
+ if (generation.getBundleInfo().getBundleId() == 0) {
+ continue; // ignore system bundle
+ }
+ StorageHook<Object, Object> hook = factory.createStorageHook(generation);
+ hook.load(loadContext, temp);
+ getHooks(hookMap, generation).add(hook);
+ }
+ } else {
+ // recover by reinitializing the hook
+ for (Generation generation : generations) {
+ if (generation.getBundleInfo().getBundleId() == 0) {
+ continue; // ignore system bundle
+ }
+ StorageHook<Object, Object> hook = factory.createStorageHook(generation);
+ hook.initialize(generation.getHeaders());
+ getHooks(hookMap, generation).add(hook);
+ }
+ }
+ } catch (BundleException e) {
+ throw new IOException(e);
+ } finally {
+ temp.close();
+ }
+ }
+ }
+ // now we need to recover for any hooks that are left
+ for (Iterator<StorageHookFactory<?, ?, ?>> iFactories = factories.iterator(); iFactories.hasNext();) {
+ @SuppressWarnings("unchecked")
+ StorageHookFactory<Object, Object, StorageHook<Object, Object>> next = (StorageHookFactory<Object, Object, StorageHook<Object, Object>>) iFactories.next();
+ // recover by reinitializing the hook
+ for (Generation generation : generations) {
+ if (generation.getBundleInfo().getBundleId() == 0) {
+ continue; // ignore system bundle
+ }
+ StorageHook<Object, Object> hook = next.createStorageHook(generation);
+ try {
+ hook.initialize(generation.getHeaders());
+ getHooks(hookMap, generation).add(hook);
+ } catch (BundleException e) {
+ throw new IOException(e);
+ }
+ }
+ }
+ // now set the hooks to the generations
+ for (Generation generation : generations) {
+ generation.setStorageHooks(Collections.unmodifiableList(getHooks(hookMap, generation)), false);
+ }
+ }
+
+ private static List<StorageHook<?, ?>> getHooks(Map<Generation, List<StorageHook<?, ?>>> hookMap, Generation generation) {
+ List<StorageHook<?, ?>> result = hookMap.get(generation);
+ if (result == null) {
+ result = new ArrayList<StorageHook<?, ?>>();
+ hookMap.put(generation, result);
+ }
+ return result;
+ }
+
+ private File getSystemContent() {
+ String frameworkValue = equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_FRAMEWORK);
+ if (frameworkValue == null || !frameworkValue.startsWith("file:")) { //$NON-NLS-1$
+ return null;
+ }
+ // TODO assumes the location is a file URL
+ File result = new File(frameworkValue.substring(5));
+ if (!result.exists()) {
+ throw new IllegalStateException("Configured framework location does not exist: " + result.getAbsolutePath()); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ private void loadVMProfile(Generation systemGeneration) {
+ EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration();
+ Properties profileProps = findVMProfile(systemGeneration);
+ String systemExports = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES);
+ // set the system exports property using the vm profile; only if the property is not already set
+ if (systemExports == null) {
+ systemExports = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
+ if (systemExports != null)
+ equinoxConfig.setConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES, systemExports);
+ }
+
+ // set the org.osgi.framework.bootdelegation property according to the java profile
+ String type = equinoxConfig.getConfiguration(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_BOOTDELEGATION); // a null value means ignore
+ String profileBootDelegation = profileProps.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
+ if (EquinoxConfiguration.PROP_OSGI_BOOTDELEGATION_OVERRIDE.equals(type)) {
+ if (profileBootDelegation == null)
+ equinoxConfig.clearConfiguration(Constants.FRAMEWORK_BOOTDELEGATION); // override with a null value
+ else
+ equinoxConfig.setConfiguration(Constants.FRAMEWORK_BOOTDELEGATION, profileBootDelegation); // override with the profile value
+ } else if (EquinoxConfiguration.PROP_OSGI_BOOTDELEGATION_NONE.equals(type))
+ equinoxConfig.clearConfiguration(Constants.FRAMEWORK_BOOTDELEGATION); // remove the bootdelegation property in case it was set
+ // set the org.osgi.framework.executionenvironment property according to the java profile
+ if (equinoxConfig.getConfiguration(Constants.FRAMEWORK_EXECUTIONENVIRONMENT) == null) {
+ // get the ee from the java profile; if no ee is defined then try the java profile name
+ String ee = profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, profileProps.getProperty(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME));
+ if (ee != null)
+ equinoxConfig.setConfiguration(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee);
+ }
+ // set the org.osgi.framework.system.capabilities property according to the java profile
+ if (equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES) == null) {
+ String systemCapabilities = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
+ if (systemCapabilities != null)
+ equinoxConfig.setConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES, systemCapabilities);
+ }
+ }
+
+ private Properties findVMProfile(Generation systemGeneration) {
+ Properties result = new Properties();
+ // Find the VM profile name using J2ME properties
+ String j2meConfig = System.getProperty(EquinoxConfiguration.PROP_J2ME_MICROEDITION_CONFIGURATION);
+ String j2meProfiles = System.getProperty(EquinoxConfiguration.PROP_J2ME_MICROEDITION_PROFILES);
+ String vmProfile = null;
+ String javaEdition = null;
+ Version javaVersion = null;
+ if (j2meConfig != null && j2meConfig.length() > 0 && j2meProfiles != null && j2meProfiles.length() > 0) {
+ // save the vmProfile based off of the config and profile
+ // use the last profile; assuming that is the highest one
+ String[] j2meProfileList = ManifestElement.getArrayFromList(j2meProfiles, " "); //$NON-NLS-1$
+ if (j2meProfileList != null && j2meProfileList.length > 0)
+ vmProfile = j2meConfig + '_' + j2meProfileList[j2meProfileList.length - 1];
+ } else {
+ // No J2ME properties; use J2SE properties
+ // Note that the CDC spec appears not to require VM implementations to set the
+ // javax.microedition properties!! So we will try to fall back to the
+ // java.specification.name property, but this is pretty ridiculous!!
+ String javaSpecVersion = System.getProperty(EquinoxConfiguration.PROP_JVM_SPEC_VERSION);
+ // set the profile and EE based off of the java.specification.version
+ // TODO We assume J2ME Foundation and J2SE here. need to support other profiles J2EE ...
+ if (javaSpecVersion != null) {
+ StringTokenizer st = new StringTokenizer(javaSpecVersion, " _-"); //$NON-NLS-1$
+ javaSpecVersion = st.nextToken();
+ String javaSpecName = System.getProperty(EquinoxConfiguration.PROP_JVM_SPEC_NAME);
+ // See bug 291269 we check for Foundation Specification and Foundation Profile Specification
+ if (javaSpecName != null && (javaSpecName.indexOf("Foundation Specification") >= 0 || javaSpecName.indexOf("Foundation Profile Specification") >= 0)) //$NON-NLS-1$ //$NON-NLS-2$
+ vmProfile = "CDC-" + javaSpecVersion + "_Foundation-" + javaSpecVersion; //$NON-NLS-1$ //$NON-NLS-2$
+ else {
+ // look for JavaSE if 1.6 or greater; otherwise look for J2SE
+ Version v16 = new Version("1.6"); //$NON-NLS-1$
+ javaEdition = J2SE;
+ try {
+ javaVersion = new Version(javaSpecVersion);
+ if (v16.compareTo(javaVersion) <= 0)
+ javaEdition = JAVASE;
+ } catch (IllegalArgumentException e) {
+ // do nothing
+ }
+ vmProfile = javaEdition + javaSpecVersion;
+ }
+ }
+ }
+ InputStream profileIn = null;
+ // check for the java profile property for a url
+ String propJavaProfile = equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE);
+ if (propJavaProfile != null)
+ try {
+ // we assume a URL
+ profileIn = new URL(propJavaProfile).openStream();
+ } catch (IOException e) {
+ // try using a relative path in the system bundle
+ profileIn = findInSystemBundle(systemGeneration, propJavaProfile);
+ }
+ if (profileIn == null && vmProfile != null) {
+ // look for a profile in the system bundle based on the vm profile
+ String javaProfile = vmProfile + PROFILE_EXT;
+ profileIn = findInSystemBundle(systemGeneration, javaProfile);
+ if (profileIn == null)
+ profileIn = getNextBestProfile(systemGeneration, javaEdition, javaVersion);
+ }
+ if (profileIn == null)
+ // the profile url is still null then use the osgi min profile in OSGi by default
+ profileIn = findInSystemBundle(systemGeneration, "JavaSE-1.6.profile"); //$NON-NLS-1$
+ if (profileIn != null) {
+ try {
+ result.load(new BufferedInputStream(profileIn));
+ } catch (IOException e) {
+ // TODO consider logging ...
+ } finally {
+ try {
+ profileIn.close();
+ } catch (IOException ee) {
+ // do nothing
+ }
+ }
+ }
+ // set the profile name if it does not provide one
+ if (result.getProperty(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME) == null)
+ if (vmProfile != null)
+ result.put(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME, vmProfile.replace('_', '/'));
+ else
+ // last resort; default to the absolute minimum profile name for the framework
+ result.put(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME, "JavaSE-1.6"); //$NON-NLS-1$
+ return result;
+ }
+
+ private InputStream getNextBestProfile(Generation systemGeneration, String javaEdition, Version javaVersion) {
+ if (javaVersion == null || (javaEdition != J2SE && javaEdition != JAVASE))
+ return null; // we cannot automatically choose the next best profile unless this is a J2SE or JavaSE vm
+ InputStream bestProfile = findNextBestProfile(systemGeneration, javaEdition, javaVersion);
+ if (bestProfile == null && javaEdition == JAVASE)
+ // if this is a JavaSE VM then search for a lower J2SE profile
+ bestProfile = findNextBestProfile(systemGeneration, J2SE, javaVersion);
+ return bestProfile;
+ }
+
+ private InputStream findNextBestProfile(Generation systemGeneration, String javaEdition, Version javaVersion) {
+ InputStream result = null;
+ int minor = javaVersion.getMinor();
+ do {
+ result = findInSystemBundle(systemGeneration, javaEdition + javaVersion.getMajor() + "." + minor + PROFILE_EXT); //$NON-NLS-1$
+ minor = minor - 1;
+ } while (result == null && minor > 0);
+ return result;
+ }
+
+ private InputStream findInSystemBundle(Generation systemGeneration, String entry) {
+ BundleFile systemContent = systemGeneration.getBundleFile();
+ BundleEntry systemEntry = systemContent != null ? systemContent.getEntry(entry) : null;
+ InputStream result = null;
+ if (systemEntry != null) {
+ try {
+ result = systemEntry.getInputStream();
+ } catch (IOException e) {
+ // Do nothing
+ }
+ }
+ if (result == null) {
+ // Check the ClassLoader in case we're launched off the Java boot classpath
+ ClassLoader loader = getClass().getClassLoader();
+ result = loader == null ? ClassLoader.getSystemResourceAsStream(entry) : loader.getResourceAsStream(entry);
+ }
+ return result;
+ }
+
+ public static Enumeration<URL> findEntries(List<Generation> generations, String path, String filePattern, int options) {
+ List<BundleFile> bundleFiles = new ArrayList<BundleFile>(generations.size());
+ for (Generation generation : generations)
+ bundleFiles.add(generation.getBundleFile());
+ // search all the bundle files
+ List<String> pathList = listEntryPaths(bundleFiles, path, filePattern, options);
+ // return null if no entries found
+ if (pathList.size() == 0)
+ return null;
+ // create an enumeration to enumerate the pathList
+ final String[] pathArray = pathList.toArray(new String[pathList.size()]);
+ final Generation[] generationArray = generations.toArray(new Generation[generations.size()]);
+ return new Enumeration<URL>() {
+ private int curPathIndex = 0;
+ private int curDataIndex = 0;
+ private URL nextElement = null;
+
+ public boolean hasMoreElements() {
+ if (nextElement != null)
+ return true;
+ getNextElement();
+ return nextElement != null;
+ }
+
+ public URL nextElement() {
+ if (!hasMoreElements())
+ throw new NoSuchElementException();
+ URL result = nextElement;
+ // force the next element search
+ getNextElement();
+ return result;
+ }
+
+ private void getNextElement() {
+ nextElement = null;
+ if (curPathIndex >= pathArray.length)
+ // reached the end of the pathArray; no more elements
+ return;
+ while (nextElement == null && curPathIndex < pathArray.length) {
+ String curPath = pathArray[curPathIndex];
+ // search the generation until we have searched them all
+ while (nextElement == null && curDataIndex < generationArray.length)
+ nextElement = generationArray[curDataIndex++].getEntry(curPath);
+ // we have searched all datas then advance to the next path
+ if (curDataIndex >= generationArray.length) {
+ curPathIndex++;
+ curDataIndex = 0;
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * Returns the names of resources available from a list of bundle files.
+ * No duplicate resource names are returned, each name is unique.
+ * @param bundleFiles the list of bundle files to search in
+ * @param path The path name in which to look.
+ * @param filePattern The file name pattern for selecting resource names in
+ * the specified path.
+ * @param options The options for listing resource names.
+ * @return a list of resource names. If no resources are found then
+ * the empty list is returned.
+ * @see BundleWiring#listResources(String, String, int)
+ */
+ public static List<String> listEntryPaths(List<BundleFile> bundleFiles, String path, String filePattern, int options) {
+ // a list used to store the results of the search
+ List<String> pathList = new ArrayList<String>();
+ Filter patternFilter = null;
+ Hashtable<String, String> patternProps = null;
+ if (filePattern != null) {
+ // Optimization: If the file pattern does not include a wildcard or escape char then it must represent a single file.
+ // Avoid pattern matching and use BundleFile.getEntry() if recursion was not requested.
+ if ((options & BundleWiring.FINDENTRIES_RECURSE) == 0 && filePattern.indexOf('*') == -1 && filePattern.indexOf('\\') == -1) {
+ if (path.length() == 0)
+ path = filePattern;
+ else
+ path += path.charAt(path.length() - 1) == '/' ? filePattern : '/' + filePattern;
+ for (BundleFile bundleFile : bundleFiles) {
+ if (bundleFile.getEntry(path) != null && !pathList.contains(path))
+ pathList.add(path);
+ }
+ return pathList;
+ }
+ // For when the file pattern includes a wildcard.
+ try {
+ // create a file pattern filter with 'filename' as the key
+ patternFilter = FilterImpl.newInstance("(filename=" + sanitizeFilterInput(filePattern) + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ // create a single hashtable to be shared during the recursive search
+ patternProps = new Hashtable<String, String>(2);
+ } catch (InvalidSyntaxException e) {
+ // TODO something unexpected happened; log error and return nothing
+ // Bundle b = context == null ? null : context.getBundle();
+ // eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, b, e);
+ return pathList;
+ }
+ }
+ // find the entry paths for the datas
+ for (BundleFile bundleFile : bundleFiles) {
+ listEntryPaths(bundleFile, path, patternFilter, patternProps, options, pathList);
+ }
+ return pathList;
+ }
+
+ private static String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException {
+ StringBuffer buffer = null;
+ boolean foundEscape = false;
+ for (int i = 0; i < filePattern.length(); i++) {
+ char c = filePattern.charAt(i);
+ switch (c) {
+ case '\\' :
+ // we either used the escape found or found a new escape.
+ foundEscape = foundEscape ? false : true;
+ if (buffer != null)
+ buffer.append(c);
+ break;
+ case '(' :
+ case ')' :
+ if (!foundEscape) {
+ if (buffer == null) {
+ buffer = new StringBuffer(filePattern.length() + 16);
+ buffer.append(filePattern.substring(0, i));
+ }
+ // must escape with '\'
+ buffer.append('\\');
+ } else {
+ foundEscape = false; // used the escape found
+ }
+ if (buffer != null)
+ buffer.append(c);
+ break;
+ default :
+ // if we found an escape it has been used
+ foundEscape = false;
+ if (buffer != null)
+ buffer.append(c);
+ break;
+ }
+ }
+ if (foundEscape)
+ throw new InvalidSyntaxException("Trailing escape characters must be escaped.", filePattern); //$NON-NLS-1$
+ return buffer == null ? filePattern : buffer.toString();
+ }
+
+ private static List<String> listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable<String, String> patternProps, int options, List<String> pathList) {
+ if (pathList == null)
+ pathList = new ArrayList<String>();
+ Enumeration<String> entryPaths = bundleFile.getEntryPaths(path);
+ if (entryPaths == null)
+ return pathList;
+ while (entryPaths.hasMoreElements()) {
+ String entry = entryPaths.nextElement();
+ int lastSlash = entry.lastIndexOf('/');
+ if (patternProps != null) {
+ int secondToLastSlash = entry.lastIndexOf('/', lastSlash - 1);
+ int fileStart;
+ int fileEnd = entry.length();
+ if (lastSlash < 0)
+ fileStart = 0;
+ else if (lastSlash != entry.length() - 1)
+ fileStart = lastSlash + 1;
+ else {
+ fileEnd = lastSlash; // leave the lastSlash out
+ if (secondToLastSlash < 0)
+ fileStart = 0;
+ else
+ fileStart = secondToLastSlash + 1;
+ }
+ String fileName = entry.substring(fileStart, fileEnd);
+ // set the filename to the current entry
+ patternProps.put("filename", fileName); //$NON-NLS-1$
+ }
+ // prevent duplicates and match on the patternFilter
+ if (!pathList.contains(entry) && (patternFilter == null || patternFilter.matchCase(patternProps)))
+ pathList.add(entry);
+ // recurse only into entries that are directories
+ if (((options & BundleWiring.FINDENTRIES_RECURSE) != 0) && !entry.equals(path) && entry.length() > 0 && lastSlash == (entry.length() - 1))
+ listEntryPaths(bundleFile, entry, patternFilter, patternProps, options, pathList);
+ }
+ return pathList;
+ }
+
+ public String copyToTempLibrary(Generation generation, String absolutePath) {
+ File libTempDir = new File(childRoot, LIB_TEMP);
+ // we assume the absolutePath is a File path
+ File realLib = new File(absolutePath);
+ String libName = realLib.getName();
+ // find a temp dir for the bundle data and the library;
+ File bundleTempDir = null;
+ File libTempFile = null;
+ // We need a somewhat predictable temp dir for the libraries of a given bundle;
+ // This is not strictly necessary but it does help scenarios where one native library loads another native library without using java.
+ // On some OSes this causes issues because the second library is cannot be found.
+ // This has been worked around by the bundles loading the libraries in a particular order (and setting some LIB_PATH env).
+ // The one catch is that the libraries need to be in the same directory and they must use their original lib names.
+ //
+ // This bit of code attempts to do that by using the bundle ID as an ID for the temp dir along with an incrementing ID
+ // in cases where the temp dir may already exist.
+ Long bundleID = new Long(generation.getBundleInfo().getBundleId());
+ for (int i = 0; i < Integer.MAX_VALUE; i++) {
+ bundleTempDir = new File(libTempDir, bundleID.toString() + "_" + new Integer(i).toString()); //$NON-NLS-1$
+ libTempFile = new File(bundleTempDir, libName);
+ if (bundleTempDir.exists()) {
+ if (libTempFile.exists())
+ continue; // to to next temp file
+ break;
+ }
+ break;
+ }
+ if (!bundleTempDir.exists()) {
+ bundleTempDir.mkdirs();
+ bundleTempDir.deleteOnExit();
+ // This is just a safeguard incase the VM is terminated unexpectantly, it also looks like deleteOnExit cannot really work because
+ // the VM likely will still have a lock on the lib file at the time of VM exit.
+ File deleteFlag = new File(libTempDir, DELETE_FLAG);
+ if (!deleteFlag.exists()) {
+ // need to create a delete flag to force removal the temp libraries
+ try {
+ FileOutputStream out = new FileOutputStream(deleteFlag);
+ out.close();
+ } catch (IOException e) {
+ // do nothing; that would mean we did not make the temp dir successfully
+ }
+ }
+ }
+ // copy the library file
+ try {
+ InputStream in = new FileInputStream(realLib);
+ AdaptorUtil.readFile(in, libTempFile);
+ // set permissions if needed
+ setPermissions(libTempFile);
+ libTempFile.deleteOnExit(); // this probably will not work because the VM will probably have the lib locked at exit
+ // return the temporary path
+ return libTempFile.getAbsolutePath();
+ } catch (IOException e) {
+ equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, e.getMessage(), e);
+ return null;
+ }
+ }
+
+ public SecurityAdmin getSecurityAdmin() {
+ return securityAdmin;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java
new file mode 100644
index 000000000..c75524400
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.storage;
+
+import java.io.*;
+import java.net.URL;
+import java.util.Enumeration;
+import org.eclipse.osgi.framework.util.Headers;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.osgi.framework.BundleException;
+
+public class SystemBundleFile extends BundleFile {
+
+ public SystemBundleFile() {
+ super(null);
+ }
+
+ @Override
+ public File getFile(String path, boolean nativeCode) {
+ return null;
+ }
+
+ @Override
+ public BundleEntry getEntry(String path) {
+ if (BundleInfo.OSGI_BUNDLE_MANIFEST.equals(path)) {
+ return new BundleEntry() {
+
+ public InputStream getInputStream() throws IOException {
+ return getManifestURL().openStream();
+ }
+
+ public long getSize() {
+ return 0;
+ }
+
+ public String getName() {
+ return BundleInfo.OSGI_BUNDLE_MANIFEST;
+ }
+
+ public long getTime() {
+ return 0;
+ }
+
+ public URL getLocalURL() {
+ return getManifestURL();
+ }
+
+ public URL getFileURL() {
+ return null;
+ }
+ };
+ }
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getEntryPaths(String path) {
+ return null;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing
+ }
+
+ @Override
+ public void open() throws IOException {
+ // nothing
+ }
+
+ @Override
+ public boolean containsDir(String dir) {
+ return false;
+ }
+
+ URL getManifestURL() {
+ ClassLoader cl = getClass().getClassLoader();
+ try {
+ // get all manifests in your classloader delegation
+ Enumeration<URL> manifests = cl != null ? cl.getResources(BundleInfo.OSGI_BUNDLE_MANIFEST) : ClassLoader.getSystemResources(BundleInfo.OSGI_BUNDLE_MANIFEST);
+ while (manifests.hasMoreElements()) {
+ URL url = manifests.nextElement();
+ try {
+ // check each manifest until we find one with the Eclipse-SystemBundle: true header
+ Headers<String, String> headers = Headers.parseManifest(url.openStream());
+ if ("true".equals(headers.get(Storage.ECLIPSE_SYSTEMBUNDLE))) //$NON-NLS-1$
+ return url;
+ } catch (BundleException e) {
+ // ignore and continue to next URL
+ }
+ }
+ } catch (IOException e) {
+ // ignore and return null
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java
index b9d48f3ae..5819728d8 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java
@@ -9,12 +9,11 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
/**
@@ -91,8 +90,8 @@ public abstract class BundleEntry {
public byte[] getBytes() throws IOException {
InputStream in = getInputStream();
int length = (int) getSize();
- if (Debug.DEBUG_LOADER)
- Debug.println(" about to read " + length + " bytes from " + getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ // if (Debug.DEBUG_LOADER)
+ // Debug.println(" about to read " + length + " bytes from " + getName()); //$NON-NLS-1$ //$NON-NLS-2$
return AdaptorUtil.getBytes(in, length, BUF_SIZE);
}
}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java
index 011359dab..320fdc3ba 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java
@@ -9,19 +9,18 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.protocol.bundleresource.Handler;
+import java.util.Enumeration;
+import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.framework.util.SecureAction;
-import org.eclipse.osgi.util.ManifestElement;
+import org.eclipse.osgi.storage.url.BundleResourceHandler;
+import org.eclipse.osgi.storage.url.bundleresource.Handler;
/**
* The BundleFile API is used by Adaptors to read resources out of an
@@ -32,7 +31,6 @@ import org.eclipse.osgi.util.ManifestElement;
* @since 3.2
*/
abstract public class BundleFile {
- protected static final String PROP_SETPERMS_CMD = "osgi.filepermissions.command"; //$NON-NLS-1$
static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
/**
* The File object for this BundleFile.
@@ -41,14 +39,6 @@ abstract public class BundleFile {
private int mruIndex = -1;
/**
- * Default constructor
- *
- */
- public BundleFile() {
- // do nothing
- }
-
- /**
* BundleFile constructor
* @param basefile The File object where this BundleFile is
* persistently stored.
@@ -115,47 +105,19 @@ abstract public class BundleFile {
/**
* Returns a URL to access the contents of the entry specified by the path
* @param path the path to the resource
- * @param hostBundleID the host bundle ID
- * @return a URL to access the contents of the entry specified by the path
- * @deprecated use {@link #getResourceURL(String, BaseData, int)}
- */
- public URL getResourceURL(String path, long hostBundleID) {
- return getResourceURL(path, hostBundleID, 0);
- }
-
- /**
- * Returns a URL to access the contents of the entry specified by the path
- * @param path the path to the resource
- * @param hostBundleID the host bundle ID
+ * @param hostModule the host module
* @param index the resource index
* @return a URL to access the contents of the entry specified by the path
- * @deprecated use {@link #getResourceURL(String, BaseData, int)}
*/
- public URL getResourceURL(String path, long hostBundleID, int index) {
- return internalGetResourceURL(path, null, hostBundleID, index);
- }
-
- /**
- * Returns a URL to access the contents of the entry specified by the path
- * @param path the path to the resource
- * @param hostData the host BaseData
- * @param index the resource index
- * @return a URL to access the contents of the entry specified by the path
- */
- public URL getResourceURL(String path, BaseData hostData, int index) {
- return internalGetResourceURL(path, hostData, 0, index);
- }
-
- private URL internalGetResourceURL(String path, BaseData hostData, long hostBundleID, int index) {
+ public URL getResourceURL(String path, Module hostModule, int index) {
BundleEntry bundleEntry = getEntry(path);
if (bundleEntry == null)
return null;
- if (hostData != null)
- hostBundleID = hostData.getBundleID();
+ long hostBundleID = hostModule.getId();
path = fixTrailingSlash(path, bundleEntry);
try {
//use the constant string for the protocol to prevent duplication
- return secureAction.getURL(Constants.OSGI_RESOURCE_URL_PROTOCOL, Long.toString(hostBundleID) + BundleResourceHandler.BID_FWKID_SEPARATOR + Integer.toString(hostData.getAdaptor().hashCode()), index, path, new Handler(bundleEntry, hostData == null ? null : hostData.getAdaptor()));
+ return secureAction.getURL(BundleResourceHandler.OSGI_RESOURCE_URL_PROTOCOL, Long.toString(hostBundleID) + BundleResourceHandler.BID_FWKID_SEPARATOR + Integer.toString(hostModule.getContainer().hashCode()), index, path, new Handler(hostModule.getContainer(), bundleEntry));
} catch (MalformedURLException e) {
return null;
}
@@ -177,35 +139,6 @@ abstract public class BundleFile {
return mruIndex;
}
- /**
- * Attempts to set the permissions of the file in a system dependent way.
- * @param file the file to set the permissions on
- */
- public static void setPermissions(File file) {
- String commandProp = FrameworkProperties.getProperty(PROP_SETPERMS_CMD);
- if (commandProp == null)
- commandProp = FrameworkProperties.getProperty(Constants.FRAMEWORK_EXECPERMISSION);
- if (commandProp == null)
- return;
- String[] temp = ManifestElement.getArrayFromList(commandProp, " "); //$NON-NLS-1$
- List<String> command = new ArrayList<String>(temp.length + 1);
- boolean foundFullPath = false;
- for (int i = 0; i < temp.length; i++) {
- if ("[fullpath]".equals(temp[i]) || "${abspath}".equals(temp[i])) { //$NON-NLS-1$ //$NON-NLS-2$
- command.add(file.getAbsolutePath());
- foundFullPath = true;
- } else
- command.add(temp[i]);
- }
- if (!foundFullPath)
- command.add(file.getAbsolutePath());
- try {
- Runtime.getRuntime().exec(command.toArray(new String[command.size()])).waitFor();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
public String toString() {
return String.valueOf(basefile);
}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleFileWrapperChain.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java
index 24e4730d5..e77aa015b 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleFileWrapperChain.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java
@@ -9,14 +9,14 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
/**
* Used to chain the BundleFile objects returned from {@link BundleFileWrapperFactoryHook}.
@@ -27,6 +27,7 @@ public class BundleFileWrapperChain extends BundleFile {
private final BundleFileWrapperChain next;
public BundleFileWrapperChain(BundleFile wrapped, BundleFileWrapperChain next) {
+ super(null);
this.wrapped = wrapped;
this.next = next;
}
@@ -59,8 +60,8 @@ public class BundleFileWrapperChain extends BundleFile {
return wrapped.getBaseFile();
}
- public URL getResourceURL(String path, BaseData hostData, int index) {
- return wrapped.getResourceURL(path, hostData, index);
+ public URL getResourceURL(String path, Module hostModule, int index) {
+ return wrapped.getResourceURL(path, hostModule, index);
}
public String toString() {
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/DirBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java
index 64c3f7191..b30cef27e 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/DirBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.File;
import java.io.IOException;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/DirZipBundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java
index 6061ee053..940209ea8 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/DirZipBundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.*;
import java.net.MalformedURLException;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/FileBundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java
index 21a7b6c88..abd4e6ab4 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/FileBundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.*;
import java.net.MalformedURLException;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java
index 8c59890a2..f3488fdcc 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.IOException;
import java.util.Map;
@@ -23,21 +23,9 @@ import org.eclipse.osgi.framework.eventmgr.*;
* @since 3.2
*/
public class MRUBundleFileList implements EventDispatcher<Object, Object, BundleFile> {
- private static final String PROP_FILE_LIMIT = "osgi.bundlefile.limit"; //$NON-NLS-1$
private static final int MIN = 10;
- private static final int PROP_FILE_LIMIT_VALUE;
private static final ThreadLocal<BundleFile> closingBundleFile = new ThreadLocal<BundleFile>();
- static {
- int propValue = 100; // enable to 100 open files by default
- try {
- String prop = BundleFile.secureAction.getProperty(PROP_FILE_LIMIT);
- if (prop != null)
- propValue = Integer.parseInt(prop);
- } catch (NumberFormatException e) {
- //MRU will be disabled
- }
- PROP_FILE_LIMIT_VALUE = propValue;
- }
+
// list of open bundle files
final private BundleFile[] bundleFileList;
// list of open bundle files use stamps
@@ -53,10 +41,6 @@ public class MRUBundleFileList implements EventDispatcher<Object, Object, Bundle
// used to work around bug 275166
private boolean firstDispatch = true;
- public MRUBundleFileList() {
- this(PROP_FILE_LIMIT_VALUE);
- }
-
public MRUBundleFileList(int fileLimit) {
// only enable the MRU if the initFileLimit is > MIN
this.fileLimit = fileLimit;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/NestedDirBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java
index 88514c2b9..bd99f8ff1 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/NestedDirBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.File;
import java.io.IOException;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/ZipBundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java
index 06a46aa9b..c182a31fa 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/ZipBundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
* Rob Harrop - SpringSource Inc. (bug 253942)
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.*;
import java.net.MalformedURLException;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/ZipBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java
index 9ce5c789d..beeadf945 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/ZipBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java
@@ -10,18 +10,19 @@
* Rob Harrop - SpringSource Inc. (bug 253942)
*******************************************************************************/
-package org.eclipse.osgi.baseadaptor.bundlefile;
+package org.eclipse.osgi.storage.bundlefile;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
+import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.storage.BundleInfo;
import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.FrameworkEvent;
/**
* A BundleFile that uses a ZipFile as it base file.
@@ -30,10 +31,10 @@ import org.osgi.framework.FrameworkEvent;
public class ZipBundleFile extends BundleFile {
private final MRUBundleFileList mruList;
- /**
- * The bundle data
- */
- protected BaseData bundledata;
+
+ private final BundleInfo.Generation generation;
+
+ private final Debug debug;
/**
* The zip file
*/
@@ -45,21 +46,12 @@ public class ZipBundleFile extends BundleFile {
private int referenceCount = 0;
- /**
- * Constructs a ZipBundle File
- * @param basefile the base file
- * @param bundledata the bundle data
- * @throws IOException
- */
- public ZipBundleFile(File basefile, BaseData bundledata) throws IOException {
- this(basefile, bundledata, null);
- }
-
- public ZipBundleFile(File basefile, BaseData bundledata, MRUBundleFileList mruList) throws IOException {
+ public ZipBundleFile(File basefile, BundleInfo.Generation generation, MRUBundleFileList mruList, Debug debug) throws IOException {
super(basefile);
if (!BundleFile.secureAction.exists(basefile))
throw new IOException(NLS.bind(AdaptorMsg.ADAPTER_FILEEXIST_EXCEPTION, basefile));
- this.bundledata = bundledata;
+ this.debug = debug;
+ this.generation = generation;
this.closed = true;
this.mruList = mruList;
}
@@ -72,9 +64,13 @@ public class ZipBundleFile extends BundleFile {
try {
return getZipFile() != null;
} catch (IOException e) {
- if (bundledata != null)
- bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), e);
- return false;
+ if (generation != null) {
+ ModuleRevision r = generation.getRevision();
+ if (r != null) {
+ generation.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.ERROR, r.getRevisions().getModule(), e);
+ }
+ }
+ throw new RuntimeException("Failed to open bundle file.", e);
}
}
@@ -144,7 +140,7 @@ public class ZipBundleFile extends BundleFile {
}
protected File getExtractFile(String entryName) {
- if (bundledata == null)
+ if (generation == null)
return null;
String path = ".cp"; /* put all these entries in this subdir *///$NON-NLS-1$
String name = entryName.replace('/', File.separatorChar);
@@ -152,7 +148,7 @@ public class ZipBundleFile extends BundleFile {
path = path.concat(name);
else
path = path + File.separator + name;
- return bundledata.getExtractFile(path);
+ return generation.getExtractFile(path);
}
public synchronized File getFile(String entry, boolean nativeCode) {
@@ -167,7 +163,7 @@ public class ZipBundleFile extends BundleFile {
if (nested != null) {
if (nested.exists()) {
/* the entry is already cached */
- if (Debug.DEBUG_GENERAL)
+ if (debug.DEBUG_GENERAL)
Debug.println("File already present: " + nested.getPath()); //$NON-NLS-1$
if (nested.isDirectory())
// must ensure the complete directory is extracted (bug 182585)
@@ -175,7 +171,7 @@ public class ZipBundleFile extends BundleFile {
} else {
if (zipEntry.getName().endsWith("/")) { //$NON-NLS-1$
if (!nested.mkdirs()) {
- if (Debug.DEBUG_GENERAL)
+ if (debug.DEBUG_GENERAL)
Debug.println("Unable to create directory: " + nested.getPath()); //$NON-NLS-1$
throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, nested.getAbsolutePath()));
}
@@ -185,26 +181,27 @@ public class ZipBundleFile extends BundleFile {
if (in == null)
return null;
/* the entry has not been cached */
- if (Debug.DEBUG_GENERAL)
+ if (debug.DEBUG_GENERAL)
Debug.println("Creating file: " + nested.getPath()); //$NON-NLS-1$
/* create the necessary directories */
File dir = new File(nested.getParent());
if (!dir.exists() && !dir.mkdirs()) {
- if (Debug.DEBUG_GENERAL)
+ if (debug.DEBUG_GENERAL)
Debug.println("Unable to create directory: " + dir.getPath()); //$NON-NLS-1$
throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, dir.getAbsolutePath()));
}
/* copy the entry to the cache */
AdaptorUtil.readFile(in, nested);
- if (nativeCode)
- setPermissions(nested);
+ if (nativeCode) {
+ generation.getBundleInfo().getStorage().setPermissions(nested);
+ }
}
}
return nested;
}
} catch (IOException e) {
- if (Debug.DEBUG_GENERAL)
+ if (debug.DEBUG_GENERAL)
Debug.printStackTrace(e);
}
return null;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/BundleResourceHandler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleResourceHandler.java
index 68d28e9ca..61015d734 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/BundleResourceHandler.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleResourceHandler.java
@@ -9,45 +9,37 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.storage.url;
import java.io.IOException;
import java.net.*;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.protocol.ProtocolActivator;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleContainer;
import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
-import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
/**
* URLStreamHandler the bundleentry and bundleresource protocols.
*/
-public abstract class BundleResourceHandler extends URLStreamHandler implements ProtocolActivator {
+public abstract class BundleResourceHandler extends URLStreamHandler {
+ // Bundle resource URL protocol
+ public static final String OSGI_RESOURCE_URL_PROTOCOL = "bundleresource"; //$NON-NLS-1$
+ // Bundle entry URL protocol
+ public static final String OSGI_ENTRY_URL_PROTOCOL = "bundleentry"; //$NON-NLS-1$
+
public static final String SECURITY_CHECKED = "SECURITY_CHECKED"; //$NON-NLS-1$
public static final String SECURITY_UNCHECKED = "SECURITY_UNCHECKED"; //$NON-NLS-1$
public static final String BID_FWKID_SEPARATOR = ".fwk"; //$NON-NLS-1$
- private BaseAdaptor adaptor;
+ protected final ModuleContainer container;
protected BundleEntry bundleEntry;
- /**
- * Constructor for a bundle protocol resource URLStreamHandler.
- */
- public BundleResourceHandler() {
- this(null, null);
- }
-
- public BundleResourceHandler(BundleEntry bundleEntry, BaseAdaptor adaptor) {
+ public BundleResourceHandler(ModuleContainer container, BundleEntry bundleEntry) {
+ this.container = container;
this.bundleEntry = bundleEntry;
- this.adaptor = adaptor;
- }
-
- public void start(BundleContext context, FrameworkAdaptor baseAdaptor) {
- this.adaptor = (BaseAdaptor) baseAdaptor;
}
/**
@@ -124,12 +116,11 @@ public abstract class BundleResourceHandler extends URLStreamHandler implements
// are allowed access to the resource.
String authorized = SECURITY_UNCHECKED;
long bundleId = getBundleID(host);
- Bundle bundle = adaptor == null ? null : adaptor.getBundle(bundleId);
- if (checkAuthorization(bundle))
+ Module module = getModule(bundleId);
+ if (checkAuthorization(module))
authorized = SECURITY_CHECKED;
// Always force the use of the hash from the adaptor
- if (adaptor != null)
- host = Long.toString(bundleId) + BID_FWKID_SEPARATOR + Integer.toString(adaptor.hashCode());
+ host = Long.toString(bundleId) + BID_FWKID_SEPARATOR + Integer.toString(container.hashCode());
// Setting the authority portion of the URL to SECURITY_ATHORIZED
// ensures that this URL was created by using this parseURL
// method. The openConnection method will only open URLs
@@ -137,6 +128,10 @@ public abstract class BundleResourceHandler extends URLStreamHandler implements
setURL(url, url.getProtocol(), host, resIndex, authorized, null, path, null, url.getRef());
}
+ private Module getModule(long id) {
+ return container.getModule(id);
+ }
+
/**
* Establishes a connection to the resource specified by <code>URL</code>.
* Since different protocols may have unique ways of connecting, it must be
@@ -155,24 +150,23 @@ public abstract class BundleResourceHandler extends URLStreamHandler implements
if (host == null) {
throw new IOException(NLS.bind(AdaptorMsg.URL_NO_BUNDLE_ID, url.toExternalForm()));
}
- AbstractBundle bundle = null;
long bundleID;
try {
bundleID = getBundleID(host);
} catch (NumberFormatException nfe) {
throw (MalformedURLException) new MalformedURLException(NLS.bind(AdaptorMsg.URL_INVALID_BUNDLE_ID, host)).initCause(nfe);
}
- bundle = adaptor == null ? null : (AbstractBundle) adaptor.getBundle(bundleID);
- if (bundle == null)
+ Module module = getModule(bundleID);
+ if (module == null)
throw new IOException(NLS.bind(AdaptorMsg.URL_NO_BUNDLE_FOUND, url.toExternalForm()));
// check to make sure that this URL was created using the
// parseURL method. This ensures the security check was done
// at URL construction.
if (!url.getAuthority().equals(SECURITY_CHECKED)) {
// No admin security check was made better check now.
- checkAuthorization(bundle);
+ checkAuthorization(module);
}
- return (new BundleURLConnection(url, findBundleEntry(url, bundle)));
+ return (new BundleURLConnection(url, findBundleEntry(url, module)));
}
/**
@@ -180,10 +174,11 @@ public abstract class BundleResourceHandler extends URLStreamHandler implements
* differently for Bundle.gerResource() and Bundle.getEntry()
* because getResource uses the bundle classloader and getEntry
* only used the base bundle file.
- * @param url The URL to find the BundleEntry for.
+ * @param url The URL to find the entry for.
+ * @param module the module to find the entry for.
* @return the bundle entry
*/
- abstract protected BundleEntry findBundleEntry(URL url, AbstractBundle bundle) throws IOException;
+ abstract protected BundleEntry findBundleEntry(URL url, Module module) throws IOException;
/**
* Converts a bundle URL to a String.
@@ -234,8 +229,7 @@ public abstract class BundleResourceHandler extends URLStreamHandler implements
if (path != null)
hash += path.hashCode();
- if (adaptor != null)
- hash += adaptor.hashCode();
+ hash += container.hashCode();
return hash;
}
@@ -280,23 +274,17 @@ public abstract class BundleResourceHandler extends URLStreamHandler implements
// URLs depending on how they were constructed.
}
- protected boolean checkAuthorization(Bundle bundle) {
+ protected boolean checkAuthorization(Module module) {
SecurityManager sm = System.getSecurityManager();
if (sm == null)
return true;
+ Bundle bundle = module == null ? null : module.getBundle();
if (bundle == null)
return false;
sm.checkPermission(new AdminPermission(bundle, AdminPermission.RESOURCE));
return true;
}
- protected static BaseClassLoader getBundleClassLoader(AbstractBundle bundle) {
- BundleLoader loader = bundle.getBundleLoader();
- if (loader == null)
- return null;
- return (BaseClassLoader) loader.createClassLoader();
- }
-
private long getBundleID(String host) {
int dotIndex = host.indexOf('.');
return (dotIndex >= 0 && dotIndex < host.length() - 1) ? Long.parseLong(host.substring(0, dotIndex)) : Long.parseLong(host);
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/BundleURLConnection.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleURLConnection.java
index c0163c4cc..003edf978 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/BundleURLConnection.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleURLConnection.java
@@ -9,14 +9,14 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.storage.url;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.util.NLS;
/**
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/URLConverterImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleURLConverter.java
index c197861e9..253095398 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/URLConverterImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/BundleURLConverter.java
@@ -8,12 +8,12 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.storage.url;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
-import org.eclipse.osgi.framework.internal.core.BundleURLConnection;
+import org.eclipse.osgi.internal.location.EclipseAdaptorMsg;
import org.eclipse.osgi.service.urlconversion.URLConverter;
import org.eclipse.osgi.util.NLS;
@@ -23,7 +23,7 @@ import org.eclipse.osgi.util.NLS;
*
* <p>Internal class.</p>
*/
-public class URLConverterImpl implements URLConverter {
+public class BundleURLConverter implements URLConverter {
/* (non-Javadoc)
* @see org.eclipse.osgi.service.urlconversion.URLConverter#toFileURL(java.net.URL)
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleentry/Handler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java
index 5e39fdcf0..e69dec312 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleentry/Handler.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java
@@ -9,16 +9,15 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol.bundleentry;
+package org.eclipse.osgi.storage.url.bundleentry;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.framework.internal.core.AbstractBundle;
-import org.eclipse.osgi.framework.internal.core.BundleResourceHandler;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.storage.BundleInfo;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.url.BundleResourceHandler;
/**
* URLStreamHandler the bundleentry protocol.
@@ -26,24 +25,16 @@ import org.eclipse.osgi.framework.internal.core.BundleResourceHandler;
public class Handler extends BundleResourceHandler {
- /**
- * Constructor for a bundle protocol resource URLStreamHandler.
- */
- public Handler() {
- super();
+ public Handler(ModuleContainer container, BundleEntry bundleEntry) {
+ super(container, bundleEntry);
}
- public Handler(BundleEntry bundleEntry, BaseAdaptor adaptor) {
- super(bundleEntry, adaptor);
- }
-
- protected BundleEntry findBundleEntry(URL url, AbstractBundle bundle) throws IOException {
- BaseData bundleData = (BaseData) bundle.getBundleData();
- BundleEntry entry = bundleData.getBundleFile().getEntry(url.getPath());
+ protected BundleEntry findBundleEntry(URL url, Module module) throws IOException {
+ ModuleRevision revision = module.getCurrentRevision();
+ BundleInfo.Generation revisionInfo = (BundleInfo.Generation) revision.getRevisionInfo();
+ BundleEntry entry = revisionInfo == null ? null : revisionInfo.getBundleFile().getEntry(url.getPath());
if (entry == null)
throw new FileNotFoundException(url.getPath());
return entry;
-
}
-
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleresource/Handler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleresource/Handler.java
new file mode 100644
index 000000000..a4dfeefde
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleresource/Handler.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.storage.url.bundleresource;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.url.BundleResourceHandler;
+
+/**
+ * URLStreamHandler the bundleresource protocol.
+ */
+
+public class Handler extends BundleResourceHandler {
+
+ public Handler(ModuleContainer container, BundleEntry bundleEntry) {
+ super(container, bundleEntry);
+ }
+
+ protected BundleEntry findBundleEntry(URL url, Module module) throws IOException {
+ ModuleRevision current = module.getCurrentRevision();
+ ModuleWiring wiring = current == null ? null : current.getWiring();
+ ModuleClassLoader classloader = (ModuleClassLoader) (current == null ? null : wiring.getClassLoader());
+ if (classloader == null)
+ throw new FileNotFoundException(url.getPath());
+ BundleEntry entry = classloader.getClasspathManager().findLocalEntry(url.getPath(), url.getPort());
+ if (entry == null) {
+ // this isn't strictly needed but is kept to maintain compatibility
+ entry = classloader.getClasspathManager().findLocalEntry(url.getPath());
+ }
+ if (entry == null) {
+ throw new FileNotFoundException(url.getPath());
+ }
+ return entry;
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/reference/Handler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/Handler.java
index d26175e55..19d6ad890 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/reference/Handler.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/Handler.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol.reference;
+package org.eclipse.osgi.storage.url.reference;
import java.io.IOException;
import java.net.*;
@@ -28,11 +28,23 @@ import java.net.*;
*/
public class Handler extends URLStreamHandler {
+ private final String installPath;
+
+ public Handler(String installURL) {
+ super();
+ if (installURL != null && installURL.startsWith("file:")) { //$NON-NLS-1$
+ // this is the safest way to create a File object off a file: URL
+ this.installPath = installURL.substring(5);
+ } else {
+ this.installPath = null;
+ }
+ }
+
/**
* @throws IOException
*/
protected URLConnection openConnection(URL url) throws IOException {
- return new ReferenceURLConnection(url);
+ return new ReferenceURLConnection(url, installPath);
}
protected void parseURL(URL url, String str, int start, int end) {
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ReferenceInputStream.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java
index 9a1064856..1c2848606 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ReferenceInputStream.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.storage.url.reference;
import java.io.IOException;
import java.io.InputStream;
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/reference/ReferenceURLConnection.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java
index f58a4b302..a5fdd2168 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/reference/ReferenceURLConnection.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java
@@ -9,24 +9,25 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.protocol.reference;
+package org.eclipse.osgi.storage.url.reference;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
-import org.eclipse.osgi.framework.adaptor.FilePath;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.internal.core.ReferenceInputStream;
+import org.eclipse.osgi.framework.util.FilePath;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
/**
* URLConnection for the reference protocol.
*/
public class ReferenceURLConnection extends URLConnection {
- protected URL reference;
+ private final String installPath;
+ private URL reference;
- protected ReferenceURLConnection(URL url) {
+ protected ReferenceURLConnection(URL url, String installPath) {
super(url);
+ this.installPath = installPath;
}
@SuppressWarnings("deprecation")
@@ -40,7 +41,6 @@ public class ReferenceURLConnection extends URLConnection {
URL ref;
if (!file.isAbsolute()) {
- String installPath = getInstallPath();
if (installPath != null)
file = makeAbsolute(installPath, file);
}
@@ -48,7 +48,7 @@ public class ReferenceURLConnection extends URLConnection {
// Pre-check if file exists, if not, and it contains escape characters,
// try decoding the absolute path generated by makeAbsolute
if (!file.exists() && path.indexOf('%') >= 0) {
- String decodePath = FrameworkProperties.decode(file.getAbsolutePath());
+ String decodePath = EquinoxConfiguration.decode(file.getAbsolutePath());
File f = new File(decodePath);
if (f.exists())
file = f;
@@ -103,16 +103,6 @@ public class ReferenceURLConnection extends URLConnection {
return new ReferenceInputStream(reference);
}
- private String getInstallPath() {
- String installURL = FrameworkProperties.getProperty("osgi.install.area"); //$NON-NLS-1$
- if (installURL == null)
- return null;
- if (!installURL.startsWith("file:")) //$NON-NLS-1$
- return null;
- // this is the safest way to create a File object off a file: URL
- return installURL.substring(5);
- }
-
private static File makeAbsolute(String base, File relative) {
if (relative.isAbsolute())
return relative;
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/TextProcessor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/util/TextProcessor.java
index 6f2b039ae..6f2b039ae 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/TextProcessor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/util/TextProcessor.java
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/package.html b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/util/package.html
index 08e65eda1..08e65eda1 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/package.html
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/util/package.html
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleClassLoader.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleClassLoader.java
deleted file mode 100644
index 258b0638f..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleClassLoader.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.*;
-import org.osgi.framework.BundleReference;
-import org.osgi.framework.wiring.BundleWiring;
-
-/**
- * The BundleClassLoader interface is used by the Framework to load local
- * classes and resources from a Bundle. Classes that implement this
- * interface must extend java.lang.ClassLoader, either directly or by extending
- * a subclass of java.lang.ClassLoader.<p>
- *
- * ClassLoaders that implement the <code>BundleClassLoader</code> interface
- * must use a <code>ClassLoaderDelegate</code> to delegate all class, resource
- * and native library lookups.
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- * @see org.eclipse.osgi.framework.adaptor.BundleData#createClassLoader(ClassLoaderDelegate, BundleProtectionDomain, String[])
- */
-public interface BundleClassLoader /*extends ClassLoader*/extends BundleReference {
-
- /**
- * Initializes the ClassLoader. This is called after all currently resolved fragment
- * bundles have been attached to the BundleClassLoader by the Framework.
- */
- public void initialize();
-
- /**
- * Finds a local resource in the BundleClassLoader without
- * consulting the delegate.
- * @param resource the resource path to find.
- * @return a URL to the resource or null if the resource does not exist.
- */
- public URL findLocalResource(String resource);
-
- /**
- * Finds all local resources in the BundleClassLoader with the specified
- * path without consulting the delegate.
- * @param resource the resource path to find.
- * @return An Enumeration of all resources found or null if the resource.
- * does not exist.
- */
- public Enumeration<URL> findLocalResources(String resource);
-
- /**
- * Finds a local class in the BundleClassLoader without
- * consulting the delegate.
- * @param classname the classname to find.
- * @return The class object found.
- * @throws ClassNotFoundException if the classname does not exist locally.
- */
- public Class<?> findLocalClass(String classname) throws ClassNotFoundException;
-
- /**
- * This method will first search the parent class loader for the resource;
- * That failing, this method will invoke
- * {@link ClassLoaderDelegate#findResource(String)} to find the resource.
- * @param name the resource path to get.
- * @return a URL for the resource or <code>null</code> if the resource is not found.
- */
- public URL getResource(String name);
-
- /**
- * This method will first search the parent class loader for the resource;
- * That failing, this method will invoke
- * {@link ClassLoaderDelegate#findResource(String)} to find the resource.
- * @param name the resource path to get.
- * @return an Enumeration of URL objects for the resource or <code>null</code> if the resource is not found.
- */
- public Enumeration<URL> getResources(String name) throws IOException;
-
- /**
- * This method will first search the parent class loader for the class;
- * That failing, this method will invoke
- * {@link ClassLoaderDelegate#findClass(String)} to find the resource.
- * @param name the class name to load.
- * @return the Class.
- * @throws ClassNotFoundException
- */
- public Class<?> loadClass(String name) throws ClassNotFoundException;
-
- /**
- * Closes this class loader. After this method is called
- * loadClass will always throw ClassNotFoundException,
- * getResource, getResourceAsStream, getResources and will
- * return null.
- *
- */
- public void close();
-
- /**
- * Attaches the BundleData for a fragment to this BundleClassLoader.
- * The Fragment BundleData resources must be appended to the end of
- * this BundleClassLoader's classpath. Fragment BundleData resources
- * must be searched ordered by Bundle ID's.
- * @param bundledata The BundleData of the fragment.
- * @param domain The ProtectionDomain of the resources of the fragment.
- * Any classes loaded from the fragment's BundleData must belong to this
- * ProtectionDomain.
- * @param classpath An array of Bundle-ClassPath entries to
- * use for loading classes and resources. This is specified by the
- * Bundle-ClassPath manifest entry of the fragment.
- */
- public void attachFragment(BundleData bundledata, ProtectionDomain domain, String[] classpath);
-
- /**
- * Returns the ClassLoaderDelegate used by this BundleClassLoader
- * @return the ClassLoaderDelegate used by this BundleClassLoader
- */
- public ClassLoaderDelegate getDelegate();
-
- /**
- * Returns the parent classloader used by this BundleClassLoader
- * @return the parent classloader used by this BundleClassLoader
- */
- public ClassLoader getParent();
-
- /**
- * Returns resource entries for the bundle associated with this class loader.
- * This is used to answer a call to the
- * {@link BundleWiring#findEntries(String, String, int)} method.
- * @param path The path name in which to look.
- * @param filePattern The file name pattern for selecting resource names in
- * the specified path.
- * @param options The options for listing resource names.
- * @return a list of resource URLs. If no resources are found then
- * the empty list is returned.
- * @see {@link BundleWiring#findEntries(String, String, int)}
- */
- List<URL> findEntries(String path, String filePattern, int options);
-
- /**
- * Returns the names of resources visible to this bundle class loader.
- * This is used to answer a call to the
- * {@link BundleWiring#listResources(String, String, int)} method.
- * This method should simply return the result of calling
- * {@link ClassLoaderDelegate#listResources(String, String, int)}
- * @param path The path name in which to look.
- * @param filePattern The file name pattern for selecting resource names in
- * the specified path.
- * @param options The options for listing resource names.
- * @return a collection of resource names. If no resources are found then
- * the empty collection is returned.
- * @see {@link BundleWiring#listResources(String, String, int)}
- * @see {@link ClassLoaderDelegate#listResources(String, String, int)}
- */
- Collection<String> listResources(String path, String filePattern, int options);
-
- /**
- * Returns the names of local resources visible to this bundle class loader.
- * Only the resources available on the local class path of this bundle
- * class loader are searched.
- * @param path The path name in which to look.
- * @param filePattern The file name pattern for selecting resource names in
- * the specified path.
- * @param options The options for listing resource names.
- * @return a collection of resource names. If no resources are found then
- * the empty collection is returned.
- * @see {@link ClassLoaderDelegate#listResources(String, String, int)}
- */
- Collection<String> listLocalResources(String path, String filePattern, int options);
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleData.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleData.java
deleted file mode 100644
index 71efc1192..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleData.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import org.osgi.framework.*;
-
-/**
- * The <code>BundleData</code> represents a single bundle that is persistently
- * stored by a <code>FrameworkAdaptor</code>. A <code>BundleData</code> creates
- * the ClassLoader for a bundle, finds native libraries installed in the
- * FrameworkAdaptor for the bundle, creates data files for the bundle,
- * used to access bundle entries, manifest information, and getting and saving
- * metadata.
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- */
-public interface BundleData extends BundleReference {
-
- /** The BundleData is for a fragment bundle */
- public static final int TYPE_FRAGMENT = 0x00000001;
- /** The BundleData is for a framework extension bundle */
- public static final int TYPE_FRAMEWORK_EXTENSION = 0x00000002;
- /** The BundleData is for a bootclasspath extension bundle */
- public static final int TYPE_BOOTCLASSPATH_EXTENSION = 0x00000004;
- /** The BundleData is for a singleton bundle */
- public static final int TYPE_SINGLETON = 0x00000008;
- /** The BundleData is for an extension classpath bundle */
- public static final int TYPE_EXTCLASSPATH_EXTENSION = 0x00000010;
- /** The BundleData is for a composite bundle */
- public static final int TYPE_COMPOSITEBUNDLE = 0x00000020;
- /** The BundleData is for a composite bundle surrogate */
- public static final int TYPE_SURROGATEBUNDLE = 0x00000040;
-
- /**
- * Creates the ClassLoader for the BundleData. The ClassLoader created
- * must use the <code>ClassLoaderDelegate</code> to delegate class, resource
- * and library loading. The delegate is responsible for finding any resource
- * or classes imported by the bundle through an imported package or a required
- * bundle. <p>
- * The <code>ProtectionDomain</code> domain must be used by the Classloader when
- * defining a class.
- * @param delegate The <code>ClassLoaderDelegate</code> to delegate to.
- * @param domain The <code>BundleProtectionDomain</code> to use when defining a class.
- * @param bundleclasspath An array of bundle classpaths to use to create this
- * classloader. This is specified by the Bundle-ClassPath manifest entry.
- * @return The new ClassLoader for the BundleData.
- */
- public BundleClassLoader createClassLoader(ClassLoaderDelegate delegate, BundleProtectionDomain domain, String[] bundleclasspath);
-
- /**
- * Gets a <code>URL</code> to the bundle entry specified by path.
- * This method must not use the BundleClassLoader to find the
- * bundle entry since the ClassLoader will delegate to find the resource.
- * @see org.osgi.framework.Bundle#getEntry(String)
- * @param path The bundle entry path.
- * @return A URL used to access the entry or null if the entry
- * does not exist.
- */
- public URL getEntry(String path);
-
- /**
- * Gets all of the bundle entries that exist under the specified path.
- * For example: <p>
- * <code>getEntryPaths("/META-INF")</code> <p>
- * This will return all entries from the /META-INF directory of the bundle.
- * @see org.osgi.framework.Bundle#getEntryPaths(String path)
- * @param path The path to a directory in the bundle.
- * @return An Enumeration of the entry paths or null if the specified path
- * does not exist.
- */
- public Enumeration<String> getEntryPaths(String path);
-
- /**
- * Returns the absolute path name of a native library. The BundleData
- * ClassLoader invokes this method to locate the native libraries that
- * belong to classes loaded from this BundleData. Returns
- * null if the library does not exist in this BundleData.
- * @param libname The name of the library to find the absolute path to.
- * @return The absolute path name of the native library or null if
- * the library does not exist.
- */
- public String findLibrary(String libname);
-
- /**
- * Installs the native code paths for this BundleData. Each
- * element of nativepaths must be installed for lookup when findLibrary
- * is called.
- * @param nativepaths The array of native code paths to install for
- * the bundle.
- * @throws BundleException If any error occurs during install.
- */
- public void installNativeCode(String[] nativepaths) throws BundleException;
-
- /**
- * Return the bundle data directory.
- * Attempt to create the directory if it does not exist.
- *
- * @see org.osgi.framework.BundleContext#getDataFile(String)
- * @return Bundle data directory or null if not supported.
- */
-
- public File getDataFile(String path);
-
- /**
- * Return the Dictionary of manifest headers for the BundleData.
- * @return Dictionary that contains the Manifest headers for the BundleData.
- * @throws BundleException if an error occurred while reading the
- * bundle manifest data.
- */
- public Dictionary<String, String> getManifest() throws BundleException;
-
- /**
- * Get the BundleData bundle ID. This will be used as the bundle
- * ID by the framework.
- * @return The BundleData ID.
- */
- public long getBundleID();
-
- /**
- * Get the BundleData Location. This will be used as the bundle
- * location by the framework.
- * @return the BundleData location.
- */
- public String getLocation();
-
- /**
- * Get the last time this BundleData was modified.
- * @return the last time this BundleData was modified
- */
- public long getLastModified();
-
- /**
- * Close all resources for this BundleData
- * @throws IOException If an error occurs closing.
- */
- public void close() throws IOException;
-
- /**
- * Open the BundleData. This method will reopen the BundleData if it has been
- * previously closed.
- * @throws IOException If an error occurs opening.
- */
- public void open() throws IOException;
-
- /**
- * Sets the Bundle object for this BundleData.
- * @param bundle The Bundle Object for this BundleData.
- */
- public void setBundle(Bundle bundle);
-
- /**
- * Returns the start level metadata for this BundleData.
- * @return the start level metadata for this BundleData.
- */
- public int getStartLevel();
-
- /**
- * Returns the status metadata for this BundleData. A value of 1
- * indicates that this bundle is started persistently. A value of 0
- * indicates that this bundle is not started persistently.
- * @return the status metadata for this BundleData.
- */
- public int getStatus();
-
- /**
- * Sets the start level metatdata for this BundleData. Metadata must be
- * stored persistently when BundleData.save() is called.
- * @param value the start level metadata
- */
- public void setStartLevel(int value);
-
- /**
- * Sets the status metadata for this BundleData. Metadata must be
- * stored persistently when BundleData.save() is called.
- * @param value the status metadata.
- */
- public void setStatus(int value);
-
- /**
- * Persistently stores all the metadata for this BundleData
- * @throws IOException
- */
- public void save() throws IOException;
-
- /**
- * Returns the Bundle-SymbolicName for this BundleData as specified in the bundle
- * manifest file.
- * @return the Bundle-SymbolicName for this BundleData.
- */
- public String getSymbolicName();
-
- /**
- * Returns the Bundle-Version for this BundleData as specified in the bundle
- * manifest file.
- * @return the Bundle-Version for this BundleData.
- */
- public Version getVersion();
-
- /**
- * Returns the type of bundle this BundleData is for.
- * @return returns the type of bundle this BundleData is for
- */
- public int getType();
-
- /**
- * Returns the Bundle-ClassPath for this BundleData as specified in
- * the bundle manifest file.
- * @return the classpath for this BundleData.
- */
- public String[] getClassPath() throws BundleException;
-
- /**
- * Returns the Bundle-Activator for this BundleData as specified in
- * the bundle manifest file.
- * @return the Bundle-Activator for this BundleData.
- */
- public String getActivator();
-
- /**
- * Returns the Bundle-RequiredExecutionEnvironment for this BundleData as
- * specified in the bundle manifest file.
- * @return the Bundle-RequiredExecutionEnvironment for this BundleData.
- */
- public String getExecutionEnvironment();
-
- /**
- * Returns the DynamicImport-Package for this BundleData as
- * specified in the bundle manifest file.
- * @return the DynamicImport-Packaget for this BundleData.
- */
- public String getDynamicImports();
-
- /**
- * Finds local resources by searching the class path of this bundle data.
- * @param path the requested resource name.
- * @return the requested enumeration of resource URLs or null if the resource does not exist
- */
- public Enumeration<URL> findLocalResources(String path);
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleOperation.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleOperation.java
deleted file mode 100644
index da5e17b7b..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleOperation.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import org.osgi.framework.BundleException;
-
-/**
- * Bundle Storage interface for managing a persistent storage life
- * cycle operation upon a bundle.
- *
- * <p>This class is used to provide methods to manage a life cycle
- * operation on a bundle in persistent storage. BundleOperation objects
- * are returned by the FrameworkAdaptor object and are called by OSGi
- * to complete the persistent storage life cycle operation.
- *
- * <p>For example
- * <pre>
- * Bundle bundle;
- * BundleOperation storage = adaptor.installBundle(location, source);
- * try {
- * bundle = storage.begin();
- *
- * // Perform some implementation specific work
- * // which may fail.
- *
- * storage.commit(false);
- * // bundle has been successfully installed
- * } catch (BundleException e) {
- * storage.undo();
- * throw e; // rethrow the error
- * }
- * return bundle;
- * </pre>
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- */
-public abstract interface BundleOperation {
-
- /**
- * Begin the operation on the bundle (install, update, uninstall).
- *
- * @return BundleData object for the target bundle.
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public abstract BundleData begin() throws BundleException;
-
- /**
- * Commit the operation performed.
- *
- * @param postpone If true, the bundle's persistent
- * storage cannot be immediately reclaimed. This may occur if the
- * bundle is still exporting a package.
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public abstract void commit(boolean postpone) throws BundleException;
-
- /**
- * Undo the change to persistent storage.
- * <p>This method can be called before calling commit or if commit
- * throws an exception to undo any changes in progress.
- *
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public abstract void undo() throws BundleException;
-
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleProtectionDomain.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleProtectionDomain.java
deleted file mode 100644
index f9a23f7b5..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleProtectionDomain.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.security.*;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleReference;
-
-/**
- *
- * This is a specialized ProtectionDomain for a bundle.
- * <p>
- * This class is not intended to be extended by clients.
- * </p>
- * @since 3.1
- */
-public class BundleProtectionDomain extends ProtectionDomain implements BundleReference {
-
- private volatile Bundle bundle;
-
- /**
- * Constructs a special ProtectionDomain for a bundle.
- *
- * @param permCollection
- * the PermissionCollection for the Bundle
- * @deprecated use {@link #BundleProtectionDomain(PermissionCollection, CodeSource, Bundle)}
- */
- public BundleProtectionDomain(PermissionCollection permCollection) {
- this(permCollection, null, null);
- }
-
- /**
- * Constructs a special ProtectionDomain for a bundle.
- *
- * @param permCollection
- * the PermissionCollection for the Bundle
- * @param codeSource
- * the code source for this domain, may be null
- * @param bundle
- * the bundle associated with this domain, may be null
- */
- public BundleProtectionDomain(PermissionCollection permCollection, CodeSource codeSource, Bundle bundle) {
- super(codeSource, permCollection);
- this.bundle = bundle;
- }
-
- /**
- * Sets the bundle object associated with this protection domain.
- * The bundle can only be set once with either this method or with
- * the constructor.
- * @param bundle the bundle object associated with this protection domain
- */
- public void setBundle(Bundle bundle) {
- if (this.bundle != null || bundle == null)
- return;
- this.bundle = bundle;
- }
-
- public Bundle getBundle() {
- return bundle;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleWatcher.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleWatcher.java
deleted file mode 100644
index 75bb33dc4..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/BundleWatcher.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.adaptor;
-
-import org.osgi.framework.Bundle;
-
-/**
- * Watches bundle lifecyle processes. This interface is different than that of
- * a BundleLisener because it gets notified before and after all lifecycle
- * changes. A bundle watcher acts as the main entry point for logging
- * bundle activity.
- * <p>
- * Note that a bundle watcher is always notified of when a lifecycle processes
- * has ended even in cases where the lifecycle process may have failed. For
- * example, if activating a bundle fails the {@link #END_ACTIVATION} flag will
- * still be sent to the bundle watcher to notify them that the activation
- * process has ended.
- * </p>
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- */
-public interface BundleWatcher {
- /**
- * The install process is beginning for a bundle
- * @since 3.2
- */
- public static final int START_INSTALLING = 0x0001;
- /**
- * The install process has ended for a bundle
- * @since 3.2
- */
- public static final int END_INSTALLING = 0x0002;
- /**
- * The activation process is beginning for a bundle
- * @since 3.2
- */
- public static final int START_ACTIVATION = 0x0004;
- /**
- * The activation process has ended for a bundle
- * @since 3.2
- */
- public static final int END_ACTIVATION = 0x0008;
- /**
- * The deactivation process is beginning for a bundle
- * @since 3.2
- */
- public static final int START_DEACTIVATION = 0x0010;
- /**
- * The deactivation process has ended for a bundle
- * @since 3.2
- */
- public static final int END_DEACTIVATION = 0x0020;
- /**
- * The uninstallation process is beginning for a bundle
- * @since 3.2
- */
- public static final int START_UNINSTALLING = 0x0040;
- /**
- * The uninstallation process has ended for a bundle
- * @since 3.2
- */
- public static final int END_UNINSTALLING = 0x0080;
-
- /**
- * Receives notification that a lifecycle change is going to start or has
- * ended.
- * @param bundle the bundle for which the lifecycle change is occurring on.
- * @param type the type of lifecycle change which is occurring.
- * @see #START_INSTALLING
- * @see #END_INSTALLING
- * @see #START_ACTIVATION
- * @see #END_ACTIVATION
- * @see #START_DEACTIVATION
- * @see #END_DEACTIVATION
- * @see #START_UNINSTALLING
- * @see #END_UNINSTALLING
- * @since 3.2
- */
- public void watchBundle(Bundle bundle, int type);
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java
deleted file mode 100644
index fd1ec3d93..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegate.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Enumeration;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.wiring.BundleWiring;
-
-/**
- * A ClassLoaderDelegate is used by the BundleClassLoader in a similar
- * fashion that a parent ClassLoader is used. A ClassLoaderDelegate must
- * be queried for any resource or class before it is loaded by the
- * BundleClassLoader. The Framework implements the ClassLoaderDelegate
- * and supplies it to the BundleClassLoader. FrameworkAdaptor implementations
- * are not responsible for suppling an implementation for ClassLoaderDelegate.
- * <p>
- * This interface is not intended to be implemented by clients.
- * </p>
- * @noimplement This interface is not intended to be implemented by clients.
- * @since 3.1
- */
-public interface ClassLoaderDelegate {
- /**
- * Finds a class for a bundle that may be outside of the actual bundle
- * (i.e. a class from an imported package or required bundle).<p>
- *
- * If the class does not belong to an imported package or is not
- * found in a required bundle then the ClassloaderDelegate will call
- * BundleClassLoader.findLocalClass(). <p>
- *
- * If no class is found then a ClassNotFoundException is thrown.
- * @param classname the class to find.
- * @return the Class.
- * @throws ClassNotFoundException if the class is not found.
- */
- public Class<?> findClass(String classname) throws ClassNotFoundException;
-
- /**
- * Finds a resource for a bundle that may be outside of the actual bundle
- * (i.e. a resource from an imported package or required bundle).<p>
- *
- * If the resource does not belong to an imported package or is not
- * found in a required bundle then the ClassloaderDelegate will call
- * BundleClassLoader.findLocalResource(). <p>
- *
- * If no resource is found then return null.
- * @param resource the resource to load.
- * @return the resource or null if resource is not found.
- */
- public URL findResource(String resource);
-
- /**
- * Finds an enumeration of resources for a bundle that may be outside of
- * the actual bundle (i.e. a resource from an imported package or required
- * bundle).<p>
- *
- * If the resource does not belong to an imported package or is not
- * found in a required bundle then the ClassloaderDelegate will call
- * BundleClassLoader.findLocalResource(). <p>
- * If no resource is found then return null.
- * @param resource the resource to find.
- * @return the enumeration of resources found or null if the resource
- * does not exist.
- */
- public Enumeration<URL> findResources(String resource) throws IOException;
-
- /**
- * Returns the absolute path name of a native library. The following is
- * a list of steps that a ClassLoaderDelegate must take when trying to
- * find a library:
- * <ul>
- * <li>If the bundle is a fragment then try to find the library in the
- * host bundle.
- * <li>if the bundle is a host then try to find the library in the
- * host bundle and then try to find the library in the fragment
- * bundles.
- * </ul>
- * If no library is found return null.
- * @param libraryname the library to find the path to.
- * @return the path to the library or null if not found.
- */
- public String findLibrary(String libraryname);
-
- /**
- * Returns true if the lazy trigger has been set for this
- * delegate. The lazy trigger is set when a bundle has been
- * marked for lazy activation due to a successful class load.
- * @return true if the lazy trigger has been set
- * @since 3.6
- */
- public boolean isLazyTriggerSet();
-
- /**
- * Sets the lazy trigger for this delegate. This will activate
- * the bundle if the bundle has been started with the activation
- * policy and the bundle's start level is met.
- * @throws BundleException if an error occurred while activating the bundle
- * @see ClassLoaderDelegate#isLazyTriggerSet()
- * @since 3.6
- */
- public void setLazyTrigger() throws BundleException;
-
- /**
- * Returns the names of resources visible to this delegate.
- * This is used to answer a call to the
- * {@link BundleWiring#listResources(String, String, int)} method.
- * First a search is done on the packages imported by the bundle associated
- * with this delegate. Next a search is done on the the bundles required by
- * the bundle associated with this delegate. Finally a local search of
- * the bundle associated with this delegate is done by calling
- * {@link BundleClassLoader#listLocalResources(String, String, int)}. Note
- * that for imported packages the search stops at the source for the import.
- * @param path The path name in which to look.
- * @param filePattern The file name pattern for selecting resource names in
- * the specified path.
- * @param options The options for listing resource names.
- * @return a collection of resource names. If no resources are found then
- * the empty collection is returned.
- * @see BundleWiring#listResources(String, String, int)
- */
- public Collection<String> listResources(String path, String filePattern, int options);
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegateHook.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegateHook.java
deleted file mode 100644
index 424feb98a..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ClassLoaderDelegateHook.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.io.FileNotFoundException;
-import java.net.URL;
-import java.util.Enumeration;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-
-/**
- * A ClassLoaderDelegateHook hooks into the <code>ClassLoaderDelegate</code>.
- * @see ClassLoaderDelegate
- * @see HookRegistry#getClassLoaderDelegateHooks()
- * @see HookRegistry#addClassLoaderDelegateHook(ClassLoaderDelegateHook)
- * @since 3.4
- */
-public interface ClassLoaderDelegateHook {
- /**
- * Called by a {@link ClassLoaderDelegate#findClass(String)} method before delegating to the resolved constraints and
- * local bundle for a class load. If this method returns null then normal delegation is done. If this method
- * returns a non-null value then the rest of the delegation process is skipped and the returned value is used.
- * If this method throws a <code>ClassNotFoundException</code> then the calling
- * {@link ClassLoaderDelegate#findClass(String)} method re-throws the exception.
- * @param name the name of the class to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the class found by this hook or null if normal delegation should continue
- * @throws ClassNotFoundException to terminate the delegation and throw an exception
- */
- public Class<?> preFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate#findClass(String)} method after delegating to the resolved constraints and
- * local bundle for a class load. This method will only be called if no class was found
- * from the normal delegation.
- * @param name the name of the class to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the class found by this hook or null if normal delegation should continue
- * @throws ClassNotFoundException to terminate the delegation and throw an exception
- */
- public Class<?> postFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate #findResource(String)} before delegating to the resolved constraints and
- * local bundle for a resource load. If this method returns null then normal delegation is done.
- * If this method returns a non-null value then the rest of the delegation process is skipped and the returned value is used.
- * If this method throws an <code>FileNotFoundException</code> then the delegation is terminated.
- * @param name the name of the resource to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the resource found by this hook or null if normal delegation should continue
- * @throws FileNotFoundException to terminate the delegation
- */
- public URL preFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate} after delegating to the resolved constraints and
- * local bundle for a resource load. This method will only be called if no resource was found
- * from the normal delegation.
- * @param name the name of the resource to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the resource found by this hook or null if normal delegation should continue
- * @throws FileNotFoundException to terminate the delegation
- */
- public URL postFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate} before delegating to the resolved constraints and
- * local bundle for a resource load. If this method returns null then normal delegation is done.
- * If this method returns a non-null value then the rest of the delegation process is skipped and the returned value is used.
- * If this method throws an <code>FileNotFoundException</code> then the delegation is terminated
- * @param name the name of the resource to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the resources found by this hook or null if normal delegation should continue
- * @throws FileNotFoundException to terminate the delegation
- */
- public Enumeration<URL> preFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate} after delegating to the resolved constraints and
- * local bundle for a resource load. This method will only be called if no resources were found
- * from the normal delegation.
- * @param name the name of the resource to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the resources found by this hook or null if normal delegation should continue
- * @throws FileNotFoundException to terminate the delegation
- */
- public Enumeration<URL> postFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate} before normal delegation. If this method returns
- * a non-null value then the rest of the delegation process is skipped and the returned value
- * is used.
- * @param name the name of the library to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the library found by this hook or null if normal delegation should continue
- * @throws FileNotFoundException to terminate the delegation
- */
- public String preFindLibrary(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException;
-
- /**
- * Called by a {@link ClassLoaderDelegate} after normal delegation. This method will only be called
- * if no library was found from the normal delegation.
- * @param name the name of the library to find
- * @param classLoader the bundle class loader
- * @param data the bundle data
- * @return the library found by this hook or null if normal delegation should continue
- */
- public String postFindLibrary(String name, BundleClassLoader classLoader, BundleData data);
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/EventPublisher.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/EventPublisher.java
deleted file mode 100644
index 429848723..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/EventPublisher.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2005 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import org.osgi.framework.Bundle;
-
-/**
- * The EventPublisher is used by FrameworkAdaptors to publish events to the
- * Framework.
- * <p>
- * This interface is not intended to be implemented by clients.
- * </p>
- * @since 3.1
- */
-public interface EventPublisher {
-
- /**
- * Publish a FrameworkEvent.
- *
- * @param type FrameworkEvent type.
- * @param bundle Bundle related to FrameworkEven or <tt>null</tt> to for the
- * system bundle.
- * @param throwable Related exception or <tt>null</tt>.
- * @see org.osgi.framework.FrameworkEvent
- */
- public abstract void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable);
-
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java
deleted file mode 100644
index e09b3633c..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.*;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.service.resolver.PlatformAdmin;
-import org.eclipse.osgi.service.resolver.State;
-import org.osgi.framework.*;
-
-/**
- * FrameworkAdaptor interface to the osgi framework. This class is used to provide
- * platform specific support for the osgi framework.
- *
- * <p>The OSGi framework will call this class to perform platform specific functions.
- *
- * Classes that implement FrameworkAdaptor MUST provide a constructor that takes as a
- * parameter an array of Strings. This array will contain arguments to be
- * handled by the FrameworkAdaptor. The FrameworkAdaptor implementation may define the format
- * and content of its arguments.
- *
- * The constructor should parse the arguments passed to it and remember them.
- * The initialize method should perform the actual processing of the adaptor
- * arguments.
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- */
-
-public interface FrameworkAdaptor {
-
- public static final String FRAMEWORK_SYMBOLICNAME = "org.eclipse.osgi"; //$NON-NLS-1$
-
- /**
- * Initialize the FrameworkAdaptor object so that it is ready to be
- * called by the framework. Handle the arguments that were
- * passed to the constructor.
- * This method must be called before any other FrameworkAdaptor methods.
- * @param eventPublisher The EventPublisher used to publish any events to
- * the framework.
- */
- public void initialize(EventPublisher eventPublisher);
-
- /**
- * Initialize the persistent storage for the adaptor.
- *
- * @throws IOException If the adaptor is unable to
- * initialize the bundle storage.
- */
- public void initializeStorage() throws IOException;
-
- /**
- * Compact/cleanup the persistent storage for the adaptor.
- * @throws IOException If the adaptor is unable to
- * compact the bundle storage.
- *
- */
- public void compactStorage() throws IOException;
-
- /**
- * Return the properties object for the adaptor.
- * The properties in the returned object supplement
- * the System properties.
- * The framework may modify this object. The Framework
- * will use the returned properties to set the System
- * properties.
- *
- * @return The properties object for the adaptor.
- */
- public Properties getProperties();
-
- /**
- * Return a list of the installed bundles. Each element in the
- * list must be of type <code>BundleData</code>. Each <code>BundleData</code>
- * corresponds to one bundle that is persistently stored.
- * This method must construct <code>BundleData</code> objects for all
- * installed bundles and return an array containing the objects.
- * The returned array becomes the property of the framework.
- *
- * @return Array of installed BundleData objects, or null if none can be found.
- */
- public BundleData[] getInstalledBundles();
-
- /**
- * Map a location to a URLConnection. This is used by the Framework when installing a bundle
- * from a spacified location.
- *
- * @param location of the bundle.
- * @return URLConnection that represents the location.
- * @throws BundleException if the mapping fails.
- */
- public URLConnection mapLocationToURLConnection(String location) throws BundleException;
-
- /**
- * Prepare to install a bundle from a URLConnection.
- * <p>To complete the install,
- * begin and then commit
- * must be called on the returned <code>BundleOperation</code> object.
- * If either of these methods throw a BundleException
- * or some other error occurs,
- * then undo must be called on the <code>BundleOperation</code> object
- * to undo the change to persistent storage.
- *
- * @param location Bundle location.
- * @param source URLConnection from which the bundle may be read.
- * Any InputStreams returned from the source
- * (URLConnections.getInputStream) must be closed by the
- * <code>BundleOperation</code> object.
- * @return BundleOperation object to be used to complete the install.
- */
- public BundleOperation installBundle(String location, URLConnection source);
-
- /**
- * Prepare to update a bundle from a URLConnection.
- * <p>To complete the update
- * begin and then commit
- * must be called on the returned <code>BundleOperation</code> object.
- * If either of these methods throw a BundleException
- * or some other error occurs,
- * then undo must be called on the <code>BundleOperation</code> object
- * to undo the change to persistent storage.
- *
- * @param bundledata BundleData to update.
- * @param source URLConnection from which the updated bundle may be read.
- * Any InputStreams returned from the source
- * (URLConnections.getInputStream) must be closed by the
- * <code>BundleOperation</code> object.
- * @return BundleOperation object to be used to complete the update.
- */
- public BundleOperation updateBundle(BundleData bundledata, URLConnection source);
-
- /**
- * Prepare to uninstall a bundle.
- * <p>To complete the uninstall,
- * begin and then commit
- * must be called on the returned <code>BundleOperation</code> object.
- * If either of these methods throw a BundleException
- * or some other error occurs,
- * then undo must be called on the <code>BundleOperation</code> object
- * to undo the change to persistent storage.
- *
- * @param bundledata BundleData to uninstall.
- * @return BundleOperation object to be used to complete the uninstall.
- */
- public BundleOperation uninstallBundle(BundleData bundledata);
-
- /**
- * Returns the total amount of free space available for bundle storage on the device.
- *
- * @return Free space available in bytes or -1 if it does not apply to this adaptor
- * @exception IOException if an I/O error occurs determining the available space
- */
- public long getTotalFreeSpace() throws IOException;
-
- /**
- * Returns the PermissionStorage object which will be used to
- * to manage the permission data.
- *
- * @return The PermissionStorage object for the adaptor.
- * @see "org.osgi.service.permissionadmin.PermissionAdmin"
- */
- public PermissionStorage getPermissionStorage() throws IOException;
-
- /**
- * The framework will call this method after the
- * System BundleActivator.start(BundleContext) has been called. The context is
- * the System Bundle's BundleContext. This method allows FrameworkAdaptors to
- * have access to the OSGi framework to get services, register services and
- * perform other OSGi operations.
- * @param context The System Bundle's BundleContext.
- * @exception BundleException on any error that may occur.
- */
- public void frameworkStart(BundleContext context) throws BundleException;
-
- /**
- * The framework will call this method before the
- * System BundleActivator.stop(BundleContext) has been called. The context is
- * the System Bundle's BundleContext. This method allows FrameworkAdaptors to
- * have access to the OSGi framework to get services, register services and
- * perform other OSGi operations.
- * @param context The System Bundle's BundleContext.
- * @exception BundleException on any error that may occur.
- */
- public void frameworkStop(BundleContext context) throws BundleException;
-
- /**
- * The framework will call this method before the process of framework
- * shutdown is started. This gives FrameworkAdaptors a chance to
- * perform actions before the framework start level is decremented and
- * all the bundles are stopped. This method will get called before the
- * {@link #frameworkStop(BundleContext)} method.
- * @param context The System Bundle's BundleContext.
- */
- public void frameworkStopping(BundleContext context);
-
- /**
- * Returns the initial bundle start level as maintained by this adaptor
- * @return the initial bundle start level
- */
- public int getInitialBundleStartLevel();
-
- /**
- * Sets the initial bundle start level
- * @param value the initial bundle start level
- */
- public void setInitialBundleStartLevel(int value);
-
- /**
- * Returns the FrameworkLog for the FrameworkAdaptor. The FrameworkLog
- * is used by the Framework and FrameworkAdaptor to log any error messages
- * and FramworkEvents of type ERROR.
- * @return The FrameworkLog to be used by the Framework.
- */
- public FrameworkLog getFrameworkLog();
-
- /**
- * Creates a BundleData object for the System Bundle. The BundleData
- * returned will be used to define the System Bundle for the Framework.
- * @return the BundleData for the System Bundle.
- * @throws BundleException if any error occurs while creating the
- * System BundleData.
- */
- public BundleData createSystemBundleData() throws BundleException;
-
- /**
- * Returns the bundle watcher for this FrameworkAdaptor.
- * @return the bundle watcher for this FrameworkAdaptor.
- */
- public BundleWatcher getBundleWatcher();
-
- /**
- * Returns the PlatformAdmin for this FrameworkAdaptor.
- * <p>
- * This method will not be called until after
- * {@link FrameworkAdaptor#frameworkStart(BundleContext)} is called.
- * @return the PlatformAdmin for this FrameworkAdaptor.
- */
- public PlatformAdmin getPlatformAdmin();
-
- /**
- * Returns the State for this FrameworkAdaptor.
- * <p>
- * This method will not be called until after
- * {@link FrameworkAdaptor#frameworkStart(BundleContext)} is called.
- * The State returned is used by the framework to resolve bundle
- * dependencies.
- * @return the State for this FrameworkAdaptor.
- */
- public State getState();
-
- /**
- * Returns the parent ClassLoader all BundleClassLoaders created. All
- * BundleClassLoaders that are created must use the ClassLoader returned
- * by this method as a parent ClassLoader. Each call to this method must
- * return the same ClassLoader object.
- * @return the parent ClassLoader for all BundleClassLoaders created.
- */
- public ClassLoader getBundleClassLoaderParent();
-
- /**
- * Handles a RuntimeException or Error that was caught by the Framework and
- * there is not a suitable caller to propagate the Throwable to. This gives
- * the FrameworkAdaptor the ablity to handle such cases. For example, a
- * FrameworkAdaptor may decide that such unexpected errors should cause an error
- * message to be logged, or that the Framework should be terminated immediately.
- * @param error The Throwable for the runtime error that is to be handled.
- */
- public void handleRuntimeError(Throwable error);
-
- /**
- * Returns resources entries for the specified bundle datas.
- * @param datas the list of bundle datas to search in
- * @param path The path name in which to look.
- * @param filePattern The file name pattern for selecting resource names in
- * the specified path.
- * @param options The options for listing resource names.
- * @return a list of resource URLs. If no resources are found then
- * the empty list is returned.
- * @see BundleClassLoader#findEntries(String, String, int)
- * @see Bundle#findEntries(String, String, boolean)
- */
- public Enumeration<URL> findEntries(List<BundleData> datas, String path, String filePattern, int options);
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/PermissionStorage.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/PermissionStorage.java
deleted file mode 100644
index 6ad1d04b4..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/PermissionStorage.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import java.io.IOException;
-
-/**
- * Permission Storage interface for managing a persistent storage of
- * bundle permissions.
- *
- * <p>This class is used to provide methods to manage
- * persistent storage of bundle permissions. The PermissionStorage object
- * is returned by the FrameworkAdaptor object and is called
- * to persistently store bundle permissions.
- *
- * <p>The permission data will typically take the form of encoded
- * <tt>PermissionInfo</tt> Strings.
- * See org.osgi.service.permissionadmin.PermissionInfo.
- *
- * <p>For example
- * <pre>
- * PermissionStorage storage = adaptor.getPermissionStorage();
- * try {
- * storage.setPermissionData(location, permissions);
- * } catch (IOException e) {
- * // Take some error action.
- * }
- * </pre>
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- */
-public interface PermissionStorage {
- /**
- * Returns the locations that have permission data assigned to them,
- * that is, locations for which permission data
- * exists in persistent storage.
- *
- * @return The locations that have permission data in
- * persistent storage, or <tt>null</tt> if there is no permission data
- * in persistent storage.
- * @throws IOException If a failure occurs accessing persistent storage.
- */
- public String[] getLocations() throws IOException;
-
- /**
- * Gets the permission data assigned to the specified
- * location.
- *
- * @param location The location whose permission data is to
- * be returned.
- * The location can be <tt>null</tt> for the default permission data.
- *
- * @return The permission data assigned to the specified
- * location, or <tt>null</tt> if that location has not been assigned any
- * permission data.
- * @throws IOException If a failure occurs accessing persistent storage.
- */
- public String[] getPermissionData(String location) throws IOException;
-
- /**
- * Assigns the specified permission data to the specified
- * location.
- *
- * @param location The location that will be assigned the
- * permissions.
- * The location can be <tt>null</tt> for the default permission data.
- * @param data The permission data to be assigned, or <tt>null</tt>
- * if the specified location is to be removed from persistent storaqe.
- * @throws IOException If a failure occurs modifying persistent storage.
- */
- public void setPermissionData(String location, String[] data) throws IOException;
-
- /**
- * Persists the array of encoded ConditionalPermissionInfo strings
- * @param infos an array of encoded ConditionalPermissionInfo strings
- * @throws IOException If a failure occurs modifying persistent storage.
- * @since 3.2
- */
- public void saveConditionalPermissionInfos(String[] infos) throws IOException;
-
- /**
- * Returns the persistent array of encoded ConditionalPermissionInfo strings
- * @return an array of encoded ConditionalPermissionInfo strings or null
- * if none exist in persistent storage.
- * @throws IOException If a failure occurs accessing persistent storage.
- * @since 3.2
- */
- public String[] getConditionalPermissionInfos() throws IOException;
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/StatusException.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/StatusException.java
deleted file mode 100644
index 86dfd3090..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/StatusException.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.adaptor;
-
-/**
- * An exception my implement the StatusException interface to give more status information about the type of exception.
- */
-public interface StatusException {
- /**
- * The exception is ok and expected
- */
- public static final int CODE_OK = 0x01;
- /**
- * The exception is for informational purposes
- */
- public static final int CODE_INFO = 0x02;
- /**
- * The exception is unexpected by may be handled, but a warning should be logged
- */
- public static final int CODE_WARNING = 0x04;
- /**
- * The exception is unexpected and should result in an error.
- */
- public static final int CODE_ERROR = 0x08;
-
- /**
- * Returns the status object
- * @return the status object
- */
- public Object getStatus();
-
- /**
- * Returns the status code
- * @return the status code
- */
- public int getStatusCode();
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/DescriptionReference.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/DescriptionReference.java
deleted file mode 100644
index d7d32cbf4..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/DescriptionReference.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.service.resolver.extras;
-
-import org.eclipse.osgi.service.resolver.BaseDescription;
-
-/**
- * A reference to a {@link BaseDescription}.
- * @since 3.8
- */
-public interface DescriptionReference {
- /**
- * Returns the {@code BaseDescription} object associated with this
- * reference.
- *
- * @return The {@code BaseDescription} object associated with this
- * reference.
- */
- public BaseDescription getDescription();
-}
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/Sortable.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/Sortable.java
deleted file mode 100644
index 2442c5e2f..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/Sortable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.service.resolver.extras;
-
-import java.util.Comparator;
-
-/**
- * Represents a collection of elements which can be sorted.
- * @since 3.8
- */
-public interface Sortable<E> {
- /**
- * Sorts collection of elements represented by this sortable according
- * to the specified comparator.
- * @param comparator the comparator used to sort the collection
- * of elements represented by this sortable.
- */
- void sort(Comparator<E> comparator);
-} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/SpecificationReference.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/SpecificationReference.java
deleted file mode 100644
index c63e2c181..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/extras/SpecificationReference.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.service.resolver.extras;
-
-import org.eclipse.osgi.service.resolver.VersionConstraint;
-
-/**
- * A reference to a {@link VersionConstraint} specification.
- * @since 3.8
- */
-public interface SpecificationReference {
- /**
- * Returns the {@code VersionConstraint} object associated with this
- * reference.
- *
- * @return The {@code VersionConstraint} object associated with this
- * reference.
- */
- public VersionConstraint getSpecification();
-} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeBase.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeBase.java
deleted file mode 100644
index 6d47cb979..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeBase.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import java.io.IOException;
-import java.io.InputStream;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
-import org.eclipse.osgi.framework.internal.core.BundleHost;
-import org.eclipse.osgi.internal.module.CompositeResolveHelper;
-import org.eclipse.osgi.service.internal.composite.CompositeModule;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.launch.Framework;
-
-/**
- * This is a base class for both composite and surrogate bundles.
- */
-public abstract class CompositeBase extends BundleHost implements CompositeResolveHelper, CompositeModule {
- protected static String PROP_COMPOSITE = "org.eclipse.equinox.Composite"; //$NON-NLS-1$
- protected static String PROP_PARENTFRAMEWORK = "org.eclipse.equinox.parentFramework"; //$NON-NLS-1$
-
- protected final Framework companionFramework;
- protected final ThreadLocal resolving = new ThreadLocal();
-
- public CompositeBase(BundleData bundledata, org.eclipse.osgi.framework.internal.core.Framework framework) throws BundleException {
- super(bundledata, framework);
- this.companionFramework = findCompanionFramework(framework, bundledata);
- }
-
- /*
- * Finds the companion framework for the composite/surrogate.
- * For surrogate bundles this is the parent framework.
- * For composite bundles this is the child framework.
- */
- protected abstract Framework findCompanionFramework(org.eclipse.osgi.framework.internal.core.Framework thisFramework, BundleData thisData) throws BundleException;
-
- /*
- * Gets the companion bundle for the composite/surrogate.
- * For surrogate bundles this is the composite bundle.
- * For composite bundles this is the surrogate bundle.
- */
- abstract protected Bundle getCompanionBundle();
-
- protected boolean isSurrogate() {
- return false;
- }
-
- public BundleDescription getCompositeDescription() {
- return getBundleDescription();
- }
-
- public ClassLoaderDelegate getDelegate() {
- return getBundleLoader();
- }
-
- public void refreshContent() {
- resolving.set(Boolean.TRUE);
- try {
- framework.getPackageAdmin().refreshPackages(new Bundle[] {this}, true, null);
- } finally {
- resolving.set(null);
- }
- }
-
- public boolean resolveContent() {
- resolving.set(Boolean.TRUE);
- try {
- return framework.getPackageAdmin().resolveBundles(new Bundle[] {this});
- } finally {
- resolving.set(null);
- }
- }
-
- public void started(CompositeModule surrogate) {
- // nothing
- }
-
- public void stopped(CompositeModule surrogate) {
- // nothing
- }
-
- public void updateContent(InputStream content) throws BundleException {
- super.update(content);
- }
-
- public void update() throws BundleException {
- throw new BundleException("Cannot update composite bundles", BundleException.INVALID_OPERATION); //$NON-NLS-1$
- }
-
- public void update(InputStream in) throws BundleException {
- try {
- in.close();
- } catch (IOException e) {
- // ignore
- }
- throw new BundleException("Cannot update composite bundles", BundleException.INVALID_OPERATION); //$NON-NLS-1$
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeClassLoader.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeClassLoader.java
deleted file mode 100644
index e0706ff41..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeClassLoader.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
-import org.osgi.framework.Bundle;
-
-public class CompositeClassLoader extends ClassLoader implements BaseClassLoader {
-
- private final ClassLoaderDelegate delegate;
- private final ClasspathManager manager;
- private final ClassLoaderDelegate companionDelegate;
- //Support to cut class / resource loading cycles in the context of one thread. The contained object is a set of classname
- private final ThreadLocal beingLoaded = new ThreadLocal();
-
- public CompositeClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, ClassLoaderDelegate companionDelegate, BaseData data) {
- super(parent);
- this.delegate = delegate;
- this.manager = new ClasspathManager(data, new String[0], this);
- this.companionDelegate = companionDelegate;
- }
-
- public ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain cpDomain) {
- // nothing
- return null;
- }
-
- public Class defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry) {
- // nothing
- return null;
- }
-
- public ClasspathManager getClasspathManager() {
- return manager;
- }
-
- public ProtectionDomain getDomain() {
- // no domain
- return null;
- }
-
- public Object publicDefinePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) {
- return definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
- }
-
- public Class publicFindLoaded(String classname) {
- return findLoadedClass(classname);
- }
-
- public Object publicGetPackage(String pkgname) {
- return getPackage(pkgname);
- }
-
- public void attachFragment(BundleData bundledata, ProtectionDomain domain, String[] classpath) {
- // nothing
- }
-
- public void close() {
- // nothing
- }
-
- public Class findLocalClass(String classname) throws ClassNotFoundException {
- if (!startLoading(classname))
- throw new ClassNotFoundException(classname);
- try {
- return companionDelegate.findClass(classname);
- } finally {
- stopLoading(classname);
- }
- }
-
- public URL findLocalResource(String resource) {
- if (!startLoading(resource))
- return null;
- try {
- return companionDelegate.findResource(resource);
- } finally {
- stopLoading(resource);
- }
- }
-
- public Enumeration findLocalResources(String resource) {
- if (!startLoading(resource))
- return null;
- try {
- return companionDelegate.findResources(resource);
- } catch (IOException e) {
- return null;
- } finally {
- stopLoading(resource);
- }
- }
-
- public ClassLoaderDelegate getDelegate() {
- return delegate;
- }
-
- public URL getResource(String name) {
- return delegate.findResource(name);
- }
-
- public void initialize() {
- manager.initialize();
- }
-
- public Class loadClass(String name) throws ClassNotFoundException {
- return delegate.findClass(name);
- }
-
- private boolean startLoading(String name) {
- Set classesAndResources = (Set) beingLoaded.get();
- if (classesAndResources != null && classesAndResources.contains(name))
- return false;
-
- if (classesAndResources == null) {
- classesAndResources = new HashSet(3);
- beingLoaded.set(classesAndResources);
- }
- classesAndResources.add(name);
- return true;
- }
-
- private void stopLoading(String name) {
- ((Set) beingLoaded.get()).remove(name);
- }
-
- public Bundle getBundle() {
- return manager.getBaseData().getBundle();
- }
-
- @SuppressWarnings("unchecked")
- public List<URL> findEntries(String path, String filePattern, int options) {
- return Collections.EMPTY_LIST;
- }
-
- @SuppressWarnings("unchecked")
- public Collection<String> listResources(String path, String filePattern, int options) {
- return Collections.EMPTY_LIST;
- }
-
- @SuppressWarnings("unchecked")
- public Collection<String> listLocalResources(String path, String filePattern, int options) {
- return Collections.EMPTY_LIST;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeConfigurator.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeConfigurator.java
deleted file mode 100644
index b545a0a70..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeConfigurator.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URLConnection;
-import java.security.AllPermission;
-import java.security.ProtectionDomain;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.internal.module.*;
-import org.eclipse.osgi.service.internal.composite.CompositeModule;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.osgi.framework.*;
-import org.osgi.framework.launch.Framework;
-import org.osgi.service.framework.CompositeBundle;
-import org.osgi.service.framework.CompositeBundleFactory;
-
-public class CompositeConfigurator implements SynchronousBundleListener, HookConfigurator, AdaptorHook, ClassLoadingHook, CompositeBundleFactory, CompositeResolveHelperRegistry {
-
- // the base adaptor
- private BaseAdaptor adaptor;
- // the composite bundle factory service reference
- private ServiceRegistration factoryService;
- // the system bundle context
- private BundleContext systemContext;
- // The composite resolver helpers
- private final Collection helpers = new ArrayList(0);
-
- public void addHooks(HookRegistry hookRegistry) {
- // this is an adaptor hook to register the composite factory and
- // to shutdown child frameworks on shutdown
- hookRegistry.addAdaptorHook(this);
- // this is a class loading hook in order to create special class loaders for composites
- hookRegistry.addClassLoadingHook(this);
- }
-
- public void addProperties(Properties properties) {
- // nothing
- }
-
- public FrameworkLog createFrameworkLog() {
- // nothing
- return null;
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStart(BundleContext context) throws BundleException {
- this.systemContext = context;
- context.addBundleListener(this);
- addHelpers(context.getBundles());
- // this is a composite resolve helper registry; add it to the resolver
- ((ResolverImpl) adaptor.getState().getResolver()).setCompositeResolveHelperRegistry(this);
- // register this as the composite bundle factory
- factoryService = context.registerService(new String[] {CompositeBundleFactory.class.getName()}, this, null);
- }
-
- public void frameworkStop(BundleContext context) {
- // unregister the factory
- if (factoryService != null)
- factoryService.unregister();
- factoryService = null;
- // stop any child frameworks than may still be running.
- stopFrameworks();
- context.removeBundleListener(this);
- removeAllHelpers();
- }
-
- public void frameworkStopping(BundleContext context) {
- // nothing
- }
-
- public void handleRuntimeError(Throwable error) {
- // nothing
- }
-
- public void initialize(BaseAdaptor initAdaptor) {
- this.adaptor = initAdaptor;
- }
-
- public URLConnection mapLocationToURLConnection(String location) {
- // nothing
- return null;
- }
-
- public boolean matchDNChain(String pattern, String[] dnChain) {
- // nothing
- return false;
- }
-
- public CompositeBundle installCompositeBundle(Map frameworkConfig, String location, Map compositeManifest) throws BundleException {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- // must have AllPermission to do this
- sm.checkPermission(new AllPermission());
- // make a local copy of the manifest first
- compositeManifest = new HashMap(compositeManifest);
- // make sure the manifest is valid
- CompositeHelper.validateCompositeManifest(compositeManifest);
-
- try {
- // get an in memory input stream to jar content of the composite we want to install
- InputStream content = CompositeHelper.getCompositeInput(frameworkConfig, compositeManifest);
- CompositeBundle result = (CompositeBundle) systemContext.installBundle(location, content);
- // set the permissions
- CompositeHelper.setCompositePermissions(location, systemContext);
- return result;
- } catch (IOException e) {
- throw new BundleException("Error creating composite bundle", e); //$NON-NLS-1$
- }
- }
-
- private void stopFrameworks() {
- Bundle[] allBundles = systemContext.getBundles();
- // stop each child framework
- for (int i = 0; i < allBundles.length; i++) {
- if (!(allBundles[i] instanceof CompositeBundle))
- continue;
- CompositeBundle composite = (CompositeBundle) allBundles[i];
- try {
- Framework child = composite.getCompositeFramework();
- child.stop();
- // need to wait for each child to stop
- child.waitForStop(30000);
- // TODO need to figure out a way to invalid the child
- } catch (Throwable t) {
- // TODO consider logging
- t.printStackTrace();
- }
- }
- }
-
- public CompositeResolveHelper getCompositeResolveHelper(BundleDescription bundle) {
- // Composite bundles implement the resolver helper
- synchronized (helpers) {
- if (helpers.size() == 0)
- return null;
- for (Iterator iHelpers = helpers.iterator(); iHelpers.hasNext();) {
- CompositeBase composite = (CompositeBase) iHelpers.next();
- if (composite.getBundleId() == bundle.getBundleId())
- // If we found a resolver helper bundle; return it
- return composite;
- }
- return null;
- }
- }
-
- public boolean addClassPathEntry(ArrayList cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) {
- // nothing
- return false;
- }
-
- public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) {
- if ((data.getType() & (BundleData.TYPE_COMPOSITEBUNDLE | BundleData.TYPE_SURROGATEBUNDLE)) == 0)
- return null;
- // only create composite class loaders for bundles that are of type composite | surrogate
- CompositeModule compositeModule = (CompositeModule) ((CompositeBase) data.getBundle()).getCompanionBundle();
- if (compositeModule == null) {
- throw new IllegalStateException("Could not find companion bundle for " + data.getBundle());
- }
- ClassLoaderDelegate companionDelegate = compositeModule.getDelegate();
- if (companionDelegate == null) {
- throw new IllegalStateException("Could not find the companion bundle delegate for" + compositeModule);
- }
- return new CompositeClassLoader(parent, delegate, companionDelegate, data);
- }
-
- public String findLibrary(BaseData data, String libName) {
- // nothing
- return null;
- }
-
- public ClassLoader getBundleClassLoaderParent() {
- // nothing
- return null;
- }
-
- public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
- // nothing
- }
-
- public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- // nothing
- return null;
- }
-
- private void addHelpers(Bundle[] bundles) {
- synchronized (helpers) {
- for (int i = 0; i < bundles.length; i++)
- addHelper(bundles[i]);
- }
- }
-
- private void addHelper(Bundle bundle) {
- if (!(bundle instanceof CompositeBase))
- return;
- synchronized (helpers) {
- if (!helpers.contains(bundle))
- helpers.add(bundle);
- }
- }
-
- private void removeHelper(Bundle bundle) {
- if (!(bundle instanceof CompositeBase))
- return;
- synchronized (helpers) {
- helpers.remove(bundle);
- }
- }
-
- private void removeAllHelpers() {
- synchronized (helpers) {
- helpers.clear();
- }
- }
-
- public void bundleChanged(BundleEvent event) {
- switch (event.getType()) {
- case BundleEvent.INSTALLED :
- addHelper(event.getBundle());
- break;
- case BundleEvent.UNINSTALLED :
- removeHelper(event.getBundle());
- break;
- default :
- break;
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeHelper.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeHelper.java
deleted file mode 100644
index 5ef32c766..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeHelper.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-import java.util.jar.*;
-import org.eclipse.osgi.internal.baseadaptor.BaseStorageHook;
-import org.eclipse.osgi.service.resolver.*;
-import org.osgi.framework.*;
-import org.osgi.service.permissionadmin.PermissionAdmin;
-import org.osgi.service.permissionadmin.PermissionInfo;
-
-public class CompositeHelper {
- private static final PermissionInfo[] COMPOSITE_PERMISSIONS = new PermissionInfo[] {new PermissionInfo(PackagePermission.class.getName(), "*", PackagePermission.EXPORT), new PermissionInfo(ServicePermission.class.getName(), "*", ServicePermission.REGISTER + ',' + ServicePermission.GET)}; //$NON-NLS-1$ //$NON-NLS-2$
- private static final String COMPOSITE_POLICY = "org.eclipse.osgi.composite"; //$NON-NLS-1$
- private static String ELEMENT_SEPARATOR = "; "; //$NON-NLS-1$
- private static final Object EQUALS_QUOTE = "=\""; //$NON-NLS-1$
- private static final String[] INVALID_COMPOSITE_HEADERS = new String[] {Constants.DYNAMICIMPORT_PACKAGE, Constants.FRAGMENT_HOST, Constants.REQUIRE_BUNDLE, Constants.BUNDLE_NATIVECODE, Constants.BUNDLE_CLASSPATH, Constants.BUNDLE_ACTIVATOR, Constants.BUNDLE_LOCALIZATION, Constants.BUNDLE_ACTIVATIONPOLICY};
-
- private static Manifest getCompositeManifest(Map compositeManifest) {
- Manifest manifest = new Manifest();
- Attributes attributes = manifest.getMainAttributes();
- attributes.putValue("Manifest-Version", "1.0"); //$NON-NLS-1$//$NON-NLS-2$
- // get the common headers Bundle-ManifestVersion, Bundle-SymbolicName and Bundle-Version
- // get the manifest version from the map
- String manifestVersion = (String) compositeManifest.remove(Constants.BUNDLE_MANIFESTVERSION);
- // here we assume the validation got the correct version for us
- attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, manifestVersion);
- // Ignore the Equinox composite bundle header
- compositeManifest.remove(BaseStorageHook.COMPOSITE_HEADER);
- attributes.putValue(BaseStorageHook.COMPOSITE_HEADER, BaseStorageHook.COMPOSITE_BUNDLE);
- for (Iterator entries = compositeManifest.entrySet().iterator(); entries.hasNext();) {
- Map.Entry entry = (Entry) entries.next();
- if (entry.getKey() instanceof String && entry.getValue() instanceof String)
- attributes.putValue((String) entry.getKey(), (String) entry.getValue());
- }
- return manifest;
- }
-
- private static Manifest getSurrogateManifest(Dictionary compositeManifest, BundleDescription compositeDesc, ExportPackageDescription[] matchingExports) {
- Manifest manifest = new Manifest();
- Attributes attributes = manifest.getMainAttributes();
- attributes.putValue("Manifest-Version", "1.0"); //$NON-NLS-1$//$NON-NLS-2$
- // Ignore the manifest version from the map
- // always use bundle manifest version 2
- attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, "2"); //$NON-NLS-1$
- // Ignore the Equinox composite bundle header
- attributes.putValue(BaseStorageHook.COMPOSITE_HEADER, BaseStorageHook.SURROGATE_BUNDLE);
-
- if (compositeDesc != null && matchingExports != null) {
- // convert the exports from the composite into imports
- addImports(attributes, compositeDesc, matchingExports);
-
- // convert the matchingExports from the composite into exports
- addExports(attributes, compositeDesc, matchingExports);
- }
-
- // add the rest
- for (Enumeration keys = compositeManifest.keys(); keys.hasMoreElements();) {
- Object header = keys.nextElement();
- if (Constants.BUNDLE_MANIFESTVERSION.equals(header) || BaseStorageHook.COMPOSITE_HEADER.equals(header) || Constants.IMPORT_PACKAGE.equals(header) || Constants.EXPORT_PACKAGE.equals(header))
- continue;
- if (header instanceof String && compositeManifest.get(header) instanceof String)
- attributes.putValue((String) header, (String) compositeManifest.get(header));
- }
- return manifest;
- }
-
- static InputStream getCompositeInput(Map frameworkConfig, Map compositeManifest) throws IOException {
- // use an in memory stream to store the content
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- // the composite bundles only consist of a manifest describing the packages they import and export
- // and a framework config properties file
- Manifest manifest = CompositeHelper.getCompositeManifest(compositeManifest);
- JarOutputStream jarOut = new JarOutputStream(bytesOut, manifest);
- try {
- // store the framework config
- Properties fwProps = new Properties();
- if (frameworkConfig != null)
- fwProps.putAll(frameworkConfig);
- JarEntry entry = new JarEntry(CompositeImpl.COMPOSITE_CONFIGURATION);
- jarOut.putNextEntry(entry);
- fwProps.store(jarOut, null);
- jarOut.closeEntry();
- jarOut.flush();
- } finally {
- try {
- jarOut.close();
- } catch (IOException e) {
- // nothing
- }
- }
- return new ByteArrayInputStream(bytesOut.toByteArray());
- }
-
- static InputStream getSurrogateInput(Dictionary compositeManifest, BundleDescription compositeDesc, ExportPackageDescription[] matchingExports) throws IOException {
- // use an in memory stream to store the content
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- Manifest manifest = CompositeHelper.getSurrogateManifest(compositeManifest, compositeDesc, matchingExports);
- JarOutputStream jarOut = new JarOutputStream(bytesOut, manifest);
- jarOut.flush();
- jarOut.close();
- return new ByteArrayInputStream(bytesOut.toByteArray());
- }
-
- private static void addImports(Attributes attrigutes, BundleDescription compositeDesc, ExportPackageDescription[] matchingExports) {
- ExportPackageDescription[] exports = compositeDesc.getExportPackages();
- List systemExports = getSystemExports(matchingExports);
- if (exports.length == 0 && systemExports.size() == 0)
- return;
- StringBuffer importStatement = new StringBuffer();
- Collection importedNames = new ArrayList(exports.length);
- int i = 0;
- for (; i < exports.length; i++) {
- if (i != 0)
- importStatement.append(',');
- importedNames.add(exports[i].getName());
- getImportFrom(exports[i], importStatement);
- }
- for (Iterator iSystemExports = systemExports.iterator(); iSystemExports.hasNext();) {
- ExportPackageDescription systemExport = (ExportPackageDescription) iSystemExports.next();
- if (!importedNames.contains(systemExport.getName())) {
- if (i != 0)
- importStatement.append(',');
- i++;
- importStatement.append(systemExport.getName()).append(ELEMENT_SEPARATOR).append(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE).append('=').append(Constants.SYSTEM_BUNDLE_SYMBOLICNAME);
- }
- }
- attrigutes.putValue(Constants.IMPORT_PACKAGE, importStatement.toString());
- }
-
- private static List getSystemExports(ExportPackageDescription[] matchingExports) {
- ArrayList list = null;
- for (int i = 0; i < matchingExports.length; i++) {
- if (matchingExports[i].getExporter().getBundleId() != 0)
- continue;
- if (list == null)
- list = new ArrayList();
- list.add(matchingExports[i]);
- }
- return list == null ? Collections.EMPTY_LIST : list;
- }
-
- private static void getImportFrom(ExportPackageDescription export, StringBuffer importStatement) {
- importStatement.append(export.getName()).append(ELEMENT_SEPARATOR);
- Version version = export.getVersion();
- importStatement.append(Constants.VERSION_ATTRIBUTE).append(EQUALS_QUOTE).append('[').append(version).append(',').append(new Version(version.getMajor(), version.getMinor(), version.getMicro() + 1)).append(')').append('\"');
- addMap(importStatement, export.getAttributes(), "="); //$NON-NLS-1$
- }
-
- private static void addExports(Attributes attributes, BundleDescription compositeDesc, ExportPackageDescription[] matchingExports) {
- if (matchingExports.length == 0)
- return;
- StringBuffer exportStatement = new StringBuffer();
- for (int i = 0; i < matchingExports.length; i++) {
- if (matchingExports[i].getExporter() == compositeDesc) {
- // the matching export from outside is the composite bundle itself
- // this must be one of our own substitutable exports, it must be ignored (bug 345640)
- continue;
- }
- if (exportStatement.length() > 0)
- exportStatement.append(',');
- getExportFrom(matchingExports[i], exportStatement);
- }
- if (exportStatement.length() > 0)
- attributes.putValue(Constants.EXPORT_PACKAGE, exportStatement.toString());
- }
-
- private static void getExportFrom(ExportPackageDescription export, StringBuffer exportStatement) {
- exportStatement.append(export.getName()).append(ELEMENT_SEPARATOR);
- exportStatement.append(Constants.VERSION_ATTRIBUTE).append(EQUALS_QUOTE).append(export.getVersion()).append('\"');
- addMap(exportStatement, export.getDirectives(), ":="); //$NON-NLS-1$
- addMap(exportStatement, export.getAttributes(), "="); //$NON-NLS-1$
- }
-
- private static void addMap(StringBuffer manifest, Map values, String assignment) {
- if (values == null)
- return; // nothing to add
- for (Iterator iEntries = values.entrySet().iterator(); iEntries.hasNext();) {
- manifest.append(ELEMENT_SEPARATOR);
- Map.Entry entry = (Entry) iEntries.next();
- manifest.append(entry.getKey()).append(assignment).append('\"');
- Object value = entry.getValue();
- if (value instanceof String[]) {
- String[] strings = (String[]) value;
- for (int i = 0; i < strings.length; i++) {
- if (i != 0)
- manifest.append(',');
- manifest.append(strings[i]);
- }
- } else {
- manifest.append(value);
- }
- manifest.append('\"');
- }
- }
-
- static void setCompositePermissions(String bundleLocation, BundleContext systemContext) {
- ServiceReference ref = systemContext.getServiceReference(PermissionAdmin.class.getName());
- PermissionAdmin permAdmin = (PermissionAdmin) (ref == null ? null : systemContext.getService(ref));
- if (permAdmin == null)
- throw new RuntimeException("No Permission Admin service is available"); //$NON-NLS-1$
- try {
- permAdmin.setPermissions(bundleLocation, COMPOSITE_PERMISSIONS);
- } finally {
- systemContext.ungetService(ref);
- }
- }
-
- static void setDisabled(boolean disable, Bundle bundle, BundleContext systemContext) {
- ServiceReference ref = systemContext.getServiceReference(PlatformAdmin.class.getName());
- PlatformAdmin pa = (PlatformAdmin) (ref == null ? null : systemContext.getService(ref));
- if (pa == null)
- throw new RuntimeException("No Platform Admin service is available."); //$NON-NLS-1$
- try {
- State state = pa.getState(false);
- BundleDescription desc = state.getBundle(bundle.getBundleId());
- setDisabled(disable, desc);
- } finally {
- systemContext.ungetService(ref);
- }
- }
-
- static void setDisabled(boolean disable, BundleDescription bundle) {
- State state = bundle.getContainingState();
- if (disable) {
- state.addDisabledInfo(new DisabledInfo(COMPOSITE_POLICY, "Composite companion bundle is not resolved.", bundle)); //$NON-NLS-1$
- } else {
- DisabledInfo toRemove = state.getDisabledInfo(bundle, COMPOSITE_POLICY);
- if (toRemove != null)
- state.removeDisabledInfo(toRemove);
- }
- }
-
- static void validateCompositeManifest(Map compositeManifest) throws BundleException {
- if (compositeManifest == null)
- throw new BundleException("The composite manifest cannot be null.", BundleException.MANIFEST_ERROR); //$NON-NLS-1$
- // check for symbolic name
- if (compositeManifest.get(Constants.BUNDLE_SYMBOLICNAME) == null)
- throw new BundleException("The composite manifest must contain a Bundle-SymbolicName header.", BundleException.MANIFEST_ERROR); //$NON-NLS-1$
- // check for invalid manifests headers
- for (int i = 0; i < INVALID_COMPOSITE_HEADERS.length; i++)
- if (compositeManifest.get(INVALID_COMPOSITE_HEADERS[i]) != null)
- throw new BundleException("The composite manifest must not contain the header " + INVALID_COMPOSITE_HEADERS[i], BundleException.MANIFEST_ERROR); //$NON-NLS-1$
- // validate manifest version
- String manifestVersion = (String) compositeManifest.get(Constants.BUNDLE_MANIFESTVERSION);
- if (manifestVersion == null) {
- compositeManifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); //$NON-NLS-1$
- } else {
- try {
- Integer parsed = Integer.valueOf(manifestVersion);
- if (parsed.intValue() > 2 || parsed.intValue() < 2)
- throw new BundleException("Invalid Bundle-ManifestVersion: " + manifestVersion); //$NON-NLS-1$
- } catch (NumberFormatException e) {
- throw new BundleException("Invalid Bundle-ManifestVersion: " + manifestVersion); //$NON-NLS-1$
- }
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeImpl.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeImpl.java
deleted file mode 100644
index 021ee9e5a..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeImpl.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import java.io.*;
-import java.net.URL;
-import java.util.Map;
-import java.util.Properties;
-import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
-import org.eclipse.osgi.launch.Equinox;
-import org.eclipse.osgi.service.internal.composite.CompositeModule;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.ExportPackageDescription;
-import org.osgi.framework.*;
-import org.osgi.framework.launch.Framework;
-import org.osgi.service.framework.*;
-
-public class CompositeImpl extends CompositeBase implements CompositeBundle {
- private static String COMPOSITE_STORAGE = "store"; //$NON-NLS-1$
- public static String COMPOSITE_CONFIGURATION = "compositeConfig.properties"; //$NON-NLS-1$
-
- private final ServiceTrackerManager trackerManager = new ServiceTrackerManager();
-
- public CompositeImpl(BundleData bundledata, org.eclipse.osgi.framework.internal.core.Framework framework) throws BundleException {
- super(bundledata, framework);
- }
-
- protected Framework findCompanionFramework(org.eclipse.osgi.framework.internal.core.Framework thisFramework, BundleData thisData) throws BundleException {
- // allocate storage area for the composite framework
- File compositeStorage = thisData.getDataFile(COMPOSITE_STORAGE);
- boolean firstTime = false;
- if (!compositeStorage.exists())
- // the child storage area has not been allocated; this is the first time
- firstTime = true;
- // find the configuration properties
- URL childConfig = bundledata.getEntry(COMPOSITE_CONFIGURATION);
- Properties props = new Properties();
- try {
- props.load(childConfig.openStream());
- } catch (IOException e) {
- throw new BundleException("Could not load child configuration", e); //$NON-NLS-1$
- }
- props.put(Constants.FRAMEWORK_STORAGE, compositeStorage.getAbsolutePath());
- // save the parent framework so the parent companion bundle can find it
- props.put(PROP_PARENTFRAMEWORK, thisFramework.getSystemBundleContext().getBundle());
- // TODO leaks "this" out of the constructor
- props.put(PROP_COMPOSITE, this);
- Equinox equinox = new Equinox((Map) props);
- if (!firstTime)
- // if not the first time then we are done
- return equinox;
- equinox.init();
- installSurrogate(equinox.getBundleContext(), thisData);
- return equinox;
- }
-
- private void installSurrogate(BundleContext companionContext, BundleData thisData) throws BundleException {
- Bundle surrogate;
- try {
- InputStream surrogateContent = CompositeHelper.getSurrogateInput(thisData.getManifest(), null, null);
- surrogate = companionContext.installBundle(thisData.getLocation(), surrogateContent);
- } catch (IOException e) {
- throw new BundleException("Error installing parent companion composite bundle", e); //$NON-NLS-1$
- }
- // disable the surrogate initially since we know we have not resolved the composite yet.
- CompositeHelper.setDisabled(true, surrogate, companionContext);
- // set the permissions of the surrogate bundle
- CompositeHelper.setCompositePermissions(thisData.getLocation(), companionContext);
- }
-
- private boolean updateSurrogate(BundleData thisData, BundleDescription child, ExportPackageDescription[] matchingExports) throws BundleException {
- // update the surrogate content with the matching exports provided by the composite
- InputStream surrogateContent;
- try {
- surrogateContent = CompositeHelper.getSurrogateInput(thisData.getManifest(), child, matchingExports);
- } catch (IOException e) {
- throw new BundleException("Error updating surrogate bundle.", e); //$NON-NLS-1$
- }
- CompositeModule surrogateComposite = (CompositeModule) getSurrogateBundle();
- surrogateComposite.updateContent(surrogateContent);
- // enable/disable the surrogate composite based on if we have exports handed to us
- boolean disable = matchingExports == null ? true : false;
- CompositeHelper.setDisabled(disable, getSurrogateBundle(), getCompositeFramework().getBundleContext());
- // return true if we can resolve the surrogate bundle
- return disable ? false : surrogateComposite.resolveContent();
- }
-
- public Framework getCompositeFramework() {
- if ((getState() & Bundle.UNINSTALLED) == 0) {
- if ((companionFramework.getState() & (Bundle.INSTALLED | Bundle.RESOLVED)) != 0)
- try {
- companionFramework.init();
- } catch (BundleException e) {
- throw new RuntimeException("Cannot initialize child framework.", e);
- }
- }
- return companionFramework;
- }
-
- public SurrogateBundle getSurrogateBundle() {
- return (SurrogateBundle) getCompanionBundle();
- }
-
- protected Bundle getCompanionBundle() {
- return getCompositeFramework().getBundleContext().getBundle(1);
- }
-
- public void update(Map compositeManifest) throws BundleException {
- // validate the composite manifest
- CompositeHelper.validateCompositeManifest(compositeManifest);
- if (isResolved()) {
- // force the class loader creation before updating the surrogate to cache the current state
- // this is to allow for lazy updates of composite bundles
- BundleLoader loader = getBundleLoader();
- if (loader != null)
- loader.createClassLoader();
- }
- try {
- Map frameworkConfig = getFrameworkConfig();
- // first update the parent companion and disable it
- updateSurrogate(getBundleData(), null, null);
- // update the content with the new manifest
- updateContent(CompositeHelper.getCompositeInput(frameworkConfig, compositeManifest));
- } catch (IOException e) {
- throw new BundleException("Error updating composite.", e); //$NON-NLS-1$
- }
- }
-
- private Map getFrameworkConfig() throws IOException {
- Properties result = new Properties();
- URL config = getEntry(COMPOSITE_CONFIGURATION);
- result.load(config.openStream());
- return result;
- }
-
- public void uninstall() throws BundleException {
- // ensure class loader is created if needed
- checkClassLoader();
- // stop first before stopping the child to let the service listener clean up
- stop(Bundle.STOP_TRANSIENT);
- stopChildFramework();
- super.uninstall();
- }
-
- private void checkClassLoader() {
- BundleLoaderProxy proxy = getLoaderProxy();
- if (proxy != null && proxy.inUse() && proxy.getBundleLoader() != null) {
- BundleClassLoader loader = proxy.getBundleLoader().createClassLoader();
- loader.getResource("dummy"); //$NON-NLS-1$
- }
- }
-
- protected void startHook() throws BundleException {
- // always start the child framework
- companionFramework.start();
- trackerManager.startedComposite();
- }
-
- protected void stopHook() throws BundleException {
- // bug 363561; need to make sure the class loader is created
- // before stopping the composite framework
- try {
- checkClassLoader();
- } catch (Throwable t) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, t);
- }
- trackerManager.stoppedComposite();
- // do not stop the framework unless we are persistently stopped
- if ((bundledata.getStatus() & Constants.BUNDLE_STARTED) == 0)
- stopChildFramework();
- }
-
- public void started(CompositeModule surrogate) {
- if (surrogate == getSurrogateBundle())
- trackerManager.startedSurrogate();
- }
-
- public void stopped(CompositeModule surrogate) {
- if (surrogate == getSurrogateBundle())
- trackerManager.stoppedSurrogate();
- }
-
- private void stopChildFramework() throws BundleException {
- companionFramework.stop();
- try {
- FrameworkEvent stopped = companionFramework.waitForStop(30000);
- switch (stopped.getType()) {
- case FrameworkEvent.ERROR :
- throw new BundleException("Error stopping the child framework.", stopped.getThrowable()); //$NON-NLS-1$
- case FrameworkEvent.WAIT_TIMEDOUT :
- throw new BundleException("Timed out waiting for the child framework to stop."); //$NON-NLS-1$
- case FrameworkEvent.STOPPED :
- // normal stop, just return
- return;
- default :
- throw new BundleException("Unexpected code returned when stopping the child framework:" + stopped.getType()); //$NON-NLS-1$
- }
- } catch (InterruptedException e) {
- throw new BundleException("Error stopping child framework", e); //$NON-NLS-1$
- }
- }
-
- public boolean giveExports(ExportPackageDescription[] matchingExports) {
- if (matchingExports == null) {
- SurrogateBundle surrogate = getSurrogateBundle();
- // disable the surrogate
- CompositeHelper.setDisabled(true, getSurrogateBundle(), getCompositeFramework().getBundleContext());
- // refresh the surrogate synchronously
- ((CompositeModule) surrogate).refreshContent();
- return true;
- }
- try {
- return updateSurrogate(getBundleData(), getBundleDescription(), matchingExports);
- } catch (BundleException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- }
-
- /*
- * Listens to source and target bundles and source and target framework changes
- */
- class ServiceTrackerManager {
- static final int COMPOSITE_ACTIVE = 0x01;
- static final int SURROGATE_ACTIVE = 0x02;
- // @GuardedBy(this)
- private int bundlesActive = 0;
- // @GuardedBy(this)
- private CompositeServiceTracker shareToChildServices;
- // @GuardedBy(this)
- private CompositeServiceTracker shareToParentServices;
-
- void startedComposite() throws BundleException {
- open(COMPOSITE_ACTIVE);
- getSurrogateBundle().start(Bundle.START_TRANSIENT);
- }
-
- void startedSurrogate() {
- open(SURROGATE_ACTIVE);
- }
-
- void stoppedComposite() {
- try {
- getSurrogateBundle().stop(Bundle.STOP_TRANSIENT);
- } catch (BundleException e) {
- // nothing
- } catch (IllegalStateException e) {
- // child framework must have been stoped
- }
- close(COMPOSITE_ACTIVE);
- }
-
- void stoppedSurrogate() {
- close(SURROGATE_ACTIVE);
- }
-
- private synchronized void open(int bundleActive) {
- bundlesActive |= bundleActive;
- if ((bundlesActive & (COMPOSITE_ACTIVE | SURROGATE_ACTIVE)) != (COMPOSITE_ACTIVE | SURROGATE_ACTIVE))
- return;
- // create a service tracker to track and share services from the parent framework
- shareToChildServices = new CompositeServiceTracker(getBundleContext(), getSurrogateBundle().getBundleContext(), (String) getBundleContext().getBundle().getHeaders("").get(CompositeBundleFactory.COMPOSITE_SERVICE_FILTER_IMPORT)); //$NON-NLS-1$
- shareToChildServices.open();
- // create a service tracker to track and share services from the child framework
- shareToParentServices = new CompositeServiceTracker(getSurrogateBundle().getBundleContext(), getBundleContext(), (String) getBundleContext().getBundle().getHeaders("").get(CompositeBundleFactory.COMPOSITE_SERVICE_FILTER_EXPORT)); //$NON-NLS-1$
- shareToParentServices.open();
-
- }
-
- private synchronized void close(int bundleStopped) {
- bundlesActive ^= bundleStopped;
- // close the service tracker to stop tracking and sharing services
- if (shareToChildServices != null)
- shareToChildServices.close();
- if (shareToParentServices != null)
- shareToParentServices.close();
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java
deleted file mode 100644
index a9a449b40..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import java.util.*;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.*;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-class CompositeServiceTracker implements ServiceTrackerCustomizer {
- final BundleContext sourceContext;
- final BundleContext targetContext;
- final ServiceTracker[] trackers;
- final String[] filters;
- /* @GuardedBy("serviceComposites") */
- final HashMap serviceComposites = new HashMap();
-
- public CompositeServiceTracker(BundleContext sourceContext, BundleContext targetContext, String serviceFilters) {
- this.sourceContext = sourceContext;
- this.targetContext = targetContext;
- filters = ManifestElement.getArrayFromList(serviceFilters, ","); //$NON-NLS-1$
- trackers = new ServiceTracker[filters.length];
- }
-
- synchronized void open() {
- for (int i = 0; i < trackers.length; i++) {
- try {
- trackers[i] = new ServiceTracker(sourceContext, sourceContext.createFilter(filters[i]), this);
- trackers[i].open();
- } catch (InvalidSyntaxException e) {
- // TODO log
- // we will skip this filter; note that trackers may have null entries
- }
- }
- }
-
- synchronized void close() {
- for (int i = 0; i < trackers.length; i++) {
- if (trackers[i] != null)
- trackers[i].close();
- }
- }
-
- public Object addingService(ServiceReference reference) {
- ServiceLink serviceLink;
- int useCount;
- synchronized (serviceComposites) {
- serviceLink = (ServiceLink) serviceComposites.get(reference);
- if (serviceLink == null) {
- serviceLink = new ServiceLink(reference);
- serviceComposites.put(reference, serviceLink);
- }
- useCount = serviceLink.incrementUse();
- }
- // register service outside of the sync block
- if (useCount == 1)
- serviceLink.register();
- return serviceLink;
- }
-
- public void modifiedService(ServiceReference reference, Object service) {
- ServiceLink serviceLink = (ServiceLink) service;
- Dictionary serviceProps = null;
- synchronized (serviceComposites) {
- serviceProps = serviceLink.getRefreshProperties();
- }
- // set service properties out side the sync block
- if (serviceProps != null)
- ((ServiceLink) service).setServiceProperties(serviceProps);
- }
-
- public void removedService(ServiceReference reference, Object service) {
- int useCount;
- synchronized (serviceComposites) {
- useCount = ((ServiceLink) service).decrementUse();
- if (useCount == 0)
- serviceComposites.remove(reference);
- }
- // unregister outside the sync block
- if (useCount == 0)
- ((ServiceLink) service).unregister();
- }
-
- class ServiceLink implements ServiceFactory {
- private final ServiceReference reference;
- private volatile ServiceRegistration registration;
- /* @GuardedBy("this") */
- private Object service;
- /* @GuardedBy("serviceLinks") */
- private int useCount;
-
- ServiceLink(ServiceReference reference) {
- this.reference = reference;
- }
-
- /* @GuardedBy("serviceLinks") */
- Dictionary getRefreshProperties() {
- Dictionary result = getServiceProperties();
- if (useCount <= 1)
- return result;
- // need to do an expensive properties check to avoid multiple registration property changes
- String[] originalKeys = registration.getReference().getPropertyKeys();
- for (int i = 0; i < originalKeys.length; i++) {
- if (!Constants.OBJECTCLASS.equals(originalKeys[i]) && !Constants.SERVICE_ID.equals(originalKeys[i]))
- // identity compare is done on purpose here to catch any kind of change
- if (registration.getReference().getProperty(originalKeys[i]) != result.get(originalKeys[i]))
- return result;
- }
- for (Enumeration eKeys = result.keys(); eKeys.hasMoreElements();) {
- String key = (String) eKeys.nextElement();
- if (!Constants.OBJECTCLASS.equals(key) && !Constants.SERVICE_ID.equals(key))
- // identity compare is done on purpose here to catch any kind of change
- if (result.get(key) != registration.getReference().getProperty(key))
- return result;
- }
- return null;
- }
-
- /* @GuardedBy("serviceLinks") */
- int decrementUse() {
- return --useCount;
- }
-
- /* @GuardedBy("serviceLinks") */
- int incrementUse() {
- return ++useCount;
- }
-
- /* @GuardedBy("serviceLinks") */
- int getUse() {
- return useCount;
- }
-
- void setServiceProperties(Dictionary props) {
- ServiceRegistration current = registration;
- if (current != null)
- current.setProperties(props);
- }
-
- void register() {
- Dictionary props = getServiceProperties();
- registration = targetContext.registerService((String[]) props.get(Constants.OBJECTCLASS), this, props);
- }
-
- void unregister() {
- ServiceRegistration current = registration;
- if (current != null)
- current.unregister();
- }
-
- private Dictionary getServiceProperties() {
- String[] keys = reference.getPropertyKeys();
- Hashtable serviceProps = new Hashtable(keys.length);
- for (int i = 0; i < keys.length; i++)
- serviceProps.put(keys[i], reference.getProperty(keys[i]));
- return serviceProps;
- }
-
- public synchronized Object getService(Bundle bundle, ServiceRegistration reg) {
- if (service == null)
- service = sourceContext.getService(reference);
- return service;
- }
-
- public void ungetService(Bundle bundle, ServiceRegistration reg, Object serv) {
- // nothing
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/SurrogateImpl.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/SurrogateImpl.java
deleted file mode 100644
index 47f58ad62..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/SurrogateImpl.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.composite;
-
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.internal.module.ResolverBundle;
-import org.eclipse.osgi.service.internal.composite.CompositeModule;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.ExportPackageDescription;
-import org.osgi.framework.*;
-import org.osgi.framework.launch.Framework;
-import org.osgi.service.framework.CompositeBundle;
-import org.osgi.service.framework.SurrogateBundle;
-
-public class SurrogateImpl extends CompositeBase implements SurrogateBundle {
-
- private final CompositeBundle composite;
-
- public SurrogateImpl(BundleData bundledata, org.eclipse.osgi.framework.internal.core.Framework framework) throws BundleException {
- super(bundledata, framework);
- this.composite = (CompositeBundle) FrameworkProperties.getProperties().get(PROP_COMPOSITE);
- }
-
- protected Framework findCompanionFramework(org.eclipse.osgi.framework.internal.core.Framework thisFramework, BundleData thisData) {
- // just get the property which was set when creating the child framework
- return (Framework) FrameworkProperties.getProperties().get(PROP_PARENTFRAMEWORK);
- }
-
- public BundleContext getCompositeBundleContext() {
- return composite.getBundleContext();
- }
-
- protected Bundle getCompanionBundle() {
- return composite;
- }
-
- protected boolean isSurrogate() {
- return true;
- }
-
- public boolean giveExports(ExportPackageDescription[] matchingExports) {
- // only allow the surrogate resolution to occur if we are in the middle of resolving the composite
- if (resolving.get() == null)
- return false;
- if (matchingExports == null) {
- // set the surrogate to disabled to prevent resolution this go around
- CompositeHelper.setDisabled(true, getBundleDescription());
- return true;
- }
- return validExports(matchingExports);
- }
-
- private boolean validExports(ExportPackageDescription[] matchingExports) {
- // make sure each matching exports matches the export signature of the composite
- CompositeModule composite = (CompositeModule) getCompanionBundle();
- BundleDescription childDesc = composite.getCompositeDescription();
- ExportPackageDescription[] childExports = childDesc.getExportPackages();
- for (int i = 0; i < matchingExports.length; i++) {
- for (int j = 0; j < childExports.length; j++) {
- if (matchingExports[i].getName().equals(childExports[j].getName())) {
- if (!validateExport(matchingExports[i], childExports[j]))
- return false;
- continue;
- }
- }
- }
- return true;
- }
-
- private boolean validateExport(ExportPackageDescription matchingExport, ExportPackageDescription childExport) {
- Version matchingVersion = matchingExport.getVersion();
- Version childVersion = childExport.getVersion();
- if (!childVersion.equals(Version.emptyVersion) && !matchingVersion.equals(childVersion))
- return false;
- if (!ResolverBundle.equivalentMaps(childExport.getAttributes(), matchingExport.getAttributes(), false))
- return false;
- if (!ResolverBundle.equivalentMaps(childExport.getDirectives(), matchingExport.getDirectives(), false))
- return false;
- return true;
- }
-
- protected void startHook() {
- ((CompositeModule) getCompanionBundle()).started(this);
- }
-
- protected void stopHook() {
- ((CompositeModule) getCompanionBundle()).stopped(this);
- }
-
- public void uninstall() throws BundleException {
- throw new BundleException("Cannot uninstall surrogate bundles", BundleException.INVALID_OPERATION); //$NON-NLS-1$
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/service/internal/composite/CompositeModule.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/service/internal/composite/CompositeModule.java
deleted file mode 100644
index 2d971053f..000000000
--- a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/service/internal/composite/CompositeModule.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.service.internal.composite;
-
-import java.io.InputStream;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.osgi.framework.BundleException;
-
-/**
- * An internal interface only used by the composite implementation
- *
- * @noextend This interface is not intended to be extended by clients.
- * @noimplement This interface is not intended to be implemented by clients.
- */
-public interface CompositeModule {
- public void updateContent(InputStream content) throws BundleException;
-
- public void refreshContent();
-
- public boolean resolveContent();
-
- public BundleDescription getCompositeDescription();
-
- public ClassLoaderDelegate getDelegate();
-
- public void started(CompositeModule compositeBundle);
-
- public void stopped(CompositeModule compositeBundle);
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/event/BatchBundleListener.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/event/BatchBundleListener.java
deleted file mode 100644
index a8dd74a8a..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/event/BatchBundleListener.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.event;
-
-import org.osgi.framework.*;
-
-/**
- * A batch <code>BundleEvent</code> listener.
- *
- * <p>
- * <code>BatchBundleListener</code> is a listener interface that may be
- * implemented by a bundle developer.
- * <p>
- * A <code>BatchBundleListener</code> object is registered with the
- * Framework using the {@link BundleContext#addBundleListener} method.
- * <code>BatchBundleListener</code> objects are called with a
- * <code>BundleEvent</code> object when a bundle has been installed, resolved,
- * started, stopped, updated, unresolved, or uninstalled.
- * <p>
- * A <code>BatchBundleListener</code> acts like a <code>BundleListener</code>
- * except the framework will call the {@link #batchBegin()} method at the beginning
- * of a batch process and call the {@link #batchEnd()} at the end of a batch
- * process. For example, the framework may notify a <code>BatchBundleListener</code>
- * of a batching process during a refresh packages operation or a resolve bundles
- * operation.
- * <p>
- * During a batching operation the framework will continue to deliver any events using
- * the {@link BundleListener#bundleChanged(BundleEvent)} method to the
- * <code>BatchBundleListener</code>. It is the responsiblity of the
- * <code>BatchBundleListener</code> to decide how to handle events when a
- * batching operation is in progress.
- * <p>
- * Note that the framework does not guarantee that batching operations will not
- * overlap. This can result in the method {@link #batchBegin()} being called
- * multiple times before the first {@link #batchEnd()} is called.
- *
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- * @see BundleEvent
- * @see BundleListener
- */
-public interface BatchBundleListener extends BundleListener {
- /**
- * Indicates that a batching process has begun.
- */
- public abstract void batchBegin();
-
- /**
- * Indicates that a batching process has ended.
- */
- public abstract void batchEnd();
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java
deleted file mode 100644
index 1cf9e943f..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java
+++ /dev/null
@@ -1,1551 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.*;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.util.KeyedElement;
-import org.eclipse.osgi.internal.composite.CompositeImpl;
-import org.eclipse.osgi.internal.composite.SurrogateImpl;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.ResolverError;
-import org.eclipse.osgi.signedcontent.*;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.framework.hooks.bundle.CollisionHook;
-import org.osgi.framework.startlevel.BundleStartLevel;
-import org.osgi.framework.wiring.*;
-
-/**
- * This object is given out to bundles and wraps the internal Bundle object. It
- * is destroyed when a bundle is uninstalled and reused if a bundle is updated.
- * This class is abstract and is extended by BundleHost and BundleFragment.
- */
-public abstract class AbstractBundle implements Bundle, Comparable<Bundle>, KeyedElement, BundleStartLevel, BundleReference, BundleRevisions {
- private final static long STATE_CHANGE_TIMEOUT;
- static {
- long stateChangeWait = 5000;
- try {
- String prop = FrameworkProperties.getProperty("equinox.statechange.timeout"); //$NON-NLS-1$
- if (prop != null)
- stateChangeWait = Long.parseLong(prop);
- } catch (Throwable t) {
- // use default 5000
- stateChangeWait = 5000;
- }
- STATE_CHANGE_TIMEOUT = stateChangeWait;
- }
- /** The Framework this bundle is part of */
- protected final Framework framework;
- /** The state of the bundle. */
- protected volatile int state;
- /** A flag to denote whether a bundle state change is in progress */
- protected volatile Thread stateChanging;
- /** Bundle's BundleData object */
- protected BundleData bundledata;
- /** Internal object used for state change synchronization */
- protected final Object statechangeLock = new Object();
- /** ProtectionDomain for the bundle */
- protected BundleProtectionDomain domain;
-
- volatile protected ManifestLocalization manifestLocalization = null;
-
- /**
- * Bundle object constructor. This constructor should not perform any real
- * work.
- *
- * @param bundledata
- * BundleData for this bundle
- * @param framework
- * Framework this bundle is running in
- */
- protected static AbstractBundle createBundle(BundleData bundledata, Framework framework, boolean setBundle) throws BundleException {
- AbstractBundle result;
- if ((bundledata.getType() & BundleData.TYPE_FRAGMENT) > 0)
- result = new BundleFragment(bundledata, framework);
- else if ((bundledata.getType() & BundleData.TYPE_COMPOSITEBUNDLE) > 0)
- result = new CompositeImpl(bundledata, framework);
- else if ((bundledata.getType() & BundleData.TYPE_SURROGATEBUNDLE) > 0)
- result = new SurrogateImpl(bundledata, framework);
- else
- result = new BundleHost(bundledata, framework);
- if (setBundle)
- bundledata.setBundle(result);
- return result;
- }
-
- /**
- * Bundle object constructor. This constructor should not perform any real
- * work.
- *
- * @param bundledata
- * BundleData for this bundle
- * @param framework
- * Framework this bundle is running in
- */
- protected AbstractBundle(BundleData bundledata, Framework framework) {
- state = INSTALLED;
- stateChanging = null;
- this.bundledata = bundledata;
- this.framework = framework;
- }
-
- /**
- * Load the bundle.
- */
- protected abstract void load();
-
- /**
- * Reload from a new bundle. This method must be called while holding the
- * bundles lock.
- *
- * @param newBundle
- * Dummy Bundle which contains new data.
- * @return true if an exported package is "in use". i.e. it has been
- * imported by a bundle
- */
- protected abstract boolean reload(AbstractBundle newBundle);
-
- /**
- * Refresh the bundle. This is called by Framework.refreshPackages. This
- * method must be called while holding the bundles lock.
- * this.loader.unimportPackages must have already been called before
- * calling this method!
- */
- protected abstract void refresh();
-
- /**
- * Unload the bundle. This method must be called while holding the bundles
- * lock.
- *
- * @return true if an exported package is "in use". i.e. it has been
- * imported by a bundle
- */
- protected abstract boolean unload();
-
- /**
- * Close the the Bundle's file.
- *
- */
- protected void close() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (INSTALLED)) == 0) {
- Debug.println("Bundle.close called when state != INSTALLED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
- state = UNINSTALLED;
- }
-
- /**
- * Load and instantiate bundle's BundleActivator class
- */
- protected BundleActivator loadBundleActivator() throws BundleException {
- /* load Bundle's BundleActivator if it has one */
- String activatorClassName = bundledata.getActivator();
- if (activatorClassName != null) {
- try {
- Class<?> activatorClass = loadClass(activatorClassName, false);
- /* Create the activator for the bundle */
- return (BundleActivator) (activatorClass.newInstance());
- } catch (Throwable t) {
- if (Debug.DEBUG_GENERAL) {
- Debug.printStackTrace(t);
- }
- throw new BundleException(NLS.bind(Msg.BUNDLE_INVALID_ACTIVATOR_EXCEPTION, activatorClassName, bundledata.getSymbolicName()), BundleException.ACTIVATOR_ERROR, t);
- }
- }
- return (null);
- }
-
- /**
- * This method loads a class from the bundle.
- *
- * @param name
- * the name of the desired Class.
- * @param checkPermission
- * indicates whether a permission check should be done.
- * @return the resulting Class
- * @exception java.lang.ClassNotFoundException
- * if the class definition was not found.
- */
- protected abstract Class<?> loadClass(String name, boolean checkPermission) throws ClassNotFoundException;
-
- /**
- * Returns the current state of the bundle.
- *
- * A bundle can only be in one state at any time.
- *
- * @return bundle's state.
- */
- public int getState() {
- return (state);
- }
-
- public Framework getFramework() {
- return framework;
- }
-
- /**
- * Return true if the bundle is starting or active.
- *
- */
- protected boolean isActive() {
- return ((state & (ACTIVE | STARTING)) != 0);
- }
-
- boolean isLazyStart() {
- int status = bundledata.getStatus();
- return (status & Constants.BUNDLE_ACTIVATION_POLICY) != 0 && (status & Constants.BUNDLE_LAZY_START) != 0;
- }
-
- /**
- * Return true if the bundle is resolved.
- *
- */
- public boolean isResolved() {
- return (state & (INSTALLED | UNINSTALLED)) == 0;
- }
-
- /**
- * Start this bundle.
- *
- * If the current start level is less than this bundle's start level, then
- * the Framework must persistently mark this bundle as started and delay
- * the starting of this bundle until the Framework's current start level
- * becomes equal or more than the bundle's start level.
- * <p>
- * Otherwise, the following steps are required to start a bundle:
- * <ol>
- * <li>If the bundle is {@link #UNINSTALLED}then an <code>IllegalStateException</code>
- * is thrown.
- * <li>If the bundle is {@link #ACTIVE}or {@link #STARTING}then this
- * method returns immediately.
- * <li>If the bundle is {@link #STOPPING}then this method may wait for
- * the bundle to return to the {@link #RESOLVED}state before continuing.
- * If this does not occur in a reasonable time, a {@link BundleException}
- * is thrown to indicate the bundle was unable to be started.
- * <li>If the bundle is not {@link #RESOLVED}, an attempt is made to
- * resolve the bundle. If the bundle cannot be resolved, a
- * {@link BundleException}is thrown.
- * <li>The state of the bundle is set to {@link #STARTING}.
- * <li>The {@link BundleActivator#start(BundleContext) start}method of the bundle's
- * {@link BundleActivator}, if one is specified, is called. If the
- * {@link BundleActivator}is invalid or throws an exception, the state of
- * the bundle is set back to {@link #RESOLVED}, the bundle's listeners, if
- * any, are removed, service's registered by the bundle, if any, are
- * unregistered, and service's used by the bundle, if any, are released. A
- * {@link BundleException}is then thrown.
- * <li>It is recorded that this bundle has been started, so that when the
- * framework is restarted, this bundle will be automatically started.
- * <li>The state of the bundle is set to {@link #ACTIVE}.
- * <li>A {@link BundleEvent}of type {@link BundleEvent#STARTED}is
- * broadcast.
- * </ol>
- *
- * <h5>Preconditons</h5>
- * <ul>
- * <li>getState() in {{@link #INSTALLED},{@link #RESOLVED}}.
- * </ul>
- * <h5>Postconditons, no exceptions thrown</h5>
- * <ul>
- * <li>getState() in {{@link #ACTIVE}}.
- * <li>{@link BundleActivator#start(BundleContext) BundleActivator.start}has been called
- * and did not throw an exception.
- * </ul>
- * <h5>Postconditions, when an exception is thrown</h5>
- * <ul>
- * <li>getState() not in {{@link #STARTING},{@link #ACTIVE}}.
- * </ul>
- *
- * @exception BundleException
- * If the bundle couldn't be started. This could be because
- * a code dependency could not be resolved or the specified
- * BundleActivator could not be loaded or threw an
- * exception.
- * @exception java.lang.IllegalStateException
- * If the bundle has been uninstalled or the bundle tries to
- * change its own state.
- * @exception java.lang.SecurityException
- * If the caller does not have {@link AdminPermission}
- * permission and the Java runtime environment supports
- * permissions.
- */
- public void start() throws BundleException {
- start(0);
- }
-
- public void start(int options) throws BundleException {
- framework.checkAdminPermission(this, AdminPermission.EXECUTE);
- checkValid();
- beginStateChange();
- try {
- startWorker(options);
- } finally {
- completeStateChange();
- }
- }
-
- /**
- * Internal worker to start a bundle.
- *
- * @param options
- */
- protected abstract void startWorker(int options) throws BundleException;
-
- /**
- * This method does the following
- * <ol>
- * <li> Return false if the bundle is a fragment
- * <li> Return false if the bundle is not at the correct start-level
- * <li> Return false if the bundle is not persistently marked for start
- * <li> Return true if the bundle's activation policy is persistently ignored
- * <li> Return true if the bundle does not define an activation policy
- * <li> Transition to STARTING state and Fire LAZY_ACTIVATION event
- * <li> Return false
- * </ol>
- * @return true if the bundle should be resumed
- */
- protected boolean readyToResume() {
- return false;
- }
-
- /**
- * Start this bundle w/o marking is persistently started.
- *
- * <p>
- * The following steps are followed to start a bundle:
- * <ol>
- * <li>If the bundle is {@link #UNINSTALLED}then an <code>IllegalStateException</code>
- * is thrown.
- * <li>If the bundle is {@link #ACTIVE}or {@link #STARTING}then this
- * method returns immediately.
- * <li>If the bundle is {@link #STOPPING}then this method may wait for
- * the bundle to return to the {@link #RESOLVED}state before continuing.
- * If this does not occur in a reasonable time, a {@link BundleException}
- * is thrown to indicate the bundle was unable to be started.
- * <li>If the bundle is not {@link #RESOLVED}, an attempt is made to
- * resolve the bundle. If the bundle cannot be resolved, a
- * {@link BundleException}is thrown.
- * <li>The state of the bundle is set to {@link #STARTING}.
- * <li>The {@link BundleActivator#start(BundleContext) start}method of the bundle's
- * {@link BundleActivator}, if one is specified, is called. If the
- * {@link BundleActivator}is invalid or throws an exception, the state of
- * the bundle is set back to {@link #RESOLVED}, the bundle's listeners, if
- * any, are removed, service's registered by the bundle, if any, are
- * unregistered, and service's used by the bundle, if any, are released. A
- * {@link BundleException}is then thrown.
- * <li>The state of the bundle is set to {@link #ACTIVE}.
- * <li>A {@link BundleEvent}of type {@link BundleEvent#STARTED}is
- * broadcast.
- * </ol>
- *
- * <h5>Preconditons</h5>
- * <ul>
- * <li>getState() in {{@link #INSTALLED},{@link #RESOLVED}}.
- * </ul>
- * <h5>Postconditons, no exceptions thrown</h5>
- * <ul>
- * <li>getState() in {{@link #ACTIVE}}.
- * <li>{@link BundleActivator#start(BundleContext) BundleActivator.start}has been called
- * and did not throw an exception.
- * </ul>
- * <h5>Postconditions, when an exception is thrown</h5>
- * <ul>
- * <li>getState() not in {{@link #STARTING},{@link #ACTIVE}}.
- * </ul>
- *
- * @exception BundleException
- * If the bundle couldn't be started. This could be because
- * a code dependency could not be resolved or the specified
- * BundleActivator could not be loaded or threw an
- * exception.
- * @exception java.lang.IllegalStateException
- * If the bundle tries to change its own state.
- */
- protected void resume() throws BundleException {
- if (state == UNINSTALLED) {
- return;
- }
- beginStateChange();
- try {
- if (readyToResume())
- startWorker(START_TRANSIENT);
- } finally {
- completeStateChange();
- }
- }
-
- /**
- * Stop this bundle.
- *
- * Any services registered by this bundle will be unregistered. Any
- * services used by this bundle will be released. Any listeners registered
- * by this bundle will be removed.
- *
- * <p>
- * The following steps are followed to stop a bundle:
- * <ol>
- * <li>If the bundle is {@link #UNINSTALLED}then an <code>IllegalStateException</code>
- * is thrown.
- * <li>If the bundle is {@link #STOPPING},{@link #RESOLVED}, or
- * {@link #INSTALLED}then this method returns immediately.
- * <li>If the bundle is {@link #STARTING}then this method may wait for
- * the bundle to reach the {@link #ACTIVE}state before continuing. If this
- * does not occur in a reasonable time, a {@link BundleException}is thrown
- * to indicate the bundle was unable to be stopped.
- * <li>The state of the bundle is set to {@link #STOPPING}.
- * <li>It is recorded that this bundle has been stopped, so that when the
- * framework is restarted, this bundle will not be automatically started.
- * <li>The {@link BundleActivator#stop(BundleContext) stop}method of the bundle's
- * {@link BundleActivator}, if one is specified, is called. If the
- * {@link BundleActivator}throws an exception, this method will continue
- * to stop the bundle. A {@link BundleException}will be thrown after
- * completion of the remaining steps.
- * <li>The bundle's listeners, if any, are removed, service's registered
- * by the bundle, if any, are unregistered, and service's used by the
- * bundle, if any, are released.
- * <li>The state of the bundle is set to {@link #RESOLVED}.
- * <li>A {@link BundleEvent}of type {@link BundleEvent#STOPPED}is
- * broadcast.
- * </ol>
- *
- * <h5>Preconditons</h5>
- * <ul>
- * <li>getState() in {{@link #ACTIVE}}.
- * </ul>
- * <h5>Postconditons, no exceptions thrown</h5>
- * <ul>
- * <li>getState() not in {{@link #ACTIVE},{@link #STOPPING}}.
- * <li>{@link BundleActivator#stop(BundleContext) BundleActivator.stop}has been called
- * and did not throw an exception.
- * </ul>
- * <h5>Postconditions, when an exception is thrown</h5>
- * <ul>
- * <li>None.
- * </ul>
- *
- * @exception BundleException
- * If the bundle's BundleActivator could not be loaded or
- * threw an exception.
- * @exception java.lang.IllegalStateException
- * If the bundle has been uninstalled or the bundle tries to
- * change its own state.
- * @exception java.lang.SecurityException
- * If the caller does not have {@link AdminPermission}
- * permission and the Java runtime environment supports
- * permissions.
- */
- public void stop() throws BundleException {
- stop(0);
- }
-
- public void stop(int options) throws BundleException {
- framework.checkAdminPermission(this, AdminPermission.EXECUTE);
- checkValid();
- beginStateChange();
- try {
- stopWorker(options);
- } finally {
- completeStateChange();
- }
- }
-
- /**
- * Internal worker to stop a bundle.
- *
- * @param options
- */
- protected abstract void stopWorker(int options) throws BundleException;
-
- /**
- * Set the persistent status bit for the bundle.
- *
- * @param mask
- * Mask for bit to set/clear
- * @param state
- * true to set bit, false to clear bit
- */
- protected void setStatus(final int mask, final boolean state) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws IOException {
- int status = bundledata.getStatus();
- boolean test = ((status & mask) != 0);
- if (test != state) {
- bundledata.setStatus(state ? (status | mask) : (status & ~mask));
- bundledata.save();
- }
- return null;
- }
- });
- } catch (PrivilegedActionException pae) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, pae.getException());
- }
- }
-
- /**
- * Stop this bundle w/o marking is persistently stopped.
- *
- * Any services registered by this bundle will be unregistered. Any
- * services used by this bundle will be released. Any listeners registered
- * by this bundle will be removed.
- *
- * <p>
- * The following steps are followed to stop a bundle:
- * <ol>
- * <li>If the bundle is {@link #UNINSTALLED}then an <code>IllegalStateException</code>
- * is thrown.
- * <li>If the bundle is {@link #STOPPING},{@link #RESOLVED}, or
- * {@link #INSTALLED}then this method returns immediately.
- * <li>If the bundle is {@link #STARTING}then this method may wait for
- * the bundle to reach the {@link #ACTIVE}state before continuing. If this
- * does not occur in a reasonable time, a {@link BundleException}is thrown
- * to indicate the bundle was unable to be stopped.
- * <li>The state of the bundle is set to {@link #STOPPING}.
- * <li>The {@link BundleActivator#stop(BundleContext) stop}method of the bundle's
- * {@link BundleActivator}, if one is specified, is called. If the
- * {@link BundleActivator}throws an exception, this method will continue
- * to stop the bundle. A {@link BundleException}will be thrown after
- * completion of the remaining steps.
- * <li>The bundle's listeners, if any, are removed, service's registered
- * by the bundle, if any, are unregistered, and service's used by the
- * bundle, if any, are released.
- * <li>The state of the bundle is set to {@link #RESOLVED}.
- * <li>A {@link BundleEvent}of type {@link BundleEvent#STOPPED}is
- * broadcast.
- * </ol>
- *
- * <h5>Preconditons</h5>
- * <ul>
- * <li>getState() in {{@link #ACTIVE}}.
- * </ul>
- * <h5>Postconditons, no exceptions thrown</h5>
- * <ul>
- * <li>getState() not in {{@link #ACTIVE},{@link #STOPPING}}.
- * <li>{@link BundleActivator#stop(BundleContext) BundleActivator.stop}has been called
- * and did not throw an exception.
- * </ul>
- * <h5>Postconditions, when an exception is thrown</h5>
- * <ul>
- * <li>None.
- * </ul>
- *
- * @param lock
- * true if state change lock should be held when returning from
- * this method.
- * @exception BundleException
- * If the bundle's BundleActivator could not be loaded or
- * threw an exception.
- * @exception java.lang.IllegalStateException
- * If the bundle tries to change its own state.
- */
- protected void suspend(boolean lock) throws BundleException {
- if (state == UNINSTALLED) {
- return;
- }
- beginStateChange();
- try {
- stopWorker(STOP_TRANSIENT);
- } finally {
- if (!lock) {
- completeStateChange();
- }
- }
- }
-
- public void update() throws BundleException {
- update(null);
- }
-
- public void update(final InputStream in) throws BundleException {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("update location " + bundledata.getLocation()); //$NON-NLS-1$
- Debug.println(" from: " + in); //$NON-NLS-1$
- }
- framework.checkAdminPermission(this, AdminPermission.LIFECYCLE);
- if ((bundledata.getType() & (BundleData.TYPE_BOOTCLASSPATH_EXTENSION | BundleData.TYPE_FRAMEWORK_EXTENSION | BundleData.TYPE_EXTCLASSPATH_EXTENSION)) != 0)
- // need special permission to update extensions
- framework.checkAdminPermission(this, AdminPermission.EXTENSIONLIFECYCLE);
- checkValid();
- beginStateChange();
- try {
- final AccessControlContext callerContext = AccessController.getContext();
- //note AdminPermission is checked again after updated bundle is loaded
- updateWorker(new PrivilegedExceptionAction<Object>() {
- public Object run() throws BundleException {
- /* compute the update location */
- URLConnection source = null;
- if (in == null) {
- String updateLocation = bundledata.getManifest().get(Constants.BUNDLE_UPDATELOCATION);
- if (updateLocation == null)
- updateLocation = bundledata.getLocation();
- if (Debug.DEBUG_GENERAL)
- Debug.println(" from location: " + updateLocation); //$NON-NLS-1$
- /* Map the update location to a URLConnection */
- source = framework.adaptor.mapLocationToURLConnection(updateLocation);
- } else {
- /* Map the InputStream to a URLConnection */
- source = new BundleSource(in);
- }
- /* call the worker */
- updateWorkerPrivileged(source, callerContext);
- return null;
- }
- });
- } finally {
- completeStateChange();
- }
- }
-
- /**
- * Update worker. Assumes the caller has the state change lock.
- */
- protected void updateWorker(PrivilegedExceptionAction<Object> action) throws BundleException {
- int previousState = 0;
- if (!isFragment())
- previousState = state;
- if ((previousState & (ACTIVE | STARTING)) != 0) {
- try {
- stopWorker(STOP_TRANSIENT);
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, e);
- if ((state & (ACTIVE | STARTING)) != 0) /* if the bundle is still active */{
- throw e;
- }
- }
- }
- try {
- AccessController.doPrivileged(action);
- framework.publishBundleEvent(BundleEvent.UPDATED, this);
- } catch (PrivilegedActionException pae) {
- if (pae.getException() instanceof RuntimeException)
- throw (RuntimeException) pae.getException();
- throw (BundleException) pae.getException();
- } finally {
- if ((previousState & (ACTIVE | STARTING)) != 0) {
- try {
- startWorker(START_TRANSIENT | ((previousState & STARTING) != 0 ? START_ACTIVATION_POLICY : 0));
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, e);
- }
- }
- }
- }
-
- /**
- * Update worker. Assumes the caller has the state change lock.
- */
- protected void updateWorkerPrivileged(URLConnection source, AccessControlContext callerContext) throws BundleException {
- AbstractBundle oldBundle = AbstractBundle.createBundle(bundledata, framework, false);
- boolean reloaded = false;
- BundleOperation storage = framework.adaptor.updateBundle(this.bundledata, source);
- BundleRepository bundles = framework.getBundles();
- try {
- BundleData newBundleData = storage.begin();
- // Must call framework createBundle to check execution environment.
- final AbstractBundle newBundle = framework.createAndVerifyBundle(CollisionHook.UPDATING, this, newBundleData, false);
- boolean exporting;
- int st = getState();
- synchronized (bundles) {
- String oldBSN = this.getSymbolicName();
- exporting = reload(newBundle);
- // update this to flush the old BSN/version etc.
- bundles.update(oldBSN, this);
- manifestLocalization = null;
- }
- // indicate we have loaded from the new version of the bundle
- reloaded = true;
- if (System.getSecurityManager() != null) {
- final boolean extension = (bundledata.getType() & (BundleData.TYPE_BOOTCLASSPATH_EXTENSION | BundleData.TYPE_FRAMEWORK_EXTENSION | BundleData.TYPE_EXTCLASSPATH_EXTENSION)) != 0;
- // must check for AllPermission before allow a bundle extension to be updated
- if (extension && !hasPermission(new AllPermission()))
- throw new BundleException(Msg.BUNDLE_EXTENSION_PERMISSION, BundleException.SECURITY_ERROR, new SecurityException(Msg.BUNDLE_EXTENSION_PERMISSION));
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- framework.checkAdminPermission(newBundle, AdminPermission.LIFECYCLE);
- if (extension) // need special permission to update extension bundles
- framework.checkAdminPermission(newBundle, AdminPermission.EXTENSIONLIFECYCLE);
- return null;
- }
- }, callerContext);
- } catch (PrivilegedActionException e) {
- throw e.getException();
- }
- }
- // send out unresolved events outside synch block (defect #80610)
- if (st == RESOLVED)
- framework.publishBundleEvent(BundleEvent.UNRESOLVED, this);
- storage.commit(exporting);
- } catch (Throwable t) {
- try {
- storage.undo();
- if (reloaded)
- /*
- * if we loaded from the new version of the
- * bundle
- */{
- synchronized (bundles) {
- String oldBSN = this.getSymbolicName();
- reload(oldBundle);
- // update this to flush the new BSN/version back to the old one etc.
- bundles.update(oldBSN, this);
- }
- }
- } catch (BundleException ee) {
- /* if we fail to revert then we are in big trouble */
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, ee);
- }
- if (t instanceof SecurityException)
- throw (SecurityException) t;
- if (t instanceof BundleException)
- throw (BundleException) t;
- throw new BundleException(t.getMessage(), t);
- }
- }
-
- /**
- * Uninstall this bundle.
- * <p>
- * This method removes all traces of the bundle, including any data in the
- * persistent storage area provided for the bundle by the framework.
- *
- * <p>
- * The following steps are followed to uninstall a bundle:
- * <ol>
- * <li>If the bundle is {@link #UNINSTALLED}then an <code>IllegalStateException</code>
- * is thrown.
- * <li>If the bundle is {@link #ACTIVE}or {@link #STARTING}, the bundle
- * is stopped as described in the {@link #stop()}method. If {@link #stop()}
- * throws an exception, a {@link FrameworkEvent}of type
- * {@link FrameworkEvent#ERROR}is broadcast containing the exception.
- * <li>A {@link BundleEvent}of type {@link BundleEvent#UNINSTALLED}is
- * broadcast.
- * <li>The state of the bundle is set to {@link #UNINSTALLED}.
- * <li>The bundle and the persistent storage area provided for the bundle
- * by the framework, if any, is removed.
- * </ol>
- *
- * <h5>Preconditions</h5>
- * <ul>
- * <li>getState() not in {{@link #UNINSTALLED}}.
- * </ul>
- * <h5>Postconditons, no exceptions thrown</h5>
- * <ul>
- * <li>getState() in {{@link #UNINSTALLED}}.
- * <li>The bundle has been uninstalled.
- * </ul>
- * <h5>Postconditions, when an exception is thrown</h5>
- * <ul>
- * <li>getState() not in {{@link #UNINSTALLED}}.
- * <li>The Bundle has not been uninstalled.
- * </ul>
- *
- * @exception BundleException
- * If the uninstall failed.
- * @exception java.lang.IllegalStateException
- * If the bundle has been uninstalled or the bundle tries to
- * change its own state.
- * @exception java.lang.SecurityException
- * If the caller does not have {@link AdminPermission}
- * permission and the Java runtime environment supports
- * permissions.
- * @see #stop()
- */
- public void uninstall() throws BundleException {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("uninstall location: " + bundledata.getLocation()); //$NON-NLS-1$
- }
- framework.checkAdminPermission(this, AdminPermission.LIFECYCLE);
- if ((bundledata.getType() & (BundleData.TYPE_BOOTCLASSPATH_EXTENSION | BundleData.TYPE_FRAMEWORK_EXTENSION | BundleData.TYPE_EXTCLASSPATH_EXTENSION)) != 0)
- // need special permission to uninstall extensions
- framework.checkAdminPermission(this, AdminPermission.EXTENSIONLIFECYCLE);
- checkValid();
- beginStateChange();
- try {
- uninstallWorker(new PrivilegedExceptionAction<Object>() {
- public Object run() throws BundleException {
- uninstallWorkerPrivileged();
- return null;
- }
- });
- } finally {
- completeStateChange();
- }
- }
-
- /**
- * Uninstall worker. Assumes the caller has the state change lock.
- */
- protected void uninstallWorker(PrivilegedExceptionAction<Object> action) throws BundleException {
- boolean bundleActive = false;
- if (!isFragment())
- bundleActive = (state & (ACTIVE | STARTING)) != 0;
- if (bundleActive) {
- try {
- stopWorker(STOP_TRANSIENT);
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, e);
- }
- }
- try {
- AccessController.doPrivileged(action);
- } catch (PrivilegedActionException pae) {
- if (bundleActive) /* if we stopped the bundle */{
- try {
- startWorker(START_TRANSIENT);
- } catch (BundleException e) {
- /*
- * if we fail to start the original bundle then we are in
- * big trouble
- */
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, e);
- }
- }
- throw (BundleException) pae.getException();
- }
- framework.publishBundleEvent(BundleEvent.UNINSTALLED, this);
- }
-
- /**
- * Uninstall worker. Assumes the caller has the state change lock.
- */
- protected void uninstallWorkerPrivileged() throws BundleException {
- BundleWatcher bundleStats = framework.adaptor.getBundleWatcher();
- if (bundleStats != null)
- bundleStats.watchBundle(this, BundleWatcher.START_UNINSTALLING);
- boolean unloaded = false;
- //cache the bundle's headers
- getHeaders();
- BundleOperation storage = framework.adaptor.uninstallBundle(this.bundledata);
- BundleRepository bundles = framework.getBundles();
- try {
- storage.begin();
- boolean exporting;
- int st = getState();
- synchronized (bundles) {
- bundles.remove(this); /* remove before calling unload */
- exporting = unload();
- }
- // send out unresolved events outside synch block (defect #80610)
- if (st == RESOLVED)
- framework.publishBundleEvent(BundleEvent.UNRESOLVED, this);
- unloaded = true;
- storage.commit(exporting);
- close();
- } catch (BundleException e) {
- try {
- storage.undo();
- if (unloaded) /* if we unloaded the bundle */{
- synchronized (bundles) {
- load(); /* reload the bundle */
- bundles.add(this);
- }
- }
- } catch (BundleException ee) {
- /*
- * if we fail to load the original bundle then we are in big
- * trouble
- */
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, ee);
- }
- throw e;
- } finally {
- if (bundleStats != null)
- bundleStats.watchBundle(this, BundleWatcher.END_UNINSTALLING);
- }
- }
-
- /**
- * Return the bundle's manifest headers and values from the manifest's
- * preliminary section. That is all the manifest's headers and values prior
- * to the first blank line.
- *
- * <p>
- * Manifest header names are case-insensitive. The methods of the returned
- * <code>Dictionary</code> object will operate on header names in a
- * case-insensitive manner.
- *
- * <p>
- * For example, the following manifest headers and values are included if
- * they are present in the manifest:
- *
- * <pre>
- * Bundle-Name
- * Bundle-Vendor
- * Bundle-Version
- * Bundle-Description
- * Bundle-DocURL
- * Bundle-ContactAddress
- * </pre>
- *
- * <p>
- * This method will continue to return this information when the bundle is
- * in the {@link #UNINSTALLED}state.
- *
- * @return A <code>Dictionary</code> object containing the bundle's
- * manifest headers and values.
- * @exception java.lang.SecurityException
- * If the caller does not have {@link AdminPermission}
- * permission and the Java runtime environment supports
- * permissions.
- */
- public Dictionary<String, String> getHeaders() {
- return getHeaders(null);
- }
-
- /**
- * Returns this bundle's Manifest headers and values. This method returns
- * all the Manifest headers and values from the main section of the
- * bundle's Manifest file; that is, all lines prior to the first blank
- * line.
- *
- * <p>
- * Manifest header names are case-insensitive. The methods of the returned
- * <tt>Dictionary</tt> object will operate on header names in a
- * case-insensitive manner.
- *
- * If a Manifest header begins with a '%', it will be evaluated with the
- * specified properties file for the specied Locale.
- *
- * <p>
- * For example, the following Manifest headers and values are included if
- * they are present in the Manifest file:
- *
- * <pre>
- * Bundle-Name
- * Bundle-Vendor
- * Bundle-Version
- * Bundle-Description
- * Bundle-DocURL
- * Bundle-ContactAddress
- * </pre>
- *
- * <p>
- * This method will continue to return Manifest header information while
- * this bundle is in the <tt>UNINSTALLED</tt> state.
- *
- * @return A <tt>Dictionary</tt> object containing this bundle's Manifest
- * headers and values.
- *
- * @exception java.lang.SecurityException
- * If the caller does not have the <tt>AdminPermission</tt>,
- * and the Java Runtime Environment supports permissions.
- */
- public Dictionary<String, String> getHeaders(String localeString) {
- framework.checkAdminPermission(this, AdminPermission.METADATA);
- ManifestLocalization localization;
- try {
- localization = getManifestLocalization();
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, this, e);
- // return an empty dictinary.
- return new Hashtable<String, String>();
- }
- if (localeString == null)
- localeString = Locale.getDefault().toString();
- return localization.getHeaders(localeString);
- }
-
- /**
- * Retrieve the bundle's unique identifier, which the framework assigned to
- * this bundle when it was installed.
- *
- * <p>
- * The unique identifier has the following attributes:
- * <ul>
- * <li>It is unique and persistent.
- * <li>The identifier is a long.
- * <li>Once its value is assigned to a bundle, that value is not reused
- * for another bundle, even after the bundle is uninstalled.
- * <li>Its value does not change as long as the bundle remains installed.
- * <li>Its value does not change when the bundle is updated
- * </ul>
- *
- * <p>
- * This method will continue to return the bundle's unique identifier when
- * the bundle is in the {@link #UNINSTALLED}state.
- *
- * @return This bundle's unique identifier.
- */
- public long getBundleId() {
- return (bundledata.getBundleID());
- }
-
- /**
- * Retrieve the location identifier of the bundle. This is typically the
- * location passed to
- * {@link BundleContextImpl#installBundle(String) BundleContext.installBundle}when the
- * bundle was installed. The location identifier of the bundle may change
- * during bundle update. Calling this method while framework is updating
- * the bundle results in undefined behavior.
- *
- * <p>
- * This method will continue to return the bundle's location identifier
- * when the bundle is in the {@link #UNINSTALLED}state.
- *
- * @return A string that is the location identifier of the bundle.
- * @exception java.lang.SecurityException
- * If the caller does not have {@link AdminPermission}
- * permission and the Java runtime environment supports
- * permissions.
- */
- public String getLocation() {
- framework.checkAdminPermission(this, AdminPermission.METADATA);
- return (bundledata.getLocation());
- }
-
- /**
- * Determine whether the bundle has the requested permission.
- *
- * <p>
- * If the Java runtime environment does not supports permissions this
- * method always returns <code>true</code>. The permission parameter is
- * of type <code>Object</code> to avoid referencing the <code>java.security.Permission</code>
- * class directly. This is to allow the framework to be implemented in Java
- * environments which do not support permissions.
- *
- * @param permission
- * The requested permission.
- * @return <code>true</code> if the bundle has the requested permission
- * or <code>false</code> if the bundle does not have the
- * permission or the permission parameter is not an <code>instanceof java.security.Permission</code>.
- * @exception java.lang.IllegalStateException
- * If the bundle has been uninstalled.
- */
- public boolean hasPermission(Object permission) {
- checkValid();
- if (domain != null) {
- if (permission instanceof Permission) {
- SecurityManager sm = System.getSecurityManager();
- if (sm instanceof EquinoxSecurityManager) {
- /*
- * If the FrameworkSecurityManager is active, we need to do checks the "right" way.
- * We can exploit our knowledge that the security context of FrameworkSecurityManager
- * is an AccessControlContext to invoke it properly with the ProtectionDomain.
- */
- AccessControlContext acc = getAccessControlContext();
- try {
- sm.checkPermission((Permission) permission, acc);
- return true;
- } catch (Exception e) {
- return false;
- }
- }
- return domain.implies((Permission) permission);
- }
- return false;
- }
- return true;
- }
-
- /**
- * This method marks the bundle's state as changing so that other calls to
- * start/stop/suspend/update/uninstall can wait until the state change is
- * complete. If stateChanging is non-null when this method is called, we
- * will wait for the state change to complete. If the timeout expires
- * without changing state (this may happen if the state change is back up
- * our call stack), a BundleException is thrown so that we don't wait
- * forever.
- *
- * A call to this method should be immediately followed by a try block
- * whose finally block calls completeStateChange().
- *
- * beginStateChange(); try { // change the bundle's state here... } finally {
- * completeStateChange(); }
- *
- * @exception org.osgi.framework.BundleException
- * if the bundles state is still changing after waiting for
- * the timeout.
- */
- protected void beginStateChange() throws BundleException {
- synchronized (statechangeLock) {
- boolean doubleFault = false;
- while (true) {
- if (stateChanging == null) {
- stateChanging = Thread.currentThread();
- return;
- }
- if (doubleFault || (stateChanging == Thread.currentThread())) {
- throw new BundleException(NLS.bind(Msg.BUNDLE_STATE_CHANGE_EXCEPTION, getBundleData().getLocation(), stateChanging.getName()), BundleException.STATECHANGE_ERROR, new BundleStatusException(null, StatusException.CODE_WARNING, stateChanging));
- }
- try {
- long start = 0;
- if (Debug.DEBUG_GENERAL) {
- Debug.println(" Waiting for state to change in bundle " + this); //$NON-NLS-1$
- start = System.currentTimeMillis();
- }
- statechangeLock.wait(STATE_CHANGE_TIMEOUT);
- /*
- * wait for other thread to
- * finish changing state
- */
- if (Debug.DEBUG_GENERAL) {
- long end = System.currentTimeMillis();
- if (end - start > 0)
- System.out.println("Waiting... : " + getSymbolicName() + ' ' + (end - start)); //$NON-NLS-1$
- }
- } catch (InterruptedException e) {
- //Nothing to do
- }
- doubleFault = true;
- }
- }
- }
-
- /**
- * This method completes the bundle state change by setting stateChanging
- * to null and notifying one waiter that the state change has completed.
- */
- protected void completeStateChange() {
- synchronized (statechangeLock) {
- if (stateChanging == Thread.currentThread()) {
- stateChanging = null;
- statechangeLock.notify();
- /*
- * notify one waiting thread that the
- * state change is complete
- */
- }
- }
- }
-
- /**
- * Return a string representation of this bundle.
- *
- * @return String
- */
- public String toString() {
- String name = bundledata.getSymbolicName();
- if (name == null)
- name = "unknown"; //$NON-NLS-1$
- return (name + '_' + bundledata.getVersion() + " [" + getBundleId() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /**
- * Answers an integer indicating the relative positions of the receiver and
- * the argument in the natural order of elements of the receiver's class.
- *
- * @return int which should be <0 if the receiver should sort before the
- * argument, 0 if the receiver should sort in the same position as
- * the argument, and >0 if the receiver should sort after the
- * argument.
- * @param obj
- * another Bundle an object to compare the receiver to
- * @exception ClassCastException
- * if the argument can not be converted into something
- * comparable with the receiver.
- */
- public int compareTo(Bundle obj) {
- int slcomp = getInternalStartLevel() - ((AbstractBundle) obj).getInternalStartLevel();
- if (slcomp != 0) {
- return slcomp;
- }
- long idcomp = getBundleId() - ((AbstractBundle) obj).getBundleId();
- return (idcomp < 0L) ? -1 : ((idcomp > 0L) ? 1 : 0);
- }
-
- /**
- * This method checks that the bundle is not uninstalled. If the bundle is
- * uninstalled, an IllegalStateException is thrown.
- *
- * @exception java.lang.IllegalStateException
- * If the bundle is uninstalled.
- */
- protected void checkValid() {
- if (state == UNINSTALLED) {
- throw new IllegalStateException(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, getBundleData().getLocation()));
- }
- }
-
- /**
- * Get the bundle's ProtectionDomain.
- *
- * @return bundle's ProtectionDomain.
- */
- public BundleProtectionDomain getProtectionDomain() {
- return domain;
- }
-
- private AccessControlContext getAccessControlContext() {
- return new AccessControlContext(new ProtectionDomain[] {domain});
- }
-
- protected BundleFragment[] getFragments() {
- checkValid();
- return null;
- }
-
- protected boolean isFragment() {
- return false;
- }
-
- BundleHost[] getHosts() {
- checkValid();
- return null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.osgi.framework.Bundle#findClass(java.lang.String)
- */
- public Class<?> loadClass(String classname) throws ClassNotFoundException {
- return loadClass(classname, true);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.osgi.framework.Bundle#getResourcePaths(java.lang.String)
- */
- public Enumeration<String> getEntryPaths(final String path) {
- try {
- framework.checkAdminPermission(this, AdminPermission.RESOURCE);
- } catch (SecurityException e) {
- return null;
- }
- checkValid();
- // TODO this doPrivileged is probably not needed. The adaptor isolates callers from disk access
- return AccessController.doPrivileged(new PrivilegedAction<Enumeration<String>>() {
- public Enumeration<String> run() {
- return bundledata.getEntryPaths(path);
- }
- });
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.osgi.framework.Bundle#getFile(java.lang.String)
- */
- public URL getEntry(String fileName) {
- try {
- framework.checkAdminPermission(this, AdminPermission.RESOURCE);
- } catch (SecurityException e) {
- return null;
- }
- return getEntry0(fileName);
- }
-
- URL getEntry0(String fileName) {
- checkValid();
- return bundledata.getEntry(fileName);
- }
-
- public String getSymbolicName() {
- return bundledata.getSymbolicName();
- }
-
- public long getLastModified() {
- return bundledata.getLastModified();
- }
-
- public BundleData getBundleData() {
- return bundledata;
- }
-
- public Version getVersion() {
- return bundledata.getVersion();
- }
-
- public BundleDescription getBundleDescription() {
- return framework.adaptor.getState().getBundle(getBundleId());
- }
-
- int getInternalStartLevel() {
- return bundledata.getStartLevel();
- }
-
- protected abstract BundleLoader getBundleLoader();
-
- /**
- * Mark this bundle as resolved.
- */
- protected void resolve() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (INSTALLED)) == 0) {
- Debug.println("Bundle.resolve called when state != INSTALLED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
- if (state == INSTALLED) {
- state = RESOLVED;
- // Do not publish RESOLVED event here. This is done by caller
- // to resolve if appropriate.
- }
- }
-
- public BundleContext getBundleContext() {
- framework.checkAdminPermission(this, AdminPermission.CONTEXT);
- return getContext();
- }
-
- /**
- * Return the current context for this bundle.
- *
- * @return BundleContext for this bundle.
- */
- abstract protected BundleContextImpl getContext();
-
- public BundleException getResolutionFailureException() {
- BundleDescription bundleDescription = getBundleDescription();
- if (bundleDescription == null)
- return new BundleException(NLS.bind(Msg.BUNDLE_UNRESOLVED_EXCEPTION, this.toString()), BundleException.RESOLVE_ERROR);
- // just a sanity check - this would be an inconsistency between the framework and the state
- if (bundleDescription.isResolved())
- return new BundleException(Msg.BUNDLE_UNRESOLVED_STATE_CONFLICT, BundleException.RESOLVE_ERROR);
- return getResolverError(bundleDescription);
- }
-
- private BundleException getResolverError(BundleDescription bundleDesc) {
- ResolverError[] errors = framework.adaptor.getState().getResolverErrors(bundleDesc);
- if (errors == null || errors.length == 0)
- return new BundleException(NLS.bind(Msg.BUNDLE_UNRESOLVED_EXCEPTION, this.toString()), BundleException.RESOLVE_ERROR);
- StringBuffer message = new StringBuffer();
- int errorType = BundleException.RESOLVE_ERROR;
- for (int i = 0; i < errors.length; i++) {
- if ((errors[i].getType() & ResolverError.INVALID_NATIVECODE_PATHS) != 0)
- errorType = BundleException.NATIVECODE_ERROR;
- message.append(errors[i].toString());
- if (i < errors.length - 1)
- message.append(", "); //$NON-NLS-1$
- }
- return new BundleException(NLS.bind(Msg.BUNDLE_UNRESOLVED_UNSATISFIED_CONSTRAINT_EXCEPTION, this.toString(), message.toString()), errorType);
- }
-
- public int getKeyHashCode() {
- long id = getBundleId();
- return (int) (id ^ (id >>> 32));
- }
-
- public boolean compare(KeyedElement other) {
- return getBundleId() == ((AbstractBundle) other).getBundleId();
- }
-
- public Object getKey() {
- return new Long(getBundleId());
- }
-
- /* This method is used by the Bundle Localization Service to obtain
- * a ResourceBundle that resides in a bundle. This is not an OSGi
- * defined method for org.osgi.framework.Bundle
- *
- */
- public ResourceBundle getResourceBundle(String localeString) {
- ManifestLocalization localization;
- try {
- localization = getManifestLocalization();
- } catch (BundleException ex) {
- return (null);
- }
- String defaultLocale = Locale.getDefault().toString();
- if (localeString == null) {
- localeString = defaultLocale;
- }
- return localization.getResourceBundle(localeString, defaultLocale.equals(localeString));
- }
-
- private synchronized ManifestLocalization getManifestLocalization() throws BundleException {
- ManifestLocalization currentLocalization = manifestLocalization;
- if (currentLocalization == null) {
- Dictionary<String, String> rawHeaders = bundledata.getManifest();
- manifestLocalization = currentLocalization = new ManifestLocalization(this, rawHeaders);
- }
- return currentLocalization;
- }
-
- public boolean testStateChanging(Object thread) {
- return stateChanging == thread;
- }
-
- public Thread getStateChanging() {
- return stateChanging;
- }
-
- public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
- try {
- framework.checkAdminPermission(this, AdminPermission.RESOURCE);
- } catch (SecurityException e) {
- return null;
- }
- checkValid();
- // check to see if the bundle is resolved
- if (!isResolved())
- framework.packageAdmin.resolveBundles(new Bundle[] {this});
-
- // if this bundle is a host to fragments then search the fragments
- BundleFragment[] fragments = getFragments();
- List<BundleData> datas = new ArrayList<BundleData>((fragments == null ? 0 : fragments.length) + 1);
- datas.add(getBundleData());
- if (fragments != null)
- for (BundleFragment fragment : fragments)
- datas.add(fragment.getBundleData());
- int options = recurse ? BundleWiring.FINDENTRIES_RECURSE : 0;
- return framework.getAdaptor().findEntries(datas, path, filePattern, options);
- }
-
- class BundleStatusException extends Throwable implements StatusException {
- private static final long serialVersionUID = 7201911791818929100L;
- private int code;
- private transient Object status;
-
- BundleStatusException(String message, int code, Object status) {
- super(message);
- this.code = code;
- this.status = status;
- }
-
- public Object getStatus() {
- return status;
- }
-
- public int getStatusCode() {
- return code;
- }
-
- }
-
- public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
- @SuppressWarnings("unchecked")
- final Map<X509Certificate, List<X509Certificate>> empty = Collections.EMPTY_MAP;
- if (signersType != SIGNERS_ALL && signersType != SIGNERS_TRUSTED)
- throw new IllegalArgumentException("Invalid signers type: " + signersType); //$NON-NLS-1$
- if (framework == null)
- return empty;
- SignedContentFactory factory = framework.getSignedContentFactory();
- if (factory == null)
- return empty;
- try {
- SignedContent signedContent = factory.getSignedContent(this);
- SignerInfo[] infos = signedContent.getSignerInfos();
- if (infos.length == 0)
- return empty;
- Map<X509Certificate, List<X509Certificate>> results = new HashMap<X509Certificate, List<X509Certificate>>(infos.length);
- for (int i = 0; i < infos.length; i++) {
- if (signersType == SIGNERS_TRUSTED && !infos[i].isTrusted())
- continue;
- Certificate[] certs = infos[i].getCertificateChain();
- if (certs == null || certs.length == 0)
- continue;
- List<X509Certificate> certChain = new ArrayList<X509Certificate>();
- for (int j = 0; j < certs.length; j++)
- certChain.add((X509Certificate) certs[j]);
- results.put((X509Certificate) certs[0], certChain);
- }
- return results;
- } catch (Exception e) {
- return empty;
- }
- }
-
- public final <A> A adapt(Class<A> adapterType) {
- checkAdaptPermission(adapterType);
- return adapt0(adapterType);
- }
-
- public List<BundleRevision> getRevisions() {
- List<BundleRevision> revisions = new ArrayList<BundleRevision>();
- BundleDescription current = getBundleDescription();
- if (current != null)
- revisions.add(current);
- BundleDescription[] removals = framework.adaptor.getState().getRemovalPending();
- for (BundleDescription removed : removals) {
- if (removed.getBundleId() == getBundleId() && removed != current) {
- revisions.add(removed);
- }
- }
- return revisions;
- }
-
- @SuppressWarnings("unchecked")
- protected <A> A adapt0(Class<A> adapterType) {
- if (adapterType.isInstance(this))
- return (A) this;
- if (BundleContext.class.equals(adapterType)) {
- try {
- return (A) getBundleContext();
- } catch (SecurityException e) {
- return null;
- }
- }
-
- if (AccessControlContext.class.equals(adapterType)) {
- return (A) getAccessControlContext();
- }
-
- if (BundleWiring.class.equals(adapterType)) {
- if (state == UNINSTALLED)
- return null;
- BundleDescription description = getBundleDescription();
- return (A) description.getWiring();
- }
-
- if (BundleRevision.class.equals(adapterType)) {
- if (state == UNINSTALLED)
- return null;
- return (A) getBundleDescription();
- }
- return null;
- }
-
- /**
- * Check for permission to get a service.
- */
- private <A> void checkAdaptPermission(Class<A> adapterType) {
- SecurityManager sm = System.getSecurityManager();
- if (sm == null) {
- return;
- }
- sm.checkPermission(new AdaptPermission(adapterType.getName(), this, AdaptPermission.ADAPT));
- }
-
- public File getDataFile(String filename) {
- return framework.getDataFile(this, filename);
- }
-
- public Bundle getBundle() {
- return this;
- }
-
- public int getStartLevel() {
- if (getState() == Bundle.UNINSTALLED)
- throw new IllegalArgumentException(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, getBundleData().getLocation()));
- return getInternalStartLevel();
- }
-
- public void setStartLevel(int startlevel) {
- framework.startLevelManager.setBundleStartLevel(this, startlevel);
- }
-
- public boolean isPersistentlyStarted() {
- if (getState() == Bundle.UNINSTALLED)
- throw new IllegalArgumentException(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, getBundleData().getLocation()));
- return (getBundleData().getStatus() & Constants.BUNDLE_STARTED) != 0;
- }
-
- public boolean isActivationPolicyUsed() {
- if (getState() == Bundle.UNINSTALLED)
- throw new IllegalArgumentException(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, getBundleData().getLocation()));
- return (getBundleData().getStatus() & Constants.BUNDLE_ACTIVATION_POLICY) != 0;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java
deleted file mode 100644
index 98ca8ee24..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Enumeration;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class BundleFragment extends AbstractBundle {
-
- /** The resolved host that this fragment is attached to */
- protected BundleHost[] hosts;
-
- /**
- * @param bundledata
- * @param framework
- * @throws BundleException
- */
- public BundleFragment(BundleData bundledata, Framework framework) throws BundleException {
- super(bundledata, framework);
- hosts = null;
- }
-
- /**
- * Load the bundle.
- */
- protected void load() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (INSTALLED)) == 0) {
- Debug.println("Bundle.load called when state != INSTALLED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- if (framework.isActive()) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null && framework.securityAdmin != null) {
- domain = framework.securityAdmin.createProtectionDomain(this);
- }
- }
- }
-
- /**
- * Reload from a new bundle.
- * This method must be called while holding the bundles lock.
- *
- * @param newBundle Dummy Bundle which contains new data.
- * @return true if an exported package is "in use". i.e. it has been imported by a bundle
- */
- protected boolean reload(AbstractBundle newBundle) {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (INSTALLED | RESOLVED)) == 0) {
- Debug.println("Bundle.reload called when state != INSTALLED | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- boolean exporting = false;
- if (framework.isActive()) {
- if (hosts != null) {
- if (state == RESOLVED) {
- exporting = true; // if we have a host we cannot be removed until the host is refreshed
- hosts = null;
- state = INSTALLED;
- }
- }
- } else {
- /* close the outgoing jarfile */
- try {
- this.bundledata.close();
- } catch (IOException e) {
- // Do Nothing
- }
- }
- if (!exporting) {
- /* close the outgoing jarfile */
- try {
- this.bundledata.close();
- } catch (IOException e) {
- // Do Nothing
- }
- }
-
- this.bundledata = newBundle.bundledata;
- this.bundledata.setBundle(this);
- // create a new domain for the bundle because its signers/symbolic-name may have changed
- if (framework.isActive() && System.getSecurityManager() != null && framework.securityAdmin != null)
- domain = framework.securityAdmin.createProtectionDomain(this);
- return (exporting);
- }
-
- /**
- * Refresh the bundle. This is called by Framework.refreshPackages.
- * This method must be called while holding the bundles lock.
- * this.loader.unimportPackages must have already been called before calling
- * this method!
- */
- protected void refresh() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (UNINSTALLED | INSTALLED | RESOLVED)) == 0) {
- Debug.println("Bundle.refresh called when state != UNINSTALLED | INSTALLED | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- if (state == RESOLVED) {
- hosts = null;
- state = INSTALLED;
- // Do not publish UNRESOLVED event here. This is done by caller
- // to resolve if appropriate.
- }
- manifestLocalization = null;
- }
-
- /**
- * Unload the bundle.
- * This method must be called while holding the bundles lock.
- *
- * @return true if an exported package is "in use". i.e. it has been imported by a bundle
- */
- protected boolean unload() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (UNINSTALLED | INSTALLED | RESOLVED)) == 0) {
- Debug.println("Bundle.unload called when state != UNINSTALLED | INSTALLED | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- boolean exporting = false;
- if (framework.isActive()) {
- if (hosts != null) {
- if (state == RESOLVED) {
- exporting = true; // if we have a host we cannot be removed until the host is refreshed
- hosts = null;
- state = INSTALLED;
- }
- domain = null;
- }
- }
- if (!exporting) {
- try {
- this.bundledata.close();
- } catch (IOException e) { // Do Nothing.
- }
- }
-
- return (exporting);
- }
-
- /**
- * This method loads a class from the bundle.
- *
- * @param name the name of the desired Class.
- * @param checkPermission indicates whether a permission check should be done.
- * @return the resulting Class
- * @exception java.lang.ClassNotFoundException if the class definition was not found.
- */
- protected Class<?> loadClass(String name, boolean checkPermission) throws ClassNotFoundException {
- if (checkPermission) {
- try {
- framework.checkAdminPermission(this, AdminPermission.CLASS);
- } catch (SecurityException e) {
- throw new ClassNotFoundException(name, e);
- }
- checkValid();
- }
- // cannot load a class from a fragment because there is no classloader
- // associated with fragments.
- throw new ClassNotFoundException(NLS.bind(Msg.BUNDLE_FRAGMENT_CNFE, name));
- }
-
- /**
- * Find the specified resource in this bundle.
- *
- * This bundle's class loader is called to search for the named resource.
- * If this bundle's state is <tt>INSTALLED</tt>, then only this bundle will
- * be searched for the specified resource. Imported packages cannot be searched
- * when a bundle has not been resolved.
- *
- * @param name The name of the resource.
- * See <tt>java.lang.ClassLoader.getResource</tt> for a description of
- * the format of a resource name.
- * @return a URL to the named resource, or <tt>null</tt> if the resource could
- * not be found or if the caller does not have
- * the <tt>AdminPermission</tt>, and the Java Runtime Environment supports permissions.
- *
- * @exception java.lang.IllegalStateException If this bundle has been uninstalled.
- */
- public URL getResource(String name) {
- checkValid();
- // cannot get a resource for a fragment because there is no classloader
- // associated with fragments.
- return (null);
-
- }
-
- public Enumeration<URL> getResources(String name) {
- checkValid();
- // cannot get a resource for a fragment because there is no classloader
- // associated with fragments.
- return null;
- }
-
- /**
- * Internal worker to start a bundle.
- *
- * @param options
- */
- protected void startWorker(int options) throws BundleException {
- throw new BundleException(NLS.bind(Msg.BUNDLE_FRAGMENT_START, this), BundleException.INVALID_OPERATION);
- }
-
- /**
- * Internal worker to stop a bundle.
- *
- * @param options
- */
- protected void stopWorker(int options) throws BundleException {
- throw new BundleException(NLS.bind(Msg.BUNDLE_FRAGMENT_STOP, this), BundleException.INVALID_OPERATION);
- }
-
- /**
- * Provides a list of {@link ServiceReference}s for the services
- * registered by this bundle
- * or <code>null</code> if the bundle has no registered
- * services.
- *
- * <p>The list is valid at the time
- * of the call to this method, but the framework is a very dynamic
- * environment and services can be modified or unregistered at anytime.
- *
- * @return An array of {@link ServiceReference} or <code>null</code>.
- * @exception java.lang.IllegalStateException If the
- * bundle has been uninstalled.
- * @see ServiceRegistration
- * @see ServiceReference
- */
- public ServiceReference<?>[] getRegisteredServices() {
- checkValid();
- // Fragments cannot have a BundleContext and therefore
- // cannot have any services registered.
- return null;
- }
-
- /**
- * Provides a list of {@link ServiceReference}s for the
- * services this bundle is using,
- * or <code>null</code> if the bundle is not using any services.
- * A bundle is considered to be using a service if the bundle's
- * use count for the service is greater than zero.
- *
- * <p>The list is valid at the time
- * of the call to this method, but the framework is a very dynamic
- * environment and services can be modified or unregistered at anytime.
- *
- * @return An array of {@link ServiceReference} or <code>null</code>.
- * @exception java.lang.IllegalStateException If the
- * bundle has been uninstalled.
- * @see ServiceReference
- */
- public ServiceReference<?>[] getServicesInUse() {
- checkValid();
- // Fragments cannot have a BundleContext and therefore
- // cannot have any services in use.
- return null;
- }
-
- synchronized BundleHost[] getHosts() {
- return hosts;
- }
-
- protected boolean isFragment() {
- return true;
- }
-
- /**
- * Adds a host bundle for this fragment.
- * @param host the BundleHost to add to the set of host bundles
- */
- boolean addHost(BundleHost host) {
- if (host == null)
- return false;
- try {
- host.attachFragment(this);
- } catch (BundleException be) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, host, be);
- return false;
- }
- synchronized (this) {
- if (hosts == null) {
- hosts = new BundleHost[] {host};
- return true;
- }
- for (int i = 0; i < hosts.length; i++) {
- if (host == hosts[i])
- return true; // already a host
- }
- BundleHost[] newHosts = new BundleHost[hosts.length + 1];
- System.arraycopy(hosts, 0, newHosts, 0, hosts.length);
- newHosts[newHosts.length - 1] = host;
- hosts = newHosts;
- }
- return true;
- }
-
- protected BundleLoader getBundleLoader() {
- // Fragments cannot have a BundleLoader.
- return null;
- }
-
- /**
- * Return the current context for this bundle.
- *
- * @return BundleContext for this bundle.
- */
- protected BundleContextImpl getContext() {
- // Fragments cannot have a BundleContext.
- return null;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
deleted file mode 100644
index cfc55b0a3..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Enumeration;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.ResolverHookException;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class BundleHost extends AbstractBundle {
- public static final int LAZY_TRIGGER = 0x40000000;
- /**
- * The BundleLoader proxy; a lightweight object that acts as a proxy
- * to the BundleLoader and allows lazy creation of the BundleLoader object
- */
- private BundleLoaderProxy proxy;
-
- /** The BundleContext that represents this Bundle and all of its fragments */
- protected BundleContextImpl context;
-
- /** The List of BundleFragments */
- protected BundleFragment[] fragments;
-
- public BundleHost(BundleData bundledata, Framework framework) {
- super(bundledata, framework);
- context = null;
- fragments = null;
- }
-
- /**
- * Load the bundle.
- */
- protected void load() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (INSTALLED)) == 0) {
- Debug.println("Bundle.load called when state != INSTALLED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- if (proxy != null) {
- Debug.println("Bundle.load called when proxy != null: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- if (framework.isActive()) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null && framework.securityAdmin != null) {
- domain = framework.securityAdmin.createProtectionDomain(this);
- }
- }
- proxy = null;
- }
-
- /**
- * Reload from a new bundle.
- * This method must be called while holding the bundles lock.
- *
- * @param newBundle Dummy Bundle which contains new data.
- * @return true if an exported package is "in use". i.e. it has been imported by a bundle
- */
- protected boolean reload(AbstractBundle newBundle) {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (INSTALLED | RESOLVED)) == 0) {
- Debug.println("Bundle.reload called when state != INSTALLED | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- boolean exporting = false;
-
- if (framework.isActive()) {
- if (state == RESOLVED) {
- BundleLoaderProxy curProxy = getLoaderProxy();
- exporting = curProxy.inUse();
- if (exporting) {
- // make sure the BundleLoader is created.
- curProxy.getBundleLoader().createClassLoader();
- } else
- BundleLoader.closeBundleLoader(proxy);
- state = INSTALLED;
- proxy = null;
- fragments = null;
- }
-
- } else {
- /* close the outgoing jarfile */
- try {
- this.bundledata.close();
- } catch (IOException e) {
- // Do Nothing
- }
- }
- this.bundledata = newBundle.bundledata;
- this.bundledata.setBundle(this);
- // create a new domain for the bundle because its signers/symbolic-name may have changed
- if (framework.isActive() && System.getSecurityManager() != null && framework.securityAdmin != null)
- domain = framework.securityAdmin.createProtectionDomain(this);
- return (exporting);
- }
-
- /**
- * Refresh the bundle. This is called by Framework.refreshPackages.
- * This method must be called while holding the bundles lock.
- */
- protected void refresh() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (UNINSTALLED | INSTALLED | RESOLVED)) == 0) {
- Debug.println("Bundle.reload called when state != UNINSTALLED | INSTALLED | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
- if (state == RESOLVED) {
- BundleLoader.closeBundleLoader(proxy);
- proxy = null;
- fragments = null;
- state = INSTALLED;
- // Do not publish UNRESOLVED event here. This is done by caller
- // to resolve if appropriate.
- }
- manifestLocalization = null;
- }
-
- /**
- * Unload the bundle.
- * This method must be called while holding the bundles lock.
- *
- * @return true if an exported package is "in use". i.e. it has been imported by a bundle
- */
- protected boolean unload() {
- if (Debug.DEBUG_GENERAL) {
- if ((state & (UNINSTALLED | INSTALLED | RESOLVED)) == 0) {
- Debug.println("Bundle.unload called when state != UNINSTALLED | INSTALLED | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- boolean exporting = false;
-
- if (framework.isActive()) {
- if (state == RESOLVED) {
- BundleLoaderProxy curProxy = getLoaderProxy();
- exporting = curProxy.inUse();
- if (exporting) {
- // make sure the BundleLoader is created.
- curProxy.getBundleLoader().createClassLoader();
- } else
- BundleLoader.closeBundleLoader(proxy);
-
- state = INSTALLED;
- proxy = null;
- fragments = null;
- domain = null;
- }
- }
- if (!exporting) {
- try {
- this.bundledata.close();
- } catch (IOException e) { // Do Nothing.
- }
- }
-
- return (exporting);
- }
-
- private BundleLoader checkLoader() {
- checkValid();
-
- // check to see if the bundle is resolved
- if (!isResolved()) {
- if (!framework.packageAdmin.resolveBundles(new Bundle[] {this})) {
- return null;
- }
- }
- if (Debug.DEBUG_GENERAL) {
- if ((state & (STARTING | ACTIVE | STOPPING | RESOLVED)) == 0) {
- Debug.println("Bundle.checkLoader() called when state != STARTING | ACTIVE | STOPPING | RESOLVED: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
-
- BundleLoader loader = getBundleLoader();
- if (loader == null) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Bundle.checkLoader() called when loader == null: " + this); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- return null;
- }
- return loader;
- }
-
- /**
- * This method loads a class from the bundle.
- *
- * @param name the name of the desired Class.
- * @param checkPermission indicates whether a permission check should be done.
- * @return the resulting Class
- * @exception java.lang.ClassNotFoundException if the class definition was not found.
- */
- protected Class<?> loadClass(String name, boolean checkPermission) throws ClassNotFoundException {
- if (checkPermission) {
- try {
- framework.checkAdminPermission(this, AdminPermission.CLASS);
- } catch (SecurityException e) {
- throw new ClassNotFoundException(name, e);
- }
- }
- BundleLoader loader = checkLoader();
- if (loader == null)
- throw new ClassNotFoundException(NLS.bind(Msg.BUNDLE_CNFE_NOT_RESOLVED, name, getBundleData().getLocation()));
- try {
- return (loader.loadClass(name));
- } catch (ClassNotFoundException e) {
- // this is to support backward compatibility in eclipse
- // we always attempted to start a bundle even if the class was not found
- if (!(e instanceof StatusException) && (bundledata.getStatus() & Constants.BUNDLE_LAZY_START) != 0 && !testStateChanging(Thread.currentThread()))
- try {
- // only start the bundle if this is a simple CNFE
- loader.setLazyTrigger();
- } catch (BundleException be) {
- framework.adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, be.getMessage(), 0, be, null));
- }
- throw e;
- }
- }
-
- /**
- * Find the specified resource in this bundle.
- *
- * This bundle's class loader is called to search for the named resource.
- * If this bundle's state is <tt>INSTALLED</tt>, then only this bundle will
- * be searched for the specified resource. Imported packages cannot be searched
- * when a bundle has not been resolved.
- *
- * @param name The name of the resource.
- * See <tt>java.lang.ClassLoader.getResource</tt> for a description of
- * the format of a resource name.
- * @return a URL to the named resource, or <tt>null</tt> if the resource could
- * not be found or if the caller does not have
- * the <tt>AdminPermission</tt>, and the Java Runtime Environment supports permissions.
- *
- * @exception java.lang.IllegalStateException If this bundle has been uninstalled.
- */
- public URL getResource(String name) {
- BundleLoader loader = null;
- try {
- framework.checkAdminPermission(this, AdminPermission.RESOURCE);
- } catch (SecurityException ee) {
- return null;
- }
- loader = checkLoader();
- if (loader == null) {
- Enumeration<URL> result = bundledata.findLocalResources(name);
- if (result != null && result.hasMoreElements())
- return result.nextElement();
- return null;
- }
- return loader.findResource(name);
- }
-
- public Enumeration<URL> getResources(String name) throws IOException {
- BundleLoader loader = null;
- try {
- framework.checkAdminPermission(this, AdminPermission.RESOURCE);
- } catch (SecurityException ee) {
- return null;
- }
- Enumeration<URL> result;
- loader = checkLoader();
- if (loader == null)
- result = bundledata.findLocalResources(name);
- else
- result = loader.getResources(name);
- if (result != null && result.hasMoreElements())
- return result;
- return null;
- }
-
- /**
- * Internal worker to start a bundle.
- *
- * @param options the start options
- */
- protected void startWorker(int options) throws BundleException {
- if ((options & START_TRANSIENT) == 0) {
- setStatus(Constants.BUNDLE_STARTED, true);
- setStatus(Constants.BUNDLE_ACTIVATION_POLICY, (options & START_ACTIVATION_POLICY) != 0);
- if (Debug.MONITOR_ACTIVATION)
- new Exception("A persistent start has been called on bundle: " + getBundleData()).printStackTrace(); //$NON-NLS-1$
- }
- if (!framework.active || (state & ACTIVE) != 0)
- return;
- if (getInternalStartLevel() > framework.startLevelManager.getStartLevel()) {
- if ((options & LAZY_TRIGGER) == 0 && (options & START_TRANSIENT) != 0) {
- // throw exception if this is a transient start
- String msg = NLS.bind(Msg.BUNDLE_TRANSIENT_START_ERROR, this);
- // Use a StatusException to indicate to the lazy starter that this should result in a warning
- throw new BundleException(msg, BundleException.INVALID_OPERATION, new BundleStatusException(msg, StatusException.CODE_WARNING, this));
- }
- return;
- }
-
- if (state == INSTALLED) {
- try {
- if (!framework.packageAdmin.resolveBundles(new Bundle[] {this}, true))
- throw getResolutionFailureException();
- } catch (IllegalStateException e) {
- // Can happen if the resolver detects a nested resolve process
- throw new BundleException("Unexpected resolution exception.", BundleException.RESOLVE_ERROR, e); //$NON-NLS-1$
- } catch (ResolverHookException e) {
- throw new BundleException("Unexpected resolution exception.", BundleException.REJECTED_BY_HOOK, e.getCause()); //$NON-NLS-1$
- }
-
- }
-
- if ((options & START_ACTIVATION_POLICY) != 0 && (bundledata.getStatus() & Constants.BUNDLE_LAZY_START) != 0) {
- // the bundle must use the activation policy here.
- if ((state & RESOLVED) != 0) {
- // now we must publish the LAZY_ACTIVATION event and return
- state = STARTING;
- // release the state change lock before sending lazy activation event (bug 258659)
- completeStateChange();
- framework.publishBundleEvent(BundleEvent.LAZY_ACTIVATION, this);
- }
- return;
- }
-
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Bundle: Active sl = " + framework.startLevelManager.getStartLevel() + "; Bundle " + getBundleId() + " sl = " + getInternalStartLevel()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- if ((options & LAZY_TRIGGER) != 0) {
- if ((state & RESOLVED) != 0) {
- // Should publish the lazy activation event here before the starting event
- // This can happen if another bundle in the same start-level causes a class load from the lazy start bundle.
- state = STARTING;
- // release the state change lock before sending lazy activation event (bug 258659)
- completeStateChange();
- framework.publishBundleEvent(BundleEvent.LAZY_ACTIVATION, this);
- beginStateChange();
- if (state != STARTING) {
- // while firing the LAZY_ACTIVATION event some one else caused the bundle to transition
- // out of STARTING. This could have happened because some listener called start on the bundle
- // or another class load could have caused the start trigger to get fired again.
- return;
- }
- }
- }
- state = STARTING;
- framework.publishBundleEvent(BundleEvent.STARTING, this);
- context = getContext();
- //STARTUP TIMING Start here
- long start = 0;
-
- BundleWatcher bundleStats = framework.adaptor.getBundleWatcher();
- if (bundleStats != null)
- bundleStats.watchBundle(this, BundleWatcher.START_ACTIVATION);
- if (Debug.DEBUG_BUNDLE_TIME) {
- start = System.currentTimeMillis();
- System.out.println("Starting " + getSymbolicName()); //$NON-NLS-1$
- }
-
- try {
- context.start();
- startHook();
- if (framework.active) {
- state = ACTIVE;
-
- if (Debug.DEBUG_GENERAL) {
- Debug.println("->started " + this); //$NON-NLS-1$
- }
- // release the state change lock before sending lazy activation event (bug 258659)
- completeStateChange();
- framework.publishBundleEvent(BundleEvent.STARTED, this);
- }
-
- } catch (BundleException e) {
- // we must fire the stopping event
- state = STOPPING;
- framework.publishBundleEvent(BundleEvent.STOPPING, this);
-
- stopHook();
- context.close();
- context = null;
-
- state = RESOLVED;
- // if this is a lazy start bundle that fails to start then
- // we must fire the stopped event
- framework.publishBundleEvent(BundleEvent.STOPPED, this);
- throw e;
- } finally {
- if (bundleStats != null)
- bundleStats.watchBundle(this, BundleWatcher.END_ACTIVATION);
- if (Debug.DEBUG_BUNDLE_TIME)
- System.out.println("End starting " + getSymbolicName() + " " + (System.currentTimeMillis() - start)); //$NON-NLS-1$ //$NON-NLS-2$
-
- }
-
- if (state == UNINSTALLED) {
- context.close();
- context = null;
- throw new BundleException(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, getBundleData().getLocation()), BundleException.STATECHANGE_ERROR);
- }
- }
-
- /**
- * @throws BundleException
- */
- protected void startHook() throws BundleException {
- // do nothing by default
- }
-
- protected boolean readyToResume() {
- // Return false if the bundle is not at the correct start-level
- if (getInternalStartLevel() > framework.startLevelManager.getStartLevel())
- return false;
- int status = bundledata.getStatus();
- // Return false if the bundle is not persistently marked for start
- if ((status & Constants.BUNDLE_STARTED) == 0)
- return false;
- if ((status & Constants.BUNDLE_ACTIVATION_POLICY) == 0 || (status & Constants.BUNDLE_LAZY_START) == 0 || isLazyTriggerSet())
- return true;
- if (!isResolved()) {
- if (framework.getAdaptor().getState().isResolved() || !framework.packageAdmin.resolveBundles(new Bundle[] {this}))
- // should never transition from UNRESOLVED -> STARTING
- return false;
- }
- // now we can publish the LAZY_ACTIVATION event
- state = STARTING;
- // release the state change lock before sending lazy activation event (bug 258659)
- completeStateChange();
- framework.publishBundleEvent(BundleEvent.LAZY_ACTIVATION, this);
- return false;
- }
-
- private synchronized boolean isLazyTriggerSet() {
- if (proxy == null)
- return false;
- BundleLoader loader = proxy.getBasicBundleLoader();
- return loader != null ? loader.isLazyTriggerSet() : false;
- }
-
- /**
- * Create a BundleContext for this bundle.
- *
- * @return BundleContext for this bundle.
- */
- protected BundleContextImpl createContext() {
- return (new BundleContextImpl(this));
- }
-
- /**
- * Return the current context for this bundle.
- *
- * @return BundleContext for this bundle.
- */
- protected synchronized BundleContextImpl getContext() {
- if (context == null) {
- // only create the context if we are starting, active or stopping
- // this is so that SCR can get the context for lazy-start bundles
- if ((state & (STARTING | ACTIVE | STOPPING)) != 0)
- context = createContext();
- }
- return (context);
- }
-
- /**
- * Internal worker to stop a bundle.
- *
- * @param options the stop options
- */
- protected void stopWorker(int options) throws BundleException {
- if ((options & STOP_TRANSIENT) == 0) {
- setStatus(Constants.BUNDLE_STARTED, false);
- setStatus(Constants.BUNDLE_ACTIVATION_POLICY, false);
- if (Debug.MONITOR_ACTIVATION)
- new Exception("A persistent start has been called on bundle: " + getBundleData()).printStackTrace(); //$NON-NLS-1$
- }
- if (framework.active) {
- if ((state & (STOPPING | RESOLVED | INSTALLED)) != 0) {
- return;
- }
-
- BundleWatcher bundleStats = framework.adaptor.getBundleWatcher();
- if (bundleStats != null)
- bundleStats.watchBundle(this, BundleWatcher.START_DEACTIVATION);
-
- state = STOPPING;
- framework.publishBundleEvent(BundleEvent.STOPPING, this);
- try {
- // context may be null if a lazy-start bundle is STARTING
- if (context != null)
- context.stop();
- } finally {
- stopHook();
- if (context != null) {
- context.close();
- context = null;
- }
-
- checkValid();
-
- state = RESOLVED;
-
- if (Debug.DEBUG_GENERAL) {
- Debug.println("->stopped " + this); //$NON-NLS-1$
- }
-
- framework.publishBundleEvent(BundleEvent.STOPPED, this);
- if (bundleStats != null)
- bundleStats.watchBundle(this, BundleWatcher.END_DEACTIVATION);
-
- }
- }
- }
-
- /**
- * @throws BundleException
- */
- protected void stopHook() throws BundleException {
- // do nothing
- }
-
- /**
- * Provides a list of {@link ServiceReference}s for the services
- * registered by this bundle
- * or <code>null</code> if the bundle has no registered
- * services.
- *
- * <p>The list is valid at the time
- * of the call to this method, but the framework is a very dynamic
- * environment and services can be modified or unregistered at anytime.
- *
- * @return An array of {@link ServiceReference} or <code>null</code>.
- * @exception java.lang.IllegalStateException If the
- * bundle has been uninstalled.
- * @see ServiceRegistration
- * @see ServiceReference
- */
- public ServiceReference<?>[] getRegisteredServices() {
- checkValid();
-
- if (context == null) {
- return null;
- }
-
- return context.getFramework().getServiceRegistry().getRegisteredServices(context);
- }
-
- /**
- * Provides a list of {@link ServiceReference}s for the
- * services this bundle is using,
- * or <code>null</code> if the bundle is not using any services.
- * A bundle is considered to be using a service if the bundle's
- * use count for the service is greater than zero.
- *
- * <p>The list is valid at the time
- * of the call to this method, but the framework is a very dynamic
- * environment and services can be modified or unregistered at anytime.
- *
- * @return An array of {@link ServiceReference} or <code>null</code>.
- * @exception java.lang.IllegalStateException If the
- * bundle has been uninstalled.
- * @see ServiceReference
- */
- public ServiceReference<?>[] getServicesInUse() {
- checkValid();
-
- if (context == null) {
- return null;
- }
-
- return context.getFramework().getServiceRegistry().getServicesInUse(context);
- }
-
- public BundleFragment[] getFragments() {
- synchronized (framework.bundles) {
- if (fragments == null)
- return null;
- BundleFragment[] result = new BundleFragment[fragments.length];
- System.arraycopy(fragments, 0, result, 0, result.length);
- return result;
- }
- }
-
- /**
- * Attaches a fragment to this BundleHost. Fragments must be attached to
- * the host by ID order. If the ClassLoader of the host is already created
- * then the fragment must be attached to the host ClassLoader
- * @param fragment The fragment bundle to attach
- * return true if the fragment successfully attached; false if the fragment
- * could not be logically inserted at the end of the fragment chain.
- */
- protected void attachFragment(BundleFragment fragment) throws BundleException {
- // do not force the creation of the bundle loader here
- BundleLoader loader = getLoaderProxy().getBasicBundleLoader();
- // If the Host ClassLoader exists then we must attach
- // the fragment to the ClassLoader.
- if (loader != null)
- loader.attachFragment(fragment);
-
- if (fragments == null) {
- fragments = new BundleFragment[] {fragment};
- } else {
- boolean inserted = false;
- // We must keep our fragments ordered by bundle ID; or
- // install order.
- BundleFragment[] newFragments = new BundleFragment[fragments.length + 1];
- for (int i = 0; i < fragments.length; i++) {
- if (fragment == fragments[i])
- return; // this fragment is already attached
- // need to flush the other attached fragment manifest caches in case the attaching fragment provides translations (bug 339211)
- fragments[i].manifestLocalization = null;
- if (!inserted && fragment.getBundleId() < fragments[i].getBundleId()) {
- // if the loader has already been created
- // then we cannot attach a fragment into the middle
- // of the fragment chain.
- if (loader != null) {
- throw new BundleException(NLS.bind(Msg.BUNDLE_LOADER_ATTACHMENT_ERROR, fragments[i].getSymbolicName(), getSymbolicName()), BundleException.INVALID_OPERATION);
- }
- newFragments[i] = fragment;
- inserted = true;
- }
- newFragments[inserted ? i + 1 : i] = fragments[i];
- }
- if (!inserted)
- newFragments[newFragments.length - 1] = fragment;
- fragments = newFragments;
- }
- // need to flush the manifest cache in case the attaching fragment provides translations
- manifestLocalization = null;
- }
-
- protected BundleLoader getBundleLoader() {
- BundleLoaderProxy curProxy = getLoaderProxy();
- return curProxy == null ? null : curProxy.getBundleLoader();
- }
-
- public synchronized BundleLoaderProxy getLoaderProxy() {
- if (proxy != null)
- return proxy;
- BundleDescription bundleDescription = getBundleDescription();
- if (bundleDescription == null)
- return null;
- proxy = new BundleLoaderProxy(this, bundleDescription);
- // Note that BundleLoaderProxy is a BundleReference
- // this is necessary to ensure the resolver can continue
- // to provide BundleRevision objects to resolver hooks.
- bundleDescription.setUserObject(proxy);
- return proxy;
- }
-
- /**
- * Gets the class loader for the host bundle. This may end up
- * creating the bundle class loader if it was not already created.
- * A null value may be returned if the bundle is not resolved.
- * @return the bundle class loader or null if the bundle is not resolved.
- */
- public ClassLoader getClassLoader() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new RuntimePermission("getClassLoader")); //$NON-NLS-1$
- BundleLoaderProxy curProxy = getLoaderProxy();
- BundleLoader loader = curProxy == null ? null : curProxy.getBundleLoader();
- BundleClassLoader bcl = loader == null ? null : loader.createClassLoader();
- return (bcl instanceof ClassLoader) ? (ClassLoader) bcl : null;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleRepository.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleRepository.java
deleted file mode 100644
index f10edf828..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleRepository.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Rob Harrop - SpringSource Inc. (bug 247521)
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.util.*;
-import org.eclipse.osgi.framework.util.KeyedHashSet;
-import org.osgi.framework.Version;
-
-/**
- * The BundleRepository holds all installed Bundle object for the
- * Framework. The BundleRepository is also used to mark and unmark
- * bundle dependancies.
- *
- * <p>
- * This class is internally synchronized and supports client locking. Clients
- * wishing to perform threadsafe composite operations on instances of this
- * class can synchronize on the instance itself when doing these operations.
- */
-public final class BundleRepository {
- /** bundles by install order */
- private List<AbstractBundle> bundlesByInstallOrder;
-
- /** bundles keyed by bundle Id */
- private KeyedHashSet bundlesById;
-
- /** bundles keyed by SymbolicName */
- private Map<String, AbstractBundle[]> bundlesBySymbolicName;
-
- public BundleRepository(int initialCapacity) {
- synchronized (this) {
- bundlesByInstallOrder = new ArrayList<AbstractBundle>(initialCapacity);
- bundlesById = new KeyedHashSet(initialCapacity, true);
- bundlesBySymbolicName = new HashMap<String, AbstractBundle[]>(initialCapacity);
- }
- }
-
- /**
- * Gets a list of bundles ordered by install order.
- * @return List of bundles by install order.
- */
- public synchronized List<AbstractBundle> getBundles() {
- return bundlesByInstallOrder;
- }
-
- /**
- * Gets a bundle by its bundle Id.
- * @param bundleId
- * @return a bundle with the specified id or null if one does not exist
- */
- public synchronized AbstractBundle getBundle(long bundleId) {
- Long key = new Long(bundleId);
- return (AbstractBundle) bundlesById.getByKey(key);
- }
-
- public synchronized AbstractBundle[] getBundles(String symbolicName) {
- if (Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName))
- symbolicName = Constants.getInternalSymbolicName();
- return bundlesBySymbolicName.get(symbolicName);
- }
-
- @SuppressWarnings("unchecked")
- public synchronized List<AbstractBundle> getBundles(String symbolicName, Version version) {
- AbstractBundle[] bundles = getBundles(symbolicName);
- List<AbstractBundle> result = null;
- if (bundles != null) {
- if (bundles.length > 0) {
- for (int i = 0; i < bundles.length; i++) {
- if (bundles[i].getVersion().equals(version)) {
- if (result == null)
- result = new ArrayList<AbstractBundle>();
- result.add(bundles[i]);
- }
- }
- }
- }
- return result == null ? Collections.EMPTY_LIST : result;
- }
-
- public synchronized void add(AbstractBundle bundle) {
- bundlesByInstallOrder.add(bundle);
- bundlesById.add(bundle);
- addSymbolicName(bundle);
- }
-
- private void addSymbolicName(AbstractBundle bundle) {
- String symbolicName = bundle.getSymbolicName();
- if (symbolicName == null)
- return;
- AbstractBundle[] bundles = bundlesBySymbolicName.get(symbolicName);
- if (bundles == null) {
- // making the initial capacity on this 1 since it
- // should be rare that multiple version exist
- bundles = new AbstractBundle[1];
- bundles[0] = bundle;
- bundlesBySymbolicName.put(symbolicName, bundles);
- return;
- }
-
- List<AbstractBundle> list = new ArrayList<AbstractBundle>(bundles.length + 1);
- // find place to insert the bundle
- Version newVersion = bundle.getVersion();
- boolean added = false;
- for (int i = 0; i < bundles.length; i++) {
- AbstractBundle oldBundle = bundles[i];
- Version oldVersion = oldBundle.getVersion();
- if (!added && newVersion.compareTo(oldVersion) >= 0) {
- added = true;
- list.add(bundle);
- }
- list.add(oldBundle);
- }
- if (!added) {
- list.add(bundle);
- }
-
- bundles = new AbstractBundle[list.size()];
- list.toArray(bundles);
- bundlesBySymbolicName.put(symbolicName, bundles);
- }
-
- public synchronized boolean remove(AbstractBundle bundle) {
- // remove by bundle ID
- boolean found = bundlesById.remove(bundle);
- if (!found)
- return false;
-
- // remove by install order
- bundlesByInstallOrder.remove(bundle);
- // remove by symbolic name
- String symbolicName = bundle.getSymbolicName();
- if (symbolicName == null)
- return true;
- removeSymbolicName(symbolicName, bundle);
- return true;
- }
-
- private void removeSymbolicName(String symbolicName, AbstractBundle bundle) {
- AbstractBundle[] bundles = bundlesBySymbolicName.get(symbolicName);
- if (bundles == null)
- return;
-
- // found some bundles with the global name.
- // remove all references to the specified bundle.
- int numRemoved = 0;
- for (int i = 0; i < bundles.length; i++) {
- if (bundle == bundles[i]) {
- numRemoved++;
- bundles[i] = null;
- }
- }
- if (numRemoved > 0) {
- if (bundles.length - numRemoved <= 0) {
- // no bundles left in the array remove the array from the hash
- bundlesBySymbolicName.remove(symbolicName);
- } else {
- // create a new array with the null entries removed.
- AbstractBundle[] newBundles = new AbstractBundle[bundles.length - numRemoved];
- int indexCnt = 0;
- for (int i = 0; i < bundles.length; i++) {
- if (bundles[i] != null) {
- newBundles[indexCnt] = bundles[i];
- indexCnt++;
- }
- }
- bundlesBySymbolicName.put(symbolicName, newBundles);
- }
- }
- }
-
- public synchronized void update(String oldSymbolicName, AbstractBundle bundle) {
- if (oldSymbolicName != null) {
- if (!oldSymbolicName.equals(bundle.getSymbolicName())) {
- removeSymbolicName(oldSymbolicName, bundle);
- addSymbolicName(bundle);
- }
- } else {
- addSymbolicName(bundle);
- }
- }
-
- public synchronized void removeAllBundles() {
- bundlesByInstallOrder.clear();
- bundlesById = new KeyedHashSet();
- bundlesBySymbolicName.clear();
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleSource.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleSource.java
deleted file mode 100644
index a27e1ee9a..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleSource.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URLConnection;
-
-/**
- * BundleSource class to wrap in InputStream.
- *
- * <p>This class implements a URLConnection which
- * wraps an InputStream.
- */
-public class BundleSource extends URLConnection {
- private InputStream in;
-
- protected BundleSource(InputStream in) {
- super(null);
- this.in = in;
- }
-
- /**
- * @throws IOException
- */
- public void connect() throws IOException {
- connected = true;
- }
-
- /**
- * @throws IOException
- */
- public InputStream getInputStream() throws IOException {
- return (in);
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Constants.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Constants.java
deleted file mode 100644
index 1bd279453..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Constants.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-/**
- * This interface contains the constants used by the eclipse
- * OSGi implementation.
- */
-
-public class Constants implements org.osgi.framework.Constants {
- /** Default framework version */
- public static final String OSGI_FRAMEWORK_VERSION = "1.3"; //$NON-NLS-1$
-
- /** Framework vendor */
- public static final String OSGI_FRAMEWORK_VENDOR = "Eclipse"; //$NON-NLS-1$
-
- /** Bundle manifest name */
- public static final String OSGI_BUNDLE_MANIFEST = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
-
- /** OSGi framework package name. */
- public static final String OSGI_FRAMEWORK_PACKAGE = "org.osgi.framework"; //$NON-NLS-1$
-
- /** Bundle resource URL protocol */
- public static final String OSGI_RESOURCE_URL_PROTOCOL = "bundleresource"; //$NON-NLS-1$
-
- /** Bundle entry URL protocol */
- public static final String OSGI_ENTRY_URL_PROTOCOL = "bundleentry"; //$NON-NLS-1$
-
- /** Processor aliases resource */
- public static final String OSGI_PROCESSOR_ALIASES = "processor.aliases"; //$NON-NLS-1$
-
- /** OS name aliases resource */
- public static final String OSGI_OSNAME_ALIASES = "osname.aliases"; //$NON-NLS-1$
-
- /** Default permissions for bundles with no permission set
- * and there are no default permissions set.
- */
- public static final String OSGI_DEFAULT_DEFAULT_PERMISSIONS = "default.permissions"; //$NON-NLS-1$
-
- /** Base implied permissions for all bundles */
- public static final String OSGI_BASE_IMPLIED_PERMISSIONS = "implied.permissions"; //$NON-NLS-1$
-
- /** Name of OSGi LogService */
- public static final String OSGI_LOGSERVICE_NAME = "org.osgi.service.log.LogService"; //$NON-NLS-1$
-
- /** Name of OSGi PackageAdmin */
- public static final String OSGI_PACKAGEADMIN_NAME = "org.osgi.service.packageadmin.PackageAdmin"; //$NON-NLS-1$
-
- /** Name of OSGi PermissionAdmin */
- public static final String OSGI_PERMISSIONADMIN_NAME = "org.osgi.service.permissionadmin.PermissionAdmin"; //$NON-NLS-1$
-
- /** Name of OSGi StartLevel */
- public static final String OSGI_STARTLEVEL_NAME = "org.osgi.service.startlevel.StartLevel"; //$NON-NLS-1$
-
- /** JVM java.vm.name property name */
- public static final String JVM_VM_NAME = "java.vm.name"; //$NON-NLS-1$
-
- /** JVM os.arch property name */
- public static final String JVM_OS_ARCH = "os.arch"; //$NON-NLS-1$
-
- /** JVM os.name property name */
- public static final String JVM_OS_NAME = "os.name"; //$NON-NLS-1$
-
- /** JVM os.version property name */
- public static final String JVM_OS_VERSION = "os.version"; //$NON-NLS-1$
-
- /** JVM user.language property name */
- public static final String JVM_USER_LANGUAGE = "user.language"; //$NON-NLS-1$
-
- /** JVM user.region property name */
- public static final String JVM_USER_REGION = "user.region"; //$NON-NLS-1$
-
- /** J2ME configuration property name */
- public static final String J2ME_MICROEDITION_CONFIGURATION = "microedition.configuration"; //$NON-NLS-1$
-
- /** J2ME profile property name */
- public static final String J2ME_MICROEDITION_PROFILES = "microedition.profiles"; //$NON-NLS-1$
-
- /** Persistent start bundle status */
- public static final int BUNDLE_STARTED = 0x00000001;
- /** Lazy start flag bundle status */
- public static final int BUNDLE_LAZY_START = 0x00000002;
- public static final int BUNDLE_ACTIVATION_POLICY = 0x00000004;
-
- /** Property file locations and default names. */
- public static final String OSGI_PROPERTIES = "osgi.framework.properties"; //$NON-NLS-1$
- public static final String DEFAULT_OSGI_PROPERTIES = "osgi.properties"; //$NON-NLS-1$
-
- private static String INTERNAL_SYSTEM_BUNDLE = "org.eclipse.osgi"; //$NON-NLS-1$
-
- public static String getInternalSymbolicName() {
- return INTERNAL_SYSTEM_BUNDLE;
- }
-
- static void setInternalSymbolicName(String name) {
- INTERNAL_SYSTEM_BUNDLE = name;
- }
-
- /** OSGI implementation version properties key */
- public static final String OSGI_IMPL_VERSION_KEY = "osgi.framework.version"; //$NON-NLS-1$
- /** OSGi java profile; used to give a URL to a java profile */
- public static final String OSGI_JAVA_PROFILE = "osgi.java.profile"; //$NON-NLS-1$
- public static final String OSGI_JAVA_PROFILE_NAME = "osgi.java.profile.name"; //$NON-NLS-1$
- /**
- * OSGi java profile bootdelegation; used to indicate how the org.osgi.framework.bootdelegation
- * property defined in the java profile should be processed, (ingnore, override, none). default is ignore
- */
- public static final String OSGI_JAVA_PROFILE_BOOTDELEGATION = "osgi.java.profile.bootdelegation"; //$NON-NLS-1$
- /** indicates that the org.osgi.framework.bootdelegation in the java profile should be ingored */
- public static final String OSGI_BOOTDELEGATION_IGNORE = "ignore"; //$NON-NLS-1$
- /** indicates that the org.osgi.framework.bootdelegation in the java profile should override the system property */
- public static final String OSGI_BOOTDELEGATION_OVERRIDE = "override"; //$NON-NLS-1$
- /** indicates that the org.osgi.framework.bootdelegation in the java profile AND the system properties should be ignored */
- public static final String OSGI_BOOTDELEGATION_NONE = "none"; //$NON-NLS-1$
- /** OSGi strict delegation **/
- public static final String OSGI_RESOLVER_MODE = "osgi.resolverMode"; //$NON-NLS-1$
- public static final String STRICT_MODE = "strict"; //$NON-NLS-1$
- public static final String DEVELOPMENT_MODE = "development"; //$NON-NLS-1$
-
- public static final String STATE_SYSTEM_BUNDLE = "osgi.system.bundle"; //$NON-NLS-1$
-
- public static final String PROP_OSGI_RELAUNCH = "osgi.framework.relaunch"; //$NON-NLS-1$
-
- public static String OSGI_COMPATIBILITY_BOOTDELEGATION = "osgi.compatibility.bootdelegation"; //$NON-NLS-1$
-
- /** Eclipse-SystemBundle header */
- public static final String ECLIPSE_SYSTEMBUNDLE = "Eclipse-SystemBundle"; //$NON-NLS-1$
- public static final String ECLIPSE_PLATFORMFILTER = "Eclipse-PlatformFilter"; //$NON-NLS-1$
- public static final String Eclipse_JREBUNDLE = "Eclipse-JREBundle"; //$NON-NLS-1$
- /**
- * Manifest Export-Package directive indicating that the exported package should only
- * be made available when the resolver is not in strict mode.
- */
- public static final String INTERNAL_DIRECTIVE = "x-internal"; //$NON-NLS-1$
-
- /**
- * Manifest Export-Package directive indicating that the exported package should only
- * be made available to friends of the exporting bundle.
- */
- public static final String FRIENDS_DIRECTIVE = "x-friends"; //$NON-NLS-1$
-
- /**
- * Manifest header (named &quot;Provide-Package&quot;)
- * identifying the packages name
- * provided to other bundles which require the bundle.
- *
- * <p>
- * NOTE: this is only used for backwards compatibility, bundles manifest using
- * syntax version 2 will not recognize this header.
- *
- * <p>The attribute value may be retrieved from the
- * <tt>Dictionary</tt> object returned by the <tt>Bundle.getHeaders</tt> method.
- * @deprecated
- */
- public final static String PROVIDE_PACKAGE = "Provide-Package"; //$NON-NLS-1$
-
- /**
- * Manifest header attribute (named &quot;reprovide&quot;)
- * for Require-Bundle
- * identifying that any packages that are provided
- * by the required bundle must be reprovided by the requiring bundle.
- * The default value is <tt>false</tt>.
- * <p>
- * The attribute value is encoded in the Require-Bundle manifest
- * header like:
- * <pre>
- * Require-Bundle: com.acme.module.test; reprovide="true"
- * </pre>
- * <p>
- * NOTE: this is only used for backwards compatibility, bundles manifest using
- * syntax version 2 will not recognize this attribute.
- * @deprecated
- */
- public final static String REPROVIDE_ATTRIBUTE = "reprovide"; //$NON-NLS-1$
-
- /**
- * Manifest header attribute (named &quot;optional&quot;)
- * for Require-Bundle
- * identifying that a required bundle is optional and that
- * the requiring bundle can be resolved if there is no
- * suitable required bundle.
- * The default value is <tt>false</tt>.
- *
- * <p>The attribute value is encoded in the Require-Bundle manifest
- * header like:
- * <pre>
- * Require-Bundle: com.acme.module.test; optional="true"
- * </pre>
- * <p>
- * NOTE: this is only used for backwards compatibility, bundles manifest using
- * syntax version 2 will not recognize this attribute.
- * @since 1.3 <b>EXPERIMENTAL</b>
- * @deprecated
- */
- public final static String OPTIONAL_ATTRIBUTE = "optional"; //$NON-NLS-1$
-
- /**
- * The key used to designate the buddy loader associated with a given bundle.
- */
- public final static String BUDDY_LOADER = "Eclipse-BuddyPolicy"; //$NON-NLS-1$
-
- public final static String REGISTERED_POLICY = "Eclipse-RegisterBuddy"; //$NON-NLS-1$
-
- static public final String INTERNAL_HANDLER_PKGS = "equinox.interal.handler.pkgs"; //$NON-NLS-1$
-
- // TODO rename it to Eclipse-PluginClass
- public static final String PLUGIN_CLASS = "Plugin-Class"; //$NON-NLS-1$
-
- /** Manifest header used to specify the lazy start properties of a bundle */
- public static final String ECLIPSE_LAZYSTART = "Eclipse-LazyStart"; //$NON-NLS-1$
-
- /** An Eclipse-LazyStart attribute used to specify exception classes for auto start */
- public static final String ECLIPSE_LAZYSTART_EXCEPTIONS = "exceptions"; //$NON-NLS-1$
-
- /**
- * Manifest header used to specify the auto start properties of a bundle
- * @deprecated use {@link #ECLIPSE_LAZYSTART}
- */
- public static final String ECLIPSE_AUTOSTART = "Eclipse-AutoStart"; //$NON-NLS-1$
-
- /**
- * @deprecated use {@link #ECLIPSE_LAZYSTART_EXCEPTIONS}
- */
- public static final String ECLIPSE_AUTOSTART_EXCEPTIONS = ECLIPSE_LAZYSTART_EXCEPTIONS;
-
- /**
- * Framework launching property specifying whether Equinox's FrameworkWiring
- * implementation should refresh bundles with equal symbolic names.
- *
- * <p>
- * Default value is <b>TRUE</b> in this release of the Equinox.
- * This default may change to <b>FALSE</b> in a future Equinox release.
- * Therefore, code must not assume the default behavior is
- * <b>TRUE</b> and should interrogate the value of this property to
- * determine the behavior.
- *
- * <p>
- * The value of this property may be retrieved by calling the
- * {@code BundleContext.getProperty} method.
- * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=351519">bug 351519</a>
- * @since 3.7.1
- */
- public static final String REFRESH_DUPLICATE_BSN = "equinox.refresh.duplicate.bsn"; //$NON-NLS-1$
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java
deleted file mode 100644
index 986de041d..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.internal.serviceregistry.*;
-import org.eclipse.osgi.service.resolver.ResolverHookException;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.hooks.resolver.ResolverHook;
-import org.osgi.framework.hooks.resolver.ResolverHookFactory;
-import org.osgi.framework.wiring.*;
-
-/**
- * This class encapsulates the delegation to ResolverHooks that are registered with the service
- * registry. This way the resolver implementation only has to call out to a single hook
- * which does all the necessary service registry lookups.
- *
- * This class is not thread safe and expects external synchronization.
- *
- */
-public class CoreResolverHookFactory implements ResolverHookFactory {
- // need a tuple to hold the service reference and hook object
- // do not use a map for performance reasons; no need to hash based on a key.
- static class HookReference {
- public HookReference(ServiceReferenceImpl<ResolverHookFactory> reference, ResolverHook hook) {
- this.reference = reference;
- this.hook = hook;
- }
-
- final ServiceReferenceImpl<ResolverHookFactory> reference;
- final ResolverHook hook;
- }
-
- private final BundleContextImpl context;
- private final ServiceRegistry registry;
-
- public CoreResolverHookFactory(BundleContextImpl context, ServiceRegistry registry) {
- this.context = context;
- this.registry = registry;
- }
-
- void handleHookException(Throwable t, Object hook, String method) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println(hook.getClass().getName() + "." + method + "() exception:"); //$NON-NLS-1$ //$NON-NLS-2$
- if (t != null)
- Debug.printStackTrace(t);
- }
- String message = NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, hook.getClass().getName(), method);
- throw new ResolverHookException(message, t);
- }
-
- private ServiceReferenceImpl<ResolverHookFactory>[] getHookReferences() {
- try {
- @SuppressWarnings("unchecked")
- ServiceReferenceImpl<ResolverHookFactory>[] result = (ServiceReferenceImpl<ResolverHookFactory>[]) registry.getServiceReferences(context, ResolverHookFactory.class.getName(), null, false, false);
- return result;
- } catch (InvalidSyntaxException e) {
- // cannot happen; no filter
- return null;
- }
- }
-
- public ResolverHook begin(Collection<BundleRevision> triggers) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("ResolverHook.begin"); //$NON-NLS-1$
- }
- ServiceReferenceImpl<ResolverHookFactory>[] refs = getHookReferences();
- @SuppressWarnings("unchecked")
- List<HookReference> hookRefs = refs == null ? Collections.EMPTY_LIST : new ArrayList<CoreResolverHookFactory.HookReference>(refs.length);
- if (refs != null)
- for (ServiceReferenceImpl<ResolverHookFactory> hookRef : refs) {
- ResolverHookFactory factory = context.getService(hookRef);
- if (factory != null) {
- try {
- ResolverHook hook = factory.begin(triggers);
- if (hook != null)
- hookRefs.add(new HookReference(hookRef, hook));
- } catch (Throwable t) {
- // need to force an end call on the ResolverHooks we got and release them
- try {
- new CoreResolverHook(hookRefs).end();
- } catch (Throwable endError) {
- // we are already in failure mode; just continue
- }
- handleHookException(t, factory, "begin"); //$NON-NLS-1$
- }
- }
- }
- return new CoreResolverHook(hookRefs);
- }
-
- void releaseHooks(List<HookReference> hookRefs) {
- for (HookReference hookRef : hookRefs)
- context.ungetService(hookRef.reference);
- hookRefs.clear();
- }
-
- class CoreResolverHook implements ResolverHook {
- private final List<HookReference> hooks;
-
- CoreResolverHook(List<HookReference> hooks) {
- this.hooks = hooks;
- }
-
- public void filterResolvable(Collection<BundleRevision> candidates) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("ResolverHook.filterResolvable(" + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (hooks.isEmpty())
- return;
- candidates = new ShrinkableCollection<BundleRevision>(candidates);
- for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
- HookReference hookRef = iHooks.next();
- if (hookRef.reference.getBundle() == null) {
- handleHookException(null, hookRef.hook, "filterResolvable"); //$NON-NLS-1$
- } else {
- try {
- hookRef.hook.filterResolvable(candidates);
- } catch (Throwable t) {
- handleHookException(t, hookRef.hook, "filterResolvable"); //$NON-NLS-1$
- }
- }
- }
- }
-
- public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("ResolverHook.filterSingletonCollisions(" + singleton + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- if (hooks.isEmpty())
- return;
- collisionCandidates = new ShrinkableCollection<BundleCapability>(collisionCandidates);
- for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
- HookReference hookRef = iHooks.next();
- if (hookRef.reference.getBundle() == null) {
- handleHookException(null, hookRef.hook, "filterSingletonCollisions"); //$NON-NLS-1$
- } else {
- try {
- hookRef.hook.filterSingletonCollisions(singleton, collisionCandidates);
- } catch (Throwable t) {
- handleHookException(t, hookRef.hook, "filterSingletonCollisions"); //$NON-NLS-1$
- }
- }
- }
- }
-
- public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("ResolverHook.filterMatches(" + requirement + ", " + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- if (hooks.isEmpty())
- return;
- candidates = new ShrinkableCollection<BundleCapability>(candidates);
- for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
- HookReference hookRef = iHooks.next();
- if (hookRef.reference.getBundle() == null) {
- handleHookException(null, hookRef.hook, "filterMatches"); //$NON-NLS-1$
- } else {
- try {
- hookRef.hook.filterMatches(requirement, candidates);
- } catch (Throwable t) {
- handleHookException(t, hookRef.hook, "filterMatches"); //$NON-NLS-1$
- }
- }
- }
- }
-
- public void end() {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("ResolverHook.end"); //$NON-NLS-1$
- }
- if (hooks.isEmpty())
- return;
- try {
- HookReference missingHook = null;
- Throwable endError = null;
- HookReference endBadHook = null;
- for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) {
- HookReference hookRef = iHooks.next();
- // We do not remove unregistered services here because we are going to remove all of them at the end
- if (hookRef.reference.getBundle() == null) {
- if (missingHook == null)
- missingHook = hookRef;
- } else {
- try {
- hookRef.hook.end();
- } catch (Throwable t) {
- // Must continue on to the next hook.end method
- // save the error for throwing at the end
- if (endError == null) {
- endError = t;
- endBadHook = hookRef;
- }
- }
- }
- }
- if (missingHook != null)
- handleHookException(null, missingHook.hook, "end"); //$NON-NLS-1$
- if (endError != null)
- handleHookException(endError, endBadHook.hook, "end"); //$NON-NLS-1$
- } finally {
- releaseHooks(hooks);
- }
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/EquinoxLauncher.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/EquinoxLauncher.java
deleted file mode 100644
index 2b71f2467..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/EquinoxLauncher.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.net.URL;
-import java.security.*;
-import java.security.cert.X509Certificate;
-import java.util.*;
-import org.eclipse.core.runtime.adaptor.EclipseStarter;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.osgi.framework.*;
-
-public class EquinoxLauncher implements org.osgi.framework.launch.Framework {
-
- private volatile Framework framework;
- private volatile Bundle systemBundle;
- private final Map<String, String> configuration;
- private volatile ConsoleManager consoleMgr = null;
-
- public EquinoxLauncher(Map<String, String> configuration) {
- this.configuration = configuration;
- }
-
- public void init() {
- checkAdminPermission(AdminPermission.EXECUTE);
- if (System.getSecurityManager() == null)
- internalInit();
- else {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- internalInit();
- return null;
- }
- });
- }
- }
-
- synchronized Framework internalInit() {
- if ((getState() & (Bundle.ACTIVE | Bundle.STARTING | Bundle.STOPPING)) != 0)
- return framework; // no op
-
- if (System.getSecurityManager() != null && configuration.get(Constants.FRAMEWORK_SECURITY) != null)
- throw new SecurityException("Cannot specify the \"" + Constants.FRAMEWORK_SECURITY + "\" configuration property when a security manager is already installed."); //$NON-NLS-1$ //$NON-NLS-2$
-
- Framework current = framework;
- if (current != null) {
- current.close();
- framework = null;
- systemBundle = null;
- }
- ClassLoader tccl = Thread.currentThread().getContextClassLoader();
- try {
- FrameworkProperties.setProperties(configuration);
- FrameworkProperties.initializeProperties();
- // make sure the active framework thread is used
- setEquinoxProperties(configuration);
- current = new Framework(new BaseAdaptor(new String[0]));
- consoleMgr = ConsoleManager.startConsole(current);
- current.launch();
- framework = current;
- systemBundle = current.systemBundle;
- } finally {
- ClassLoader currentCCL = Thread.currentThread().getContextClassLoader();
- if (currentCCL != tccl)
- Thread.currentThread().setContextClassLoader(tccl);
- }
- return current;
- }
-
- private void setEquinoxProperties(Map<String, String> configuration) {
- Object threadBehavior = configuration == null ? null : configuration.get(Framework.PROP_FRAMEWORK_THREAD);
- if (threadBehavior == null) {
- if (FrameworkProperties.getProperty(Framework.PROP_FRAMEWORK_THREAD) == null)
- FrameworkProperties.setProperty(Framework.PROP_FRAMEWORK_THREAD, Framework.THREAD_NORMAL);
- } else {
- FrameworkProperties.setProperty(Framework.PROP_FRAMEWORK_THREAD, (String) threadBehavior);
- }
-
- // set the compatibility boot delegation flag to false to get "standard" OSGi behavior WRT boot delegation (bug 344850)
- if (FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION) == null)
- FrameworkProperties.setProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "false"); //$NON-NLS-1$
- // set the support for multiple host to true to get "standard" OSGi behavior (bug 344850)
- if (FrameworkProperties.getProperty("osgi.support.multipleHosts") == null) //$NON-NLS-1$
- FrameworkProperties.setProperty("osgi.support.multipleHosts", "true"); //$NON-NLS-1$ //$NON-NLS-2$
- // first check props we are required to provide reasonable defaults for
- Object windowSystem = configuration == null ? null : configuration.get(Constants.FRAMEWORK_WINDOWSYSTEM);
- if (windowSystem == null) {
- windowSystem = FrameworkProperties.getProperty(EclipseStarter.PROP_WS);
- if (windowSystem != null)
- FrameworkProperties.setProperty(Constants.FRAMEWORK_WINDOWSYSTEM, (String) windowSystem);
- }
- // rest of props can be ignored if the configuration is null
- if (configuration == null)
- return;
- // check each osgi clean property and set the appropriate equinox one
- Object clean = configuration.get(Constants.FRAMEWORK_STORAGE_CLEAN);
- if (Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT.equals(clean)) {
- // remove this so we only clean on first init
- configuration.remove(Constants.FRAMEWORK_STORAGE_CLEAN);
- FrameworkProperties.setProperty(EclipseStarter.PROP_CLEAN, Boolean.TRUE.toString());
- }
- }
-
- public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
- Framework current = framework;
- if (current == null)
- return new FrameworkEvent(FrameworkEvent.STOPPED, this, null);
- return current.waitForStop(timeout);
- }
-
- public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.findEntries(path, filePattern, recurse);
- }
-
- public BundleContext getBundleContext() {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getBundleContext();
- }
-
- public long getBundleId() {
- return 0;
- }
-
- public URL getEntry(String path) {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getEntry(path);
- }
-
- public Enumeration<String> getEntryPaths(String path) {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getEntryPaths(path);
- }
-
- public Dictionary<String, String> getHeaders() {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getHeaders();
- }
-
- public Dictionary<String, String> getHeaders(String locale) {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getHeaders(locale);
- }
-
- public long getLastModified() {
- Bundle current = systemBundle;
- if (current == null)
- return System.currentTimeMillis();
- return current.getLastModified();
- }
-
- public String getLocation() {
- return Constants.SYSTEM_BUNDLE_LOCATION;
- }
-
- public ServiceReference<?>[] getRegisteredServices() {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getRegisteredServices();
- }
-
- public URL getResource(String name) {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getResource(name);
- }
-
- public Enumeration<URL> getResources(String name) throws IOException {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getResources(name);
- }
-
- public ServiceReference<?>[] getServicesInUse() {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.getServicesInUse();
- }
-
- public int getState() {
- Bundle current = systemBundle;
- if (current == null)
- return Bundle.INSTALLED;
- return current.getState();
- }
-
- public String getSymbolicName() {
- return FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME;
- }
-
- public boolean hasPermission(Object permission) {
- Bundle current = systemBundle;
- if (current == null)
- return false;
- return current.hasPermission(permission);
- }
-
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- Bundle current = systemBundle;
- if (current == null)
- return null;
- return current.loadClass(name);
- }
-
- public void start(int options) throws BundleException {
- start();
- }
-
- /**
- * @throws BundleException
- */
- public void start() throws BundleException {
- checkAdminPermission(AdminPermission.EXECUTE);
- if (System.getSecurityManager() == null)
- internalStart();
- else
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() {
- internalStart();
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- throw (BundleException) e.getException();
- }
- }
-
- private void checkAdminPermission(String actions) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new AdminPermission(this, actions));
- }
-
- void internalStart() {
- if (getState() == Bundle.ACTIVE)
- return;
- Framework current = internalInit();
- int level = 1;
- try {
- level = Integer.parseInt(configuration.get(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
- } catch (Throwable t) {
- // do nothing
- }
- current.startLevelManager.doSetStartLevel(level);
- }
-
- public void stop(int options) throws BundleException {
- stop();
- }
-
- public void stop() throws BundleException {
- Bundle current = systemBundle;
- if (current == null)
- return;
- ConsoleManager currentConsole = consoleMgr;
- if (currentConsole != null) {
- currentConsole.stopConsole();
- consoleMgr = null;
- }
- current.stop();
- }
-
- public void uninstall() throws BundleException {
- throw new BundleException(Msg.BUNDLE_SYSTEMBUNDLE_UNINSTALL_EXCEPTION, BundleException.INVALID_OPERATION);
- }
-
- public void update() throws BundleException {
- Bundle current = systemBundle;
- if (current == null)
- return;
- current.update();
- }
-
- public void update(InputStream in) throws BundleException {
- try {
- in.close();
- } catch (IOException e) {
- // nothing; just being nice
- }
- update();
- }
-
- public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
- Bundle current = systemBundle;
- if (current != null)
- return current.getSignerCertificates(signersType);
- @SuppressWarnings("unchecked")
- final Map<X509Certificate, List<X509Certificate>> empty = Collections.EMPTY_MAP;
- return empty;
- }
-
- public Version getVersion() {
- Bundle current = systemBundle;
- if (current != null)
- return current.getVersion();
- return Version.emptyVersion;
- }
-
- public <A> A adapt(Class<A> adapterType) {
- Bundle current = systemBundle;
- if (current != null) {
- return current.adapt(adapterType);
- }
- return null;
- }
-
- public int compareTo(Bundle o) {
- Bundle current = systemBundle;
- if (current != null)
- return current.compareTo(o);
- throw new IllegalStateException();
- }
-
- public File getDataFile(String filename) {
- Bundle current = systemBundle;
- if (current != null)
- return current.getDataFile(filename);
- return null;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ExportedPackageImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ExportedPackageImpl.java
deleted file mode 100644
index a26998541..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ExportedPackageImpl.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.eclipse.osgi.internal.loader.*;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.ExportPackageDescription;
-import org.osgi.framework.*;
-import org.osgi.framework.Constants;
-import org.osgi.service.packageadmin.ExportedPackage;
-
-/**
- * @deprecated
- */
-public class ExportedPackageImpl implements ExportedPackage {
-
- private final ExportPackageDescription exportedPackage;
- private final BundleLoaderProxy supplier;
-
- public ExportedPackageImpl(ExportPackageDescription exportedPackage, BundleLoaderProxy supplier) {
- this.exportedPackage = exportedPackage;
- this.supplier = supplier;
- }
-
- public String getName() {
- return exportedPackage.getName();
- }
-
- public org.osgi.framework.Bundle getExportingBundle() {
- if (supplier.isStale())
- return null;
- return supplier.getBundleHost();
- }
-
- /*
- * get the bundle without checking if it is stale
- */
- AbstractBundle getBundle() {
- return supplier.getBundleHost();
- }
-
- public Bundle[] getImportingBundles() {
- if (supplier.isStale())
- return null;
- AbstractBundle bundle = (AbstractBundle) getExportingBundle();
- if (bundle == null)
- return null;
- AbstractBundle[] bundles = bundle.framework.getAllBundles();
- List<Bundle> importers = new ArrayList<Bundle>(10);
- PackageSource supplierSource = supplier.createPackageSource(exportedPackage, false);
- for (int i = 0; i < bundles.length; i++) {
- if (!(bundles[i] instanceof BundleHost))
- continue;
- BundleLoader loader = ((BundleHost) bundles[i]).getBundleLoader();
- if (loader == null || loader.getBundle() == supplier.getBundle())
- continue; // do not include include the exporter of the package
- PackageSource importerSource = loader.getPackageSource(getName());
- if (supplierSource != null && supplierSource.hasCommonSource(importerSource))
- importers.add(bundles[i]);
- }
- return importers.toArray(new Bundle[importers.size()]);
- }
-
- /**
- * @deprecated
- */
- public String getSpecificationVersion() {
- return exportedPackage.getVersion().toString();
- }
-
- public Version getVersion() {
- return exportedPackage.getVersion();
- }
-
- public boolean isRemovalPending() {
- BundleDescription exporter = exportedPackage.getExporter();
- if (exporter != null)
- return exporter.isRemovalPending();
- return true;
- }
-
- public String toString() {
- StringBuffer result = new StringBuffer(getName());
- result.append("; ").append(Constants.VERSION_ATTRIBUTE); //$NON-NLS-1$
- result.append("=\"").append(exportedPackage.getVersion().toString()).append("\""); //$NON-NLS-1$//$NON-NLS-2$
-
- return result.toString();
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java
deleted file mode 100644
index 617db7f49..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java
+++ /dev/null
@@ -1,2006 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.security.*;
-import java.util.*;
-import org.eclipse.core.runtime.internal.adaptor.ContextFinder;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.eventmgr.*;
-import org.eclipse.osgi.framework.internal.protocol.ContentHandlerFactory;
-import org.eclipse.osgi.framework.internal.protocol.StreamHandlerFactory;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.framework.util.SecureAction;
-import org.eclipse.osgi.internal.loader.*;
-import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
-import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
-import org.eclipse.osgi.internal.profile.Profile;
-import org.eclipse.osgi.internal.serviceregistry.*;
-import org.eclipse.osgi.signedcontent.SignedContentFactory;
-import org.eclipse.osgi.util.ManifestElement;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.framework.hooks.bundle.*;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Core OSGi Framework class.
- */
-public class Framework implements EventPublisher, Runnable {
- // System property used to set the context classloader parent classloader type (ccl is the default)
- private static final String PROP_CONTEXTCLASSLOADER_PARENT = "osgi.contextClassLoaderParent"; //$NON-NLS-1$
- private static final String CONTEXTCLASSLOADER_PARENT_APP = "app"; //$NON-NLS-1$
- private static final String CONTEXTCLASSLOADER_PARENT_EXT = "ext"; //$NON-NLS-1$
- private static final String CONTEXTCLASSLOADER_PARENT_BOOT = "boot"; //$NON-NLS-1$
- private static final String CONTEXTCLASSLOADER_PARENT_FWK = "fwk"; //$NON-NLS-1$
-
- public static final String PROP_FRAMEWORK_THREAD = "osgi.framework.activeThreadType"; //$NON-NLS-1$
- public static final String THREAD_NORMAL = "normal"; //$NON-NLS-1$
- public static final String PROP_EQUINOX_SECURITY = "eclipse.security"; //$NON-NLS-1$
- public static final String SECURITY_OSGI = "osgi"; //$NON-NLS-1$
-
- private static String J2SE = "J2SE-"; //$NON-NLS-1$
- private static String JAVASE = "JavaSE-"; //$NON-NLS-1$
- private static String PROFILE_EXT = ".profile"; //$NON-NLS-1$
- /** FrameworkAdaptor specific functions. */
- protected volatile FrameworkAdaptor adaptor;
- /** Framework properties object. A reference to the
- * System.getProperies() object. The properties from
- * the adaptor will be merged into these properties.
- */
- protected Properties properties;
- /** Has the framework been started */
- protected volatile boolean active;
- /** Event indicating the reason for shutdown*/
- private FrameworkEvent[] shutdownEvent;
- /** The bundles installed in the framework */
- protected BundleRepository bundles;
- /** Package Admin object. This object manages the exported packages. */
- protected volatile PackageAdminImpl packageAdmin;
- /** PermissionAdmin and ConditionalPermissionAdmin impl. This object manages the bundle permissions. */
- protected SecurityAdmin securityAdmin;
- /** Startlevel object. This object manages the framework and bundle startlevels */
- protected StartLevelManager startLevelManager;
- /** The ServiceRegistry */
- private volatile ServiceRegistry serviceRegistry;
- private final int BSN_VERSION;
- private static final int BSN_VERSION_SINGLE = 1;
- private static final int BSN_VERSION_MULTIPLE = 2;
- private static final int BSN_VERSION_MANAGED = 3;
-
- /*
- * The following maps objects keep track of event listeners
- * by BundleContext. Each element is a Map that is the set
- * of event listeners for a particular BundleContext. The max number of
- * elements each of the following maps will have is the number of bundles
- * installed in the Framework.
- */
- // Map of BundleContexts for bundle's BundleListeners.
- private final Map<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> allBundleListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>>();
- protected static final int BUNDLEEVENT = 1;
- // Map of BundleContexts for bundle's SynchronousBundleListeners.
- private final Map<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> allSyncBundleListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>>();
- protected static final int BUNDLEEVENTSYNC = 2;
- /* SERVICEEVENT(3) is now handled by ServiceRegistry */
- // Map of BundleContexts for bundle's FrameworkListeners.
- private final Map<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> allFrameworkListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>>();
- protected static final int FRAMEWORKEVENT = 4;
- protected static final int BATCHEVENT_BEGIN = Integer.MIN_VALUE + 1;
- protected static final int BATCHEVENT_END = Integer.MIN_VALUE;
- static final String eventHookName = EventHook.class.getName();
- static final String findHookName = FindHook.class.getName();
- static final String collisionHookName = CollisionHook.class.getName();
- /** EventManager for event delivery. */
- protected volatile EventManager eventManager;
- /* Reservation object for install synchronization */
- private Map<String, Thread> installLock;
- /** System Bundle object */
- protected InternalSystemBundle systemBundle;
- private String[] bootDelegation;
- private String[] bootDelegationStems;
- private boolean bootDelegateAll = false;
- public final boolean contextBootDelegation = "true".equals(FrameworkProperties.getProperty("osgi.context.bootdelegation", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- public final boolean compatibiltyBootDelegation = "true".equals(FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
- private final boolean allowRefreshDuplicateBSN = Boolean.TRUE.toString().equals(FrameworkProperties.getProperty(Constants.REFRESH_DUPLICATE_BSN, "true")); //$NON-NLS-1$
- ClassLoaderDelegateHook[] delegateHooks;
- private volatile boolean forcedRestart = false;
- /**
- * The AliasMapper used to alias OS Names.
- */
- protected static AliasMapper aliasMapper = new AliasMapper();
- static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
- // cache of AdminPermissions keyed by Bundle ID
- private final Map<Long, Map<String, AdminPermission>> adminPermissions = new HashMap<Long, Map<String, AdminPermission>>();
-
- // we need to hold these so that we can unregister them at shutdown
- private StreamHandlerFactory streamHandlerFactory;
- private ContentHandlerFactory contentHandlerFactory;
-
- private volatile ServiceTracker<SignedContentFactory, SignedContentFactory> signedContentFactory;
- private volatile ContextFinder contextFinder;
-
- /*
- * We need to make sure that the GetDataFileAction class loads early to prevent a ClassCircularityError when checking permissions.
- * see bug 161561
- */
- static {
- Class<?> c;
- c = GetDataFileAction.class;
- c.getName(); // to prevent compiler warnings
- }
-
- static class GetDataFileAction implements PrivilegedAction<File> {
- private AbstractBundle bundle;
- private String filename;
-
- public GetDataFileAction(AbstractBundle bundle, String filename) {
- this.bundle = bundle;
- this.filename = filename;
- }
-
- public File run() {
- return bundle.getBundleData().getDataFile(filename);
- }
- }
-
- /**
- * Constructor for the Framework instance. This method initializes the
- * framework to an unlaunched state.
- *
- */
- public Framework(FrameworkAdaptor adaptor) {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logEnter("Framework.initialze()", null); //$NON-NLS-1$
- String bsnVersion = FrameworkProperties.getProperty(Constants.FRAMEWORK_BSNVERSION);
- if (Constants.FRAMEWORK_BSNVERSION_SINGLE.equals(bsnVersion)) {
- BSN_VERSION = BSN_VERSION_SINGLE;
- } else if (Constants.FRAMEWORK_BSNVERSION_MULTIPLE.equals(bsnVersion)) {
- BSN_VERSION = BSN_VERSION_MULTIPLE;
- } else {
- BSN_VERSION = BSN_VERSION_MANAGED;
- }
- long start = System.currentTimeMillis();
- this.adaptor = adaptor;
- delegateHooks = adaptor instanceof BaseAdaptor ? ((BaseAdaptor) adaptor).getHookRegistry().getClassLoaderDelegateHooks() : null;
- active = false;
- installSecurityManager();
- if (Debug.DEBUG_SECURITY) {
- Debug.println("SecurityManager: " + System.getSecurityManager()); //$NON-NLS-1$
- Debug.println("ProtectionDomain of Framework.class: \n" + this.getClass().getProtectionDomain()); //$NON-NLS-1$
- }
- setNLSFrameworkLog();
- // initialize ContextFinder
- initializeContextFinder();
- /* initialize the adaptor */
- adaptor.initialize(this);
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("Framework.initialze()", "adapter initialized"); //$NON-NLS-1$//$NON-NLS-2$
- try {
- adaptor.initializeStorage();
- } catch (IOException e) /* fatal error */{
- throw new RuntimeException(e.getMessage(), e);
- }
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("Framework.initialze()", "adapter storage initialized"); //$NON-NLS-1$//$NON-NLS-2$
- /*
- * This must be done before calling any of the framework getProperty
- * methods.
- */
- initializeProperties(adaptor.getProperties());
- /* initialize admin objects */
- packageAdmin = new PackageAdminImpl(this);
- try {
- // always create security admin even with security off
- securityAdmin = new SecurityAdmin(null, this, adaptor.getPermissionStorage());
- } catch (IOException e) /* fatal error */{
- e.printStackTrace();
- throw new RuntimeException(e.getMessage(), e);
- }
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("Framework.initialze()", "done init props & new PermissionAdminImpl"); //$NON-NLS-1$//$NON-NLS-2$
- startLevelManager = new StartLevelManager(this);
- /* create the event manager and top level event dispatchers */
- eventManager = new EventManager("Framework Event Dispatcher"); //$NON-NLS-1$
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("Framework.initialze()", "done new EventManager"); //$NON-NLS-1$ //$NON-NLS-2$
- /* create the service registry */
- serviceRegistry = new ServiceRegistry(this);
- // Initialize the installLock; there is no way of knowing
- // what the initial size should be, at most it will be the number
- // of threads trying to install a bundle (probably a very low number).
- installLock = new HashMap<String, Thread>(10);
- /* create the system bundle */
- createSystemBundle();
- loadVMProfile(); // load VM profile after the system bundle has been created
- setBootDelegation(); //set boot delegation property after system exports have been set
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("Framework.initialze()", "done createSystemBundle"); //$NON-NLS-1$ //$NON-NLS-2$
- /* install URLStreamHandlerFactory */
- installURLStreamHandlerFactory(systemBundle.context, adaptor);
- /* install ContentHandlerFactory for OSGi URLStreamHandler support */
- installContentHandlerFactory(systemBundle.context, adaptor);
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logTime("Framework.initialze()", "done new URLStream/Content HandlerFactory"); //$NON-NLS-1$//$NON-NLS-2$
- /* create bundle objects for all installed bundles. */
- BundleData[] bundleDatas = adaptor.getInstalledBundles();
- bundles = new BundleRepository(bundleDatas == null ? 10 : bundleDatas.length + 1);
- /* add the system bundle to the Bundle Repository */
- bundles.add(systemBundle);
- if (bundleDatas != null) {
- for (int i = 0; i < bundleDatas.length; i++) {
- try {
- AbstractBundle bundle = AbstractBundle.createBundle(bundleDatas[i], this, true);
- bundles.add(bundle);
- } catch (BundleException be) {
- // This is not a fatal error. Publish the framework event.
- publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, be);
- }
- }
- }
- if (Debug.DEBUG_GENERAL)
- System.out.println("Initialize the framework: " + (System.currentTimeMillis() - start)); //$NON-NLS-1$
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logExit("Framework.initialize()"); //$NON-NLS-1$
- }
-
- public FrameworkAdaptor getAdaptor() {
- return adaptor;
- }
-
- public ClassLoaderDelegateHook[] getDelegateHooks() {
- return delegateHooks;
- }
-
- public ServiceRegistry getServiceRegistry() {
- return serviceRegistry;
- }
-
- private void setNLSFrameworkLog() {
- try {
- Field frameworkLogField = NLS.class.getDeclaredField("frameworkLog"); //$NON-NLS-1$
- frameworkLogField.setAccessible(true);
- frameworkLogField.set(null, adaptor.getFrameworkLog());
- } catch (Exception e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
- }
- }
-
- private void createSystemBundle() {
- try {
- systemBundle = new InternalSystemBundle(this);
- systemBundle.getBundleData().setBundle(systemBundle);
- } catch (BundleException e) { // fatal error
- e.printStackTrace();
- throw new RuntimeException(NLS.bind(Msg.OSGI_SYSTEMBUNDLE_CREATE_EXCEPTION, e.getMessage()), e);
- }
- }
-
- /**
- * Initialize the System properties by copying properties from the adaptor
- * properties object. This method is called by the initialize method.
- *
- */
- protected void initializeProperties(Properties adaptorProperties) {
- properties = FrameworkProperties.getProperties();
- Enumeration<?> enumKeys = adaptorProperties.propertyNames();
- while (enumKeys.hasMoreElements()) {
- String key = (String) enumKeys.nextElement();
- if (properties.getProperty(key) == null) {
- properties.put(key, adaptorProperties.getProperty(key));
- }
- }
- properties.put(Constants.FRAMEWORK_VENDOR, Constants.OSGI_FRAMEWORK_VENDOR);
- properties.put(Constants.FRAMEWORK_VERSION, Constants.OSGI_FRAMEWORK_VERSION);
- String value = properties.getProperty(Constants.FRAMEWORK_PROCESSOR);
- if (value == null) {
- value = properties.getProperty(Constants.JVM_OS_ARCH);
- if (value != null) {
- properties.put(Constants.FRAMEWORK_PROCESSOR, aliasMapper.aliasProcessor(value));
- }
- }
- value = properties.getProperty(Constants.FRAMEWORK_OS_NAME);
- if (value == null) {
- value = properties.getProperty(Constants.JVM_OS_NAME);
- try {
- String canonicalValue = (String) aliasMapper.aliasOSName(value);
- if (canonicalValue != null) {
- value = canonicalValue;
- }
- } catch (ClassCastException ex) {
- //A vector was returned from the alias mapper.
- //The alias mapped to more than one canonical value
- //such as "win32" for example
- }
- if (value != null) {
- properties.put(Constants.FRAMEWORK_OS_NAME, value);
- }
- }
- value = properties.getProperty(Constants.FRAMEWORK_OS_VERSION);
- if (value == null) {
- value = properties.getProperty(Constants.JVM_OS_VERSION);
- if (value != null) {
- // only use the value upto the first space
- int space = value.indexOf(' ');
- if (space > 0) {
- value = value.substring(0, space);
- }
- // fix up cases where the os version does not make a valid Version string.
- int major = 0, minor = 0, micro = 0;
- String qualifier = ""; //$NON-NLS-1$
- try {
- StringTokenizer st = new StringTokenizer(value, ".", true); //$NON-NLS-1$
- major = parseVersionInt(st.nextToken());
-
- if (st.hasMoreTokens()) {
- st.nextToken(); // consume delimiter
- minor = parseVersionInt(st.nextToken());
-
- if (st.hasMoreTokens()) {
- st.nextToken(); // consume delimiter
- micro = parseVersionInt(st.nextToken());
-
- if (st.hasMoreTokens()) {
- st.nextToken(); // consume delimiter
- qualifier = st.nextToken();
- }
- }
- }
- } catch (NoSuchElementException e) {
- // ignore, use the values parsed so far
- }
- try {
- value = new Version(major, minor, micro, qualifier).toString();
- } catch (IllegalArgumentException e) {
- // must be an invalid qualifier; just ignore it
- value = new Version(major, minor, micro).toString();
- }
- properties.put(Constants.FRAMEWORK_OS_VERSION, value);
- }
- }
- value = properties.getProperty(Constants.FRAMEWORK_LANGUAGE);
- if (value == null)
- // set the value of the framework language property
- properties.put(Constants.FRAMEWORK_LANGUAGE, Locale.getDefault().getLanguage());
- // set the support properties for fragments and require-bundle (bug 173090)
- properties.put(Constants.SUPPORTS_FRAMEWORK_FRAGMENT, "true"); //$NON-NLS-1$
- properties.put(Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, "true"); //$NON-NLS-1$
- properties.put(Constants.FRAMEWORK_UUID, new UniversalUniqueIdentifier().toString());
- }
-
- private int parseVersionInt(String value) {
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- // try up to the first non-number char
- StringBuffer sb = new StringBuffer(value.length());
- char[] chars = value.toCharArray();
- for (int i = 0; i < chars.length; i++) {
- if (!Character.isDigit(chars[i]))
- break;
- sb.append(chars[i]);
- }
- if (sb.length() > 0)
- return Integer.parseInt(sb.toString());
- return 0;
- }
- }
-
- private void setBootDelegation() {
- // set the boot delegation according to the osgi boot delegation property
- String bootDelegationProp = properties.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
- if (bootDelegationProp == null)
- return;
- if (bootDelegationProp.trim().length() == 0)
- return;
- String[] bootPackages = ManifestElement.getArrayFromList(bootDelegationProp);
- List<String> exactMatch = new ArrayList<String>(bootPackages.length);
- List<String> stemMatch = new ArrayList<String>(bootPackages.length);
- for (int i = 0; i < bootPackages.length; i++) {
- if (bootPackages[i].equals("*")) { //$NON-NLS-1$
- bootDelegateAll = true;
- return;
- } else if (bootPackages[i].endsWith("*")) { //$NON-NLS-1$
- if (bootPackages[i].length() > 2 && bootPackages[i].endsWith(".*")) //$NON-NLS-1$
- stemMatch.add(bootPackages[i].substring(0, bootPackages[i].length() - 1));
- } else {
- exactMatch.add(bootPackages[i]);
- }
- }
- if (!exactMatch.isEmpty())
- bootDelegation = exactMatch.toArray(new String[exactMatch.size()]);
- if (!stemMatch.isEmpty())
- bootDelegationStems = stemMatch.toArray(new String[stemMatch.size()]);
- }
-
- @SuppressWarnings("deprecation")
- private void loadVMProfile() {
- Properties profileProps = findVMProfile();
- String systemExports = properties.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
- // set the system exports property using the vm profile; only if the property is not already set
- if (systemExports == null) {
- systemExports = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
- if (systemExports != null)
- properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemExports);
- }
- // set the org.osgi.framework.bootdelegation property according to the java profile
- String type = properties.getProperty(Constants.OSGI_JAVA_PROFILE_BOOTDELEGATION); // a null value means ignore
- String profileBootDelegation = profileProps.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
- if (Constants.OSGI_BOOTDELEGATION_OVERRIDE.equals(type)) {
- if (profileBootDelegation == null)
- properties.remove(Constants.FRAMEWORK_BOOTDELEGATION); // override with a null value
- else
- properties.put(Constants.FRAMEWORK_BOOTDELEGATION, profileBootDelegation); // override with the profile value
- } else if (Constants.OSGI_BOOTDELEGATION_NONE.equals(type))
- properties.remove(Constants.FRAMEWORK_BOOTDELEGATION); // remove the bootdelegation property in case it was set
- // set the org.osgi.framework.executionenvironment property according to the java profile
- if (properties.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT) == null) {
- // get the ee from the java profile; if no ee is defined then try the java profile name
- String ee = profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, profileProps.getProperty(Constants.OSGI_JAVA_PROFILE_NAME));
- if (ee != null)
- properties.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee);
- }
- // set the org.osgi.framework.system.capabilities property according to the java profile
- if (properties.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES) == null) {
- String systemCapabilities = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
- if (systemCapabilities != null)
- properties.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, systemCapabilities);
- }
- }
-
- private Properties findVMProfile() {
- Properties result = new Properties();
- // Find the VM profile name using J2ME properties
- String j2meConfig = properties.getProperty(Constants.J2ME_MICROEDITION_CONFIGURATION);
- String j2meProfiles = properties.getProperty(Constants.J2ME_MICROEDITION_PROFILES);
- String vmProfile = null;
- String javaEdition = null;
- Version javaVersion = null;
- if (j2meConfig != null && j2meConfig.length() > 0 && j2meProfiles != null && j2meProfiles.length() > 0) {
- // save the vmProfile based off of the config and profile
- // use the last profile; assuming that is the highest one
- String[] j2meProfileList = ManifestElement.getArrayFromList(j2meProfiles, " "); //$NON-NLS-1$
- if (j2meProfileList != null && j2meProfileList.length > 0)
- vmProfile = j2meConfig + '_' + j2meProfileList[j2meProfileList.length - 1];
- } else {
- // No J2ME properties; use J2SE properties
- // Note that the CDC spec appears not to require VM implementations to set the
- // javax.microedition properties!! So we will try to fall back to the
- // java.specification.name property, but this is pretty ridiculous!!
- String javaSpecVersion = properties.getProperty("java.specification.version"); //$NON-NLS-1$
- // set the profile and EE based off of the java.specification.version
- // TODO We assume J2ME Foundation and J2SE here. need to support other profiles J2EE ...
- if (javaSpecVersion != null) {
- StringTokenizer st = new StringTokenizer(javaSpecVersion, " _-"); //$NON-NLS-1$
- javaSpecVersion = st.nextToken();
- String javaSpecName = properties.getProperty("java.specification.name"); //$NON-NLS-1$
- // See bug 291269 we check for Foundation Specification and Foundation Profile Specification
- if (javaSpecName != null && (javaSpecName.indexOf("Foundation Specification") >= 0 || javaSpecName.indexOf("Foundation Profile Specification") >= 0)) //$NON-NLS-1$ //$NON-NLS-2$
- vmProfile = "CDC-" + javaSpecVersion + "_Foundation-" + javaSpecVersion; //$NON-NLS-1$ //$NON-NLS-2$
- else {
- // look for JavaSE if 1.6 or greater; otherwise look for J2SE
- Version v16 = new Version("1.6"); //$NON-NLS-1$
- javaEdition = J2SE;
- try {
- javaVersion = new Version(javaSpecVersion);
- if (v16.compareTo(javaVersion) <= 0)
- javaEdition = JAVASE;
- } catch (IllegalArgumentException e) {
- // do nothing
- }
- vmProfile = javaEdition + javaSpecVersion;
- }
- }
- }
- URL url = null;
- // check for the java profile property for a url
- String propJavaProfile = FrameworkProperties.getProperty(Constants.OSGI_JAVA_PROFILE);
- if (propJavaProfile != null)
- try {
- // we assume a URL
- url = new URL(propJavaProfile);
- } catch (MalformedURLException e1) {
- // try using a relative path in the system bundle
- url = findInSystemBundle(propJavaProfile);
- }
- if (url == null && vmProfile != null) {
- // look for a profile in the system bundle based on the vm profile
- String javaProfile = vmProfile + PROFILE_EXT;
- url = findInSystemBundle(javaProfile);
- if (url == null)
- url = getNextBestProfile(javaEdition, javaVersion);
- }
- if (url == null)
- // the profile url is still null then use the osgi min profile in OSGi by default
- url = findInSystemBundle("OSGi_Minimum-1.2.profile"); //$NON-NLS-1$
- if (url != null) {
- InputStream in = null;
- try {
- in = url.openStream();
- result.load(new BufferedInputStream(in));
- } catch (IOException e) {
- // TODO consider logging ...
- } finally {
- if (in != null)
- try {
- in.close();
- } catch (IOException ee) {
- // do nothing
- }
- }
- }
- // set the profile name if it does not provide one
- if (result.getProperty(Constants.OSGI_JAVA_PROFILE_NAME) == null)
- if (vmProfile != null)
- result.put(Constants.OSGI_JAVA_PROFILE_NAME, vmProfile.replace('_', '/'));
- else
- // last resort; default to the absolute minimum profile name for the framework
- result.put(Constants.OSGI_JAVA_PROFILE_NAME, "OSGi/Minimum-1.2"); //$NON-NLS-1$
- return result;
- }
-
- private URL getNextBestProfile(String javaEdition, Version javaVersion) {
- if (javaVersion == null || (javaEdition != J2SE && javaEdition != JAVASE))
- return null; // we cannot automatically choose the next best profile unless this is a J2SE or JavaSE vm
- URL bestProfile = findNextBestProfile(javaEdition, javaVersion);
- if (bestProfile == null && javaEdition == JAVASE)
- // if this is a JavaSE VM then search for a lower J2SE profile
- bestProfile = findNextBestProfile(J2SE, javaVersion);
- return bestProfile;
- }
-
- private URL findNextBestProfile(String javaEdition, Version javaVersion) {
- URL result = null;
- int minor = javaVersion.getMinor();
- do {
- result = findInSystemBundle(javaEdition + javaVersion.getMajor() + "." + minor + PROFILE_EXT); //$NON-NLS-1$
- minor = minor - 1;
- } while (result == null && minor > 0);
- return result;
- }
-
- private URL findInSystemBundle(String entry) {
- URL result = systemBundle.getEntry0(entry);
- if (result == null) {
- // Check the ClassLoader in case we're launched off the Java boot classpath
- ClassLoader loader = getClass().getClassLoader();
- result = loader == null ? ClassLoader.getSystemResource(entry) : loader.getResource(entry);
- }
- return result;
- }
-
- /**
- * This method return the state of the framework.
- *
- */
- protected boolean isActive() {
- return (active);
- }
-
- /**
- * This method is called to destory the framework instance.
- *
- */
- public synchronized void close() {
- if (adaptor == null)
- return;
- if (active)
- shutdown(FrameworkEvent.STOPPED);
-
- synchronized (bundles) {
- List<AbstractBundle> allBundles = bundles.getBundles();
- int size = allBundles.size();
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = allBundles.get(i);
- bundle.close();
- }
- bundles.removeAllBundles();
- }
- serviceRegistry = null;
- allBundleListeners.clear();
- allSyncBundleListeners.clear();
- allFrameworkListeners.clear();
- if (eventManager != null) {
- eventManager.close();
- eventManager = null;
- }
- packageAdmin = null;
- adaptor = null;
- uninstallURLStreamHandlerFactory();
- uninstallContentHandlerFactory();
- if (System.getSecurityManager() instanceof EquinoxSecurityManager)
- System.setSecurityManager(null);
- }
-
- /**
- * Start the framework.
- *
- * When the framework is started. The following actions occur: 1. Event
- * handling is enabled. Events can now be delivered to listeners. 2. All
- * bundles which are recorded as started are started as described in the
- * Bundle.start() method. These bundles are the bundles that were started
- * when the framework was last stopped. Reports any exceptions that occur
- * during startup using FrameworkEvents. 3. A FrameworkEvent of type
- * FrameworkEvent.STARTED is broadcast.
- *
- */
- public synchronized void launch() {
- /* Return if framework already started */
- if (active) {
- return;
- }
- /* mark framework as started */
- active = true;
- shutdownEvent = new FrameworkEvent[1];
- if (THREAD_NORMAL.equals(FrameworkProperties.getProperty(PROP_FRAMEWORK_THREAD, THREAD_NORMAL))) {
- Thread fwkThread = new Thread(this, "Framework Active Thread"); //$NON-NLS-1$
- fwkThread.setDaemon(false);
- fwkThread.start();
- }
- /* Resume systembundle */
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Trying to launch framework"); //$NON-NLS-1$
- }
- systemBundle.resume();
- signedContentFactory = new ServiceTracker<SignedContentFactory, SignedContentFactory>(systemBundle.getBundleContext(), SignedContentFactory.class.getName(), null);
- signedContentFactory.open();
- }
-
- /**
- * Stop the framework.
- *
- * When the framework is stopped. The following actions occur: 1. Suspend
- * all started bundles as described in the Bundle.stop method except that
- * the bundle is recorded as started. These bundles will be restarted when
- * the framework is next started. Reports any exceptions that occur during
- * stopping using FrameworkEvents. 2. Event handling is disabled.
- *
- */
- public synchronized void shutdown(int eventType) {
- /* Return if framework already stopped */
- if (!active)
- return;
- this.shutdownEvent[0] = new FrameworkEvent(eventType, systemBundle, null);
- /*
- * set the state of the System Bundle to STOPPING.
- * this must be done first according to section 4.19.2 from the OSGi R3 spec.
- */
- systemBundle.state = Bundle.STOPPING;
- publishBundleEvent(BundleEvent.STOPPING, systemBundle); // need to send system bundle stopping event
- /* call the FrameworkAdaptor.frameworkStopping method first */
- try {
- adaptor.frameworkStopping(systemBundle.getContext());
- } catch (Throwable t) {
- publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, t);
- }
- /* Suspend systembundle */
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Trying to shutdown Framework"); //$NON-NLS-1$
- }
- systemBundle.suspend();
- try {
- adaptor.compactStorage();
- } catch (IOException e) {
- publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, e);
- }
- if (signedContentFactory != null)
- signedContentFactory.close();
- /* mark framework as stopped */
- active = false;
- notifyAll();
- }
-
- /**
- * Create a new Bundle object.
- * @param bundledata the BundleData of the Bundle to create
- */
- AbstractBundle createAndVerifyBundle(int operationType, Bundle target, BundleData bundledata, boolean setBundle) throws BundleException {
- // Check for a bundle already installed with the same symbolic name and version.
- if (BSN_VERSION != BSN_VERSION_MULTIPLE && bundledata.getSymbolicName() != null) {
- List<AbstractBundle> installedBundles = getBundleBySymbolicName(bundledata.getSymbolicName(), bundledata.getVersion());
- if (operationType == CollisionHook.UPDATING) {
- installedBundles.remove(target);
- }
- if (BSN_VERSION == BSN_VERSION_MANAGED && !installedBundles.isEmpty()) {
- notifyCollisionHooks(operationType, target, installedBundles);
- }
- if (!installedBundles.isEmpty()) {
- Bundle installedBundle = installedBundles.iterator().next();
- String msg = NLS.bind(Msg.BUNDLE_INSTALL_SAME_UNIQUEID, new Object[] {installedBundle.getSymbolicName(), installedBundle.getVersion().toString(), installedBundle.getLocation()});
- throw new DuplicateBundleException(msg, installedBundle);
- }
- }
- return AbstractBundle.createBundle(bundledata, this, setBundle);
- }
-
- private class DuplicateBundleException extends BundleException implements StatusException {
- private static final long serialVersionUID = 135669822846323624L;
- private transient Bundle duplicate;
-
- public DuplicateBundleException(String msg, Bundle duplicate) {
- super(msg, BundleException.DUPLICATE_BUNDLE_ERROR);
- this.duplicate = duplicate;
- }
-
- public Object getStatus() {
- return duplicate;
- }
-
- public int getStatusCode() {
- return StatusException.CODE_OK;
- }
-
- }
-
- /**
- * Retrieve the value of the named environment property. Values are
- * provided for the following properties:
- * <dl>
- * <dt><code>org.osgi.framework.version</code>
- * <dd>The version of the framework.
- * <dt><code>org.osgi.framework.vendor</code>
- * <dd>The vendor of this framework implementation.
- * <dt><code>org.osgi.framework.language</code>
- * <dd>The language being used. See ISO 639 for possible values.
- * <dt><code>org.osgi.framework.os.name</code>
- * <dd>The name of the operating system of the hosting computer.
- * <dt><code>org.osgi.framework.os.version</code>
- * <dd>The version number of the operating system of the hosting computer.
- * <dt><code>org.osgi.framework.processor</code>
- * <dd>The name of the processor of the hosting computer.
- * </dl>
- *
- * <p>
- * Note: These last four properties are used by the <code>Bundle-NativeCode</code>
- * manifest header's matching algorithm for selecting native code.
- *
- * @param key
- * The name of the requested property.
- * @return The value of the requested property, or <code>null</code> if
- * the property is undefined.
- */
- public String getProperty(String key) {
- return properties.getProperty(key);
- }
-
- /**
- * Retrieve the value of the named environment property. Values are
- * provided for the following properties:
- * <dl>
- * <dt><code>org.osgi.framework.version</code>
- * <dd>The version of the framework.
- * <dt><code>org.osgi.framework.vendor</code>
- * <dd>The vendor of this framework implementation.
- * <dt><code>org.osgi.framework.language</code>
- * <dd>The language being used. See ISO 639 for possible values.
- * <dt><code>org.osgi.framework.os.name</code>
- * <dd>The name of the operating system of the hosting computer.
- * <dt><code>org.osgi.framework.os.version</code>
- * <dd>The version number of the operating system of the hosting computer.
- * <dt><code>org.osgi.framework.processor</code>
- * <dd>The name of the processor of the hosting computer.
- * </dl>
- *
- * <p>
- * Note: These last four properties are used by the <code>Bundle-NativeCode</code>
- * manifest header's matching algorithm for selecting native code.
- *
- * @param key
- * The name of the requested property.
- * @param def
- * A default value is the requested property is not present.
- * @return The value of the requested property, or the default value if the
- * property is undefined.
- */
- protected String getProperty(String key, String def) {
- return properties.getProperty(key, def);
- }
-
- /**
- * Set a system property.
- *
- * @param key
- * The name of the property to set.
- * @param value
- * The value to set.
- * @return The previous value of the property or null if the property was
- * not previously set.
- */
- protected Object setProperty(String key, String value) {
- return properties.put(key, value);
- }
-
- /**
- * Install a bundle from an InputStream.
- *
- * @param location
- * The location identifier of the bundle to install.
- * @param in
- * The InputStream from which the bundle will be read. If null
- * then the location is used to get the bundle content.
- * @return The Bundle of the installed bundle.
- */
- AbstractBundle installBundle(final String location, final InputStream in, final BundleContextImpl origin) throws BundleException {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("install from inputstream: " + location + ", " + in); //$NON-NLS-1$ //$NON-NLS-2$
- }
- final AccessControlContext callerContext = AccessController.getContext();
- return installWorker(location, new PrivilegedExceptionAction<AbstractBundle>() {
- public AbstractBundle run() throws BundleException {
- /* Map the InputStream or location to a URLConnection */
- URLConnection source = in != null ? new BundleSource(in) : adaptor.mapLocationToURLConnection(location);
- /* call the worker to install the bundle */
- return installWorkerPrivileged(location, source, callerContext, origin);
- }
- }, origin);
- }
-
- /**
- * Worker method to install a bundle. It obtains the reservation for the
- * location and calls the specified action.
- *
- * @param location
- * The location identifier of the bundle to install.
- * @param action
- * A PrivilegedExceptionAction which calls the real worker.
- * @return The {@link AbstractBundle}of the installed bundle.
- * @exception BundleException
- * If the action throws an error.
- */
- protected AbstractBundle installWorker(String location, PrivilegedExceptionAction<AbstractBundle> action, BundleContext origin) throws BundleException {
- synchronized (installLock) {
- while (true) {
- /* Check that the bundle is not already installed. */
- AbstractBundle bundle = getBundleByLocation(location);
- /* If already installed, return bundle object */
- if (bundle != null) {
- Bundle visible = origin.getBundle(bundle.getBundleId());
- if (visible == null) {
- BundleData data = bundle.getBundleData();
- String msg = NLS.bind(Msg.BUNDLE_INSTALL_SAME_UNIQUEID, new Object[] {data.getSymbolicName(), data.getVersion().toString(), data.getLocation()});
- throw new BundleException(msg, BundleException.REJECTED_BY_HOOK);
- }
- return bundle;
- }
- Thread current = Thread.currentThread();
- /* Check for and make reservation */
- Thread reservation = installLock.put(location, current);
- /* if the location is not already reserved */
- if (reservation == null) {
- /* we have made the reservation and can continue */
- break;
- }
- /* the location was already reserved */
- /*
- * If the reservation is held by the current thread, we have
- * recursed to install the same bundle!
- */
- if (current.equals(reservation)) {
- throw new BundleException(Msg.BUNDLE_INSTALL_RECURSION_EXCEPTION, BundleException.STATECHANGE_ERROR);
- }
- try {
- /* wait for the reservation to be released */
- installLock.wait();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new BundleException("Thread has been interrupted while waiting for the location lock.", e); //$NON-NLS-1$
- }
- }
- }
- /* Don't call adaptor while holding the install lock */
- try {
- AbstractBundle bundle = AccessController.doPrivileged(action);
- publishBundleEvent(new BundleEvent(BundleEvent.INSTALLED, bundle, origin.getBundle()));
- return bundle;
- } catch (PrivilegedActionException e) {
- if (e.getException() instanceof RuntimeException)
- throw (RuntimeException) e.getException();
- throw (BundleException) e.getException();
- } finally {
- synchronized (installLock) {
- /* release reservation */
- installLock.remove(location);
- /* wake up all waiters */
- installLock.notifyAll();
- }
- }
- }
-
- /**
- * Worker method to install a bundle. It calls the FrameworkAdaptor object
- * to install the bundle in persistent storage.
- *
- * @param location
- * The location identifier of the bundle to install.
- * @param source
- * The URLConnection from which the bundle will be read.
- * @param callerContext
- * The caller access control context
- * @param origin
- * The origin bundle context that is installing the the bundle
- * @return The {@link AbstractBundle}of the installed bundle.
- * @exception BundleException
- * If the provided stream cannot be read.
- */
- protected AbstractBundle installWorkerPrivileged(String location, URLConnection source, AccessControlContext callerContext, BundleContextImpl origin) throws BundleException {
- BundleOperation storage = adaptor.installBundle(location, source);
- final AbstractBundle bundle;
- try {
- BundleData bundledata = storage.begin();
- bundle = createAndVerifyBundle(CollisionHook.INSTALLING, origin.getBundle(), bundledata, true);
-
- BundleWatcher bundleStats = adaptor.getBundleWatcher();
- if (bundleStats != null)
- bundleStats.watchBundle(bundle, BundleWatcher.START_INSTALLING);
-
- try {
- bundle.load();
- if (System.getSecurityManager() != null) {
- final boolean extension = (bundledata.getType() & (BundleData.TYPE_BOOTCLASSPATH_EXTENSION | BundleData.TYPE_FRAMEWORK_EXTENSION | BundleData.TYPE_EXTCLASSPATH_EXTENSION)) != 0;
- // must check for AllPermission before allow a bundle extension to be installed
- if (extension && !bundle.hasPermission(new AllPermission()))
- throw new BundleException(Msg.BUNDLE_EXTENSION_PERMISSION, BundleException.SECURITY_ERROR, new SecurityException(Msg.BUNDLE_EXTENSION_PERMISSION));
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- checkAdminPermission(bundle, AdminPermission.LIFECYCLE);
- if (extension) // need special permission to install extension bundles
- checkAdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE);
- return null;
- }
- }, callerContext);
- } catch (PrivilegedActionException e) {
- throw e.getException();
- }
- }
- // must add the bundle before committing (bug 330905)
- bundles.add(bundle);
- storage.commit(false);
- } catch (Throwable error) {
- bundles.remove(bundle);
- synchronized (bundles) {
- bundle.unload();
- }
- bundle.close();
- throw error;
- } finally {
- if (bundleStats != null)
- bundleStats.watchBundle(bundle, BundleWatcher.END_INSTALLING);
- }
-
- } catch (Throwable t) {
- try {
- storage.undo();
- } catch (BundleException ee) {
- publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, ee);
- }
- if (t instanceof SecurityException)
- throw (SecurityException) t;
- if (t instanceof BundleException)
- throw (BundleException) t;
- throw new BundleException(t.getMessage(), t);
- }
- return bundle;
- }
-
- /**
- * Retrieve the bundle that has the given unique identifier.
- *
- * @param id
- * The identifier of the bundle to retrieve.
- * @return A {@link AbstractBundle}object, or <code>null</code> if the
- * identifier doesn't match any installed bundle.
- */
- // changed visibility to gain access through the adaptor
- public AbstractBundle getBundle(long id) {
- synchronized (bundles) {
- return bundles.getBundle(id);
- }
- }
-
- AbstractBundle getBundle(final BundleContextImpl context, long id) {
- AbstractBundle bundle = getBundle(id);
- // TODO we make the system bundle special because there are lots of places
- // where we assume the system bundle can get all bundles
- if (bundle == null || context.getBundle().getBundleId() == 0)
- return bundle;
- List<AbstractBundle> single = new ArrayList<AbstractBundle>(1);
- single.add(bundle);
- notifyFindHooks(context, single);
- return single.size() == 0 ? null : bundle;
- }
-
- public BundleContextImpl getSystemBundleContext() {
- if (systemBundle == null)
- return null;
- return systemBundle.context;
- }
-
- public PackageAdminImpl getPackageAdmin() {
- return packageAdmin;
- }
-
- /**
- * Retrieve the bundles that has the given symbolic name and version.
- *
- * @param symbolicName
- * The symbolic name of the bundle to retrieve
- * @param version The version of the bundle to retrieve
- * @return A collection of {@link AbstractBundle} that match the symbolic name and version
- */
- public List<AbstractBundle> getBundleBySymbolicName(String symbolicName, Version version) {
- synchronized (bundles) {
- return bundles.getBundles(symbolicName, version);
- }
- }
-
- /**
- * Retrieve the BundleRepository of all installed bundles. The list is
- * valid at the time of the call to getBundles, but the framework is a very
- * dynamic environment and bundles can be installed or uninstalled at
- * anytime.
- *
- * @return The BundleRepository.
- */
- protected BundleRepository getBundles() {
- return (bundles);
- }
-
- /**
- * Retrieve a list of all installed bundles. The list is valid at the time
- * of the call to getBundleAlls, but the framework is a very dynamic
- * environment and bundles can be installed or uninstalled at anytime.
- *
- * @return An Array of {@link AbstractBundle}objects, one object per installed
- * bundle.
- */
- protected AbstractBundle[] getAllBundles() {
- synchronized (bundles) {
- List<AbstractBundle> allBundles = bundles.getBundles();
- int size = allBundles.size();
- if (size == 0) {
- return (null);
- }
- AbstractBundle[] bundlelist = new AbstractBundle[size];
- allBundles.toArray(bundlelist);
- return (bundlelist);
- }
- }
-
- AbstractBundle[] getBundles(final BundleContextImpl context) {
- List<AbstractBundle> allBundles;
- synchronized (bundles) {
- allBundles = new ArrayList<AbstractBundle>(bundles.getBundles());
- }
- notifyFindHooks(context, allBundles);
- return allBundles.toArray(new AbstractBundle[allBundles.size()]);
- }
-
- private void notifyFindHooks(final BundleContextImpl context, List<AbstractBundle> allBundles) {
- final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(allBundles);
- if (System.getSecurityManager() == null) {
- notifyFindHooksPriviledged(context, shrinkable);
- } else {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- notifyFindHooksPriviledged(context, shrinkable);
- return null;
- }
- });
- }
- }
-
- void notifyFindHooksPriviledged(final BundleContextImpl context, final Collection<Bundle> allBundles) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("notifyBundleFindHooks(" + allBundles + ")"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- getServiceRegistry().notifyHooksPrivileged(new HookContext() {
- public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
- if (hook instanceof FindHook) {
- ((FindHook) hook).find(context, allBundles);
- }
- }
-
- public String getHookClassName() {
- return findHookName;
- }
-
- public String getHookMethodName() {
- return "find"; //$NON-NLS-1$
- }
- });
- }
-
- private void notifyCollisionHooks(final int operationType, final Bundle target, List<AbstractBundle> collisionCandidates) {
- final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(collisionCandidates);
- if (System.getSecurityManager() == null) {
- notifyCollisionHooksPriviledged(operationType, target, shrinkable);
- } else {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- notifyCollisionHooksPriviledged(operationType, target, shrinkable);
- return null;
- }
- });
- }
- }
-
- void notifyCollisionHooksPriviledged(final int operationType, final Bundle target, final Collection<Bundle> collisionCandidates) {
- if (Debug.DEBUG_HOOKS) {
- Debug.println("notifyCollisionHooks(" + operationType + ", " + target + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- }
- getServiceRegistry().notifyHooksPrivileged(new HookContext() {
- public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
- if (hook instanceof CollisionHook) {
- ((CollisionHook) hook).filterCollisions(operationType, target, collisionCandidates);
- }
- }
-
- public String getHookClassName() {
- return collisionHookName;
- }
-
- public String getHookMethodName() {
- return "filterCollisions"; //$NON-NLS-1$
- }
- });
- }
-
- /**
- * Resume a bundle.
- *
- * @param bundle
- * Bundle to resume.
- */
- protected void resumeBundle(AbstractBundle bundle) {
- if (bundle.isActive()) {
- // if bundle is active.
- return;
- }
- try {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Trying to resume bundle " + bundle); //$NON-NLS-1$
- }
- bundle.resume();
- } catch (BundleException be) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Bundle resume exception: " + be.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException());
- }
- publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be);
- }
- }
-
- /**
- * Suspend a bundle.
- *
- * @param bundle
- * Bundle to suspend.
- * @param lock
- * true if state change lock should be held when returning from
- * this method.
- * @return true if bundle was active and is now suspended.
- */
- protected boolean suspendBundle(AbstractBundle bundle, boolean lock) {
- boolean changed = false;
- if (!bundle.isActive() || bundle.isFragment()) {
- // if bundle is not active or is a fragment then do nothing.
- return changed;
- }
- try {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Trying to suspend bundle " + bundle); //$NON-NLS-1$
- }
- bundle.suspend(lock);
- } catch (BundleException be) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Bundle suspend exception: " + be.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException());
- }
- publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be);
- }
- if (!bundle.isActive()) {
- changed = true;
- }
- return (changed);
- }
-
- /**
- * Locate an installed bundle with a given identity.
- *
- * @param location
- * string for the bundle
- * @return Bundle object for bundle with the specified location or null if
- * no bundle is installed with the specified location.
- */
- protected AbstractBundle getBundleByLocation(String location) {
- synchronized (bundles) {
- // this is not optimized; do not think it will get called
- // that much.
- final String finalLocation = location;
-
- //Bundle.getLocation requires AdminPermission (metadata)
- return AccessController.doPrivileged(new PrivilegedAction<AbstractBundle>() {
- public AbstractBundle run() {
- List<AbstractBundle> allBundles = bundles.getBundles();
- int size = allBundles.size();
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = allBundles.get(i);
- if (finalLocation.equals(bundle.getLocation())) {
- return bundle;
- }
- }
- return null;
- }
- });
- }
- }
-
- /**
- * Locate an installed bundle with a given symbolic name
- *
- * @param symbolicName
- * The symbolic name for the bundle
- * @return Bundle object for bundle with the specified Unique or null if no
- * bundle is installed with the specified symbolicName.
- */
- protected AbstractBundle[] getBundleBySymbolicName(String symbolicName) {
- synchronized (bundles) {
- return bundles.getBundles(symbolicName);
- }
- }
-
- /**
- * Creates a <code>File</code> object for a file in the persistent
- * storage area provided for the bundle by the framework. If the adaptor
- * does not have file system support, this method will return <code>null</code>.
- *
- * <p>
- * A <code>File</code> object for the base directory of the persistent
- * storage area provided for the context bundle by the framework can be
- * obtained by calling this method with the empty string ("") as the
- * parameter.
- */
- protected File getDataFile(final AbstractBundle bundle, final String filename) {
- return AccessController.doPrivileged(new GetDataFileAction(bundle, filename));
- }
-
- /**
- * Check for specific AdminPermission (RFC 73)
- */
- protected void checkAdminPermission(Bundle bundle, String action) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(getAdminPermission(bundle, action));
- }
-
- // gets AdminPermission objects from a cache to reduce the number of AdminPermission
- // objects that are created.
- private AdminPermission getAdminPermission(Bundle bundle, String action) {
- synchronized (adminPermissions) {
- Long ID = new Long(bundle.getBundleId());
- Map<String, AdminPermission> bundlePermissions = adminPermissions.get(ID);
- if (bundlePermissions == null) {
- bundlePermissions = new HashMap<String, AdminPermission>();
- adminPermissions.put(ID, bundlePermissions);
- }
- AdminPermission result = bundlePermissions.get(action);
- if (result == null) {
- result = new AdminPermission(bundle, action);
- bundlePermissions.put(action, result);
- }
- return result;
- }
- }
-
- /**
- * This is necessary for running from a JXE, otherwise the SecurityManager
- * is set much later than we would like!
- */
- protected void installSecurityManager() {
- String securityManager = FrameworkProperties.getProperty(Constants.FRAMEWORK_SECURITY, FrameworkProperties.getProperty(PROP_EQUINOX_SECURITY, FrameworkProperties.getProperty("java.security.manager")));
- if (securityManager != null) {
- SecurityManager sm = System.getSecurityManager();
- if (sm == null) {
- if (securityManager.length() == 0)
- sm = new SecurityManager(); // use the default one from java
- else if (securityManager.equals(SECURITY_OSGI))
- sm = new EquinoxSecurityManager(); // use an OSGi enabled manager that understands postponed conditions
- else {
- // try to use a specific classloader by classname
- try {
- Class<?> clazz = Class.forName(securityManager);
- sm = (SecurityManager) clazz.newInstance();
- } catch (ClassNotFoundException e) {
- // do nothing
- } catch (ClassCastException e) {
- // do nothing
- } catch (InstantiationException e) {
- // do nothing
- } catch (IllegalAccessException e) {
- // do nothing
- }
- }
- if (sm == null)
- throw new NoClassDefFoundError(securityManager);
- if (Debug.DEBUG_SECURITY)
- Debug.println("Setting SecurityManager to: " + sm); //$NON-NLS-1$
- System.setSecurityManager(sm);
- return;
- }
- }
- }
-
- void addFrameworkListener(FrameworkListener listener, BundleContextImpl context) {
- synchronized (allFrameworkListeners) {
- CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = allFrameworkListeners.get(context);
- if (listeners == null) {
- listeners = new CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>();
- allFrameworkListeners.put(context, listeners);
- }
- listeners.put(listener, listener);
- }
- }
-
- void removeFrameworkListener(FrameworkListener listener, BundleContextImpl context) {
- synchronized (allFrameworkListeners) {
- CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = allFrameworkListeners.get(context);
- if (listeners != null)
- listeners.remove(listener);
- }
- }
-
- void removeAllListeners(BundleContextImpl context) {
- synchronized (allBundleListeners) {
- allBundleListeners.remove(context);
- }
- synchronized (allSyncBundleListeners) {
- allSyncBundleListeners.remove(context);
- }
- synchronized (allFrameworkListeners) {
- allFrameworkListeners.remove(context);
- }
- }
-
- /**
- * Deliver a FrameworkEvent.
- *
- * @param type
- * FrameworkEvent type.
- * @param bundle
- * Affected bundle or null for system bundle.
- * @param throwable
- * Related exception or null.
- */
- public void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable) {
- publishFrameworkEvent(type, bundle, throwable, (FrameworkListener[]) null);
- }
-
- public void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable, final FrameworkListener... listeners) {
- if (bundle == null)
- bundle = systemBundle;
- final FrameworkEvent event = new FrameworkEvent(type, bundle, throwable);
- if (System.getSecurityManager() == null) {
- publishFrameworkEventPrivileged(event, listeners);
- } else {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- publishFrameworkEventPrivileged(event, listeners);
- return null;
- }
- });
- }
- }
-
- public void publishFrameworkEventPrivileged(FrameworkEvent event, FrameworkListener... callerListeners) {
- // Build the listener snapshot
- Map<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> listenerSnapshot;
- synchronized (allFrameworkListeners) {
- listenerSnapshot = new HashMap<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>>(allFrameworkListeners.size());
- for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> entry : allFrameworkListeners.entrySet()) {
- CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = entry.getValue();
- if (!listeners.isEmpty()) {
- listenerSnapshot.put(entry.getKey(), listeners.entrySet());
- }
- }
- }
- // If framework event hook were defined they would be called here
-
- // deliver the event to the snapshot
- ListenerQueue<FrameworkListener, FrameworkListener, FrameworkEvent> queue = newListenerQueue();
-
- // add the listeners specified by the caller first
- if (callerListeners != null && callerListeners.length > 0) {
- Map<FrameworkListener, FrameworkListener> listeners = new HashMap<FrameworkListener, FrameworkListener>();
- for (FrameworkListener listener : callerListeners) {
- if (listener != null)
- listeners.put(listener, listener);
- }
- // We use the system bundle context as the dispatcher
- if (listeners.size() > 0) {
- @SuppressWarnings({"rawtypes", "unchecked"})
- EventDispatcher<FrameworkListener, FrameworkListener, FrameworkEvent> dispatcher = (EventDispatcher) getSystemBundleContext();
- queue.queueListeners(listeners.entrySet(), dispatcher);
- }
- }
-
- for (Map.Entry<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> entry : listenerSnapshot.entrySet()) {
- @SuppressWarnings({"rawtypes", "unchecked"})
- EventDispatcher<FrameworkListener, FrameworkListener, FrameworkEvent> dispatcher = (EventDispatcher) entry.getKey();
- Set<Map.Entry<FrameworkListener, FrameworkListener>> listeners = entry.getValue();
- queue.queueListeners(listeners, dispatcher);
- }
-
- queue.dispatchEventAsynchronous(FRAMEWORKEVENT, event);
- }
-
- void addBundleListener(BundleListener listener, BundleContextImpl context) {
- if (listener instanceof SynchronousBundleListener) {
- checkAdminPermission(context.getBundle(), AdminPermission.LISTENER);
- synchronized (allSyncBundleListeners) {
- CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = allSyncBundleListeners.get(context);
- if (listeners == null) {
- listeners = new CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>();
- allSyncBundleListeners.put(context, listeners);
- }
- listeners.put((SynchronousBundleListener) listener, (SynchronousBundleListener) listener);
- }
- } else {
- synchronized (allBundleListeners) {
- CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = allBundleListeners.get(context);
- if (listeners == null) {
- listeners = new CopyOnWriteIdentityMap<BundleListener, BundleListener>();
- allBundleListeners.put(context, listeners);
- }
- listeners.put(listener, listener);
- }
- }
- }
-
- void removeBundleListener(BundleListener listener, BundleContextImpl context) {
- if (listener instanceof SynchronousBundleListener) {
- checkAdminPermission(context.getBundle(), AdminPermission.LISTENER);
- synchronized (allSyncBundleListeners) {
- CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = allSyncBundleListeners.get(context);
- if (listeners != null)
- listeners.remove(listener);
- }
- } else {
- synchronized (allBundleListeners) {
- CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = allBundleListeners.get(context);
- if (listeners != null)
- listeners.remove(listener);
- }
- }
- }
-
- /**
- * Deliver a BundleEvent to SynchronousBundleListeners (synchronous). and
- * BundleListeners (asynchronous).
- *
- * @param type
- * BundleEvent type.
- * @param bundle
- * Affected bundle or null.
- */
- public void publishBundleEvent(int type, Bundle bundle) {
- publishBundleEvent(new BundleEvent(type, bundle));
- }
-
- private void publishBundleEvent(final BundleEvent event) {
- if (System.getSecurityManager() == null) {
- publishBundleEventPrivileged(event);
- } else {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- publishBundleEventPrivileged(event);
- return null;
- }
- });
- }
- }
-
- public void publishBundleEventPrivileged(BundleEvent event) {
- /*
- * We must collect the snapshots of the sync and async listeners
- * BEFORE we dispatch the event.
- */
- /* Collect snapshot of SynchronousBundleListeners */
- /* Build the listener snapshot */
- Map<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>> listenersSync;
- synchronized (allSyncBundleListeners) {
- listenersSync = new HashMap<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>>(allSyncBundleListeners.size());
- for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> entry : allSyncBundleListeners.entrySet()) {
- CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = entry.getValue();
- if (!listeners.isEmpty()) {
- listenersSync.put(entry.getKey(), listeners.entrySet());
- }
- }
- }
- /* Collect snapshot of BundleListeners; only if the event is NOT STARTING or STOPPING or LAZY_ACTIVATION */
- Map<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>> listenersAsync = null;
- if ((event.getType() & (BundleEvent.STARTING | BundleEvent.STOPPING | BundleEvent.LAZY_ACTIVATION)) == 0) {
- synchronized (allBundleListeners) {
- listenersAsync = new HashMap<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>>(allBundleListeners.size());
- for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> entry : allBundleListeners.entrySet()) {
- CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = entry.getValue();
- if (!listeners.isEmpty()) {
- listenersAsync.put(entry.getKey(), listeners.entrySet());
- }
- }
- }
- }
-
- /* shrink the snapshot.
- * keySet returns a Collection which cannot be added to and
- * removals from that collection will result in removals of the
- * entry from the snapshot.
- */
- Collection<BundleContext> shrinkable;
- if (listenersAsync == null) {
- shrinkable = asBundleContexts(listenersSync.keySet());
- } else {
- shrinkable = new ShrinkableCollection<BundleContext>(asBundleContexts(listenersSync.keySet()), asBundleContexts(listenersAsync.keySet()));
- }
- notifyEventHooksPrivileged(event, shrinkable);
-
- /* Dispatch the event to the snapshot for sync listeners */
- if (!listenersSync.isEmpty()) {
- ListenerQueue<SynchronousBundleListener, SynchronousBundleListener, BundleEvent> queue = newListenerQueue();
- for (Map.Entry<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>> entry : listenersSync.entrySet()) {
- @SuppressWarnings({"rawtypes", "unchecked"})
- EventDispatcher<SynchronousBundleListener, SynchronousBundleListener, BundleEvent> dispatcher = (EventDispatcher) entry.getKey();
- Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>> listeners = entry.getValue();
- queue.queueListeners(listeners, dispatcher);
- }
- queue.dispatchEventSynchronous(BUNDLEEVENTSYNC, event);
- }
-
- /* Dispatch the event to the snapshot for async listeners */
- if ((listenersAsync != null) && !listenersAsync.isEmpty()) {
- ListenerQueue<BundleListener, BundleListener, BundleEvent> queue = newListenerQueue();
- for (Map.Entry<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>> entry : listenersAsync.entrySet()) {
- @SuppressWarnings({"rawtypes", "unchecked"})
- EventDispatcher<BundleListener, BundleListener, BundleEvent> dispatcher = (EventDispatcher) entry.getKey();
- Set<Map.Entry<BundleListener, BundleListener>> listeners = entry.getValue();
- queue.queueListeners(listeners, dispatcher);
- }
- queue.dispatchEventAsynchronous(BUNDLEEVENT, event);
- }
- }
-
- /**
- * Coerce the generic type of a collection from Collection<BundleContextImpl>
- * to Collection<BundleContext>
- * @param c Collection to be coerced.
- * @return c coerced to Collection<BundleContext>
- */
- @SuppressWarnings("unchecked")
- public static Collection<BundleContext> asBundleContexts(Collection<? extends BundleContext> c) {
- return (Collection<BundleContext>) c;
- }
-
- private void notifyEventHooksPrivileged(final BundleEvent event, final Collection<BundleContext> result) {
- if (event.getType() == Framework.BATCHEVENT_BEGIN || event.getType() == Framework.BATCHEVENT_END)
- return; // we don't need to send this event; it is used to book case special listeners
- if (Debug.DEBUG_HOOKS) {
- Debug.println("notifyBundleEventHooks(" + event.getType() + ":" + event.getBundle() + ", " + result + " )"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- }
-
- getServiceRegistry().notifyHooksPrivileged(new HookContext() {
- public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
- if (hook instanceof EventHook) {
- ((EventHook) hook).event(event, result);
- }
- }
-
- public String getHookClassName() {
- return eventHookName;
- }
-
- public String getHookMethodName() {
- return "event"; //$NON-NLS-1$
- }
- });
- }
-
- public <K, V, E> ListenerQueue<K, V, E> newListenerQueue() {
- return new ListenerQueue<K, V, E>(eventManager);
- }
-
- private void initializeContextFinder() {
- Thread current = Thread.currentThread();
- try {
- ClassLoader parent = null;
- // check property for specified parent
- String type = FrameworkProperties.getProperty(PROP_CONTEXTCLASSLOADER_PARENT);
- if (CONTEXTCLASSLOADER_PARENT_APP.equals(type))
- parent = ClassLoader.getSystemClassLoader();
- else if (CONTEXTCLASSLOADER_PARENT_BOOT.equals(type))
- parent = null;
- else if (CONTEXTCLASSLOADER_PARENT_FWK.equals(type))
- parent = Framework.class.getClassLoader();
- else if (CONTEXTCLASSLOADER_PARENT_EXT.equals(type)) {
- ClassLoader appCL = ClassLoader.getSystemClassLoader();
- if (appCL != null)
- parent = appCL.getParent();
- } else { // default is ccl (null or any other value will use ccl)
- parent = current.getContextClassLoader();
- }
- contextFinder = new ContextFinder(parent);
- current.setContextClassLoader(contextFinder);
- return;
- } catch (Exception e) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.INFO, 0, NLS.bind(Msg.CANNOT_SET_CONTEXTFINDER, null), 0, e, null);
- adaptor.getFrameworkLog().log(entry);
- }
-
- }
-
- public static Field getField(Class<?> clazz, Class<?> type, boolean instance) {
- Field[] fields = clazz.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- boolean isStatic = Modifier.isStatic(fields[i].getModifiers());
- if (instance != isStatic && fields[i].getType().equals(type)) {
- fields[i].setAccessible(true);
- return fields[i];
- }
- }
- return null;
- }
-
- private void installContentHandlerFactory(BundleContext context, FrameworkAdaptor frameworkAdaptor) {
- ContentHandlerFactory chf = new ContentHandlerFactory(context, frameworkAdaptor);
- try {
- // first try the standard way
- URLConnection.setContentHandlerFactory(chf);
- } catch (Error err) {
- // ok we failed now use more drastic means to set the factory
- try {
- forceContentHandlerFactory(chf);
- } catch (Exception ex) {
- // this is unexpected, log the exception and throw the original error
- adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), ex));
- throw err;
- }
- }
- contentHandlerFactory = chf;
- }
-
- private static void forceContentHandlerFactory(ContentHandlerFactory chf) throws Exception {
- Field factoryField = getField(URLConnection.class, java.net.ContentHandlerFactory.class, false);
- if (factoryField == null)
- throw new Exception("Could not find ContentHandlerFactory field"); //$NON-NLS-1$
- synchronized (URLConnection.class) {
- java.net.ContentHandlerFactory factory = (java.net.ContentHandlerFactory) factoryField.get(null);
- // doing a null check here just in case, but it would be really strange if it was null,
- // because we failed to set the factory normally!!
-
- if (factory != null) {
- try {
- factory.getClass().getMethod("isMultiplexing", (Class[]) null); //$NON-NLS-1$
- Method register = factory.getClass().getMethod("register", new Class[] {Object.class}); //$NON-NLS-1$
- register.invoke(factory, new Object[] {chf});
- } catch (NoSuchMethodException e) {
- // current factory does not support multiplexing, ok we'll wrap it
- chf.setParentFactory(factory);
- factory = chf;
- }
- }
- // null out the field so that we can successfully call setContentHandlerFactory
- factoryField.set(null, null);
- // always attempt to clear the handlers cache
- // This allows an optomization for the single framework use-case
- resetContentHandlers();
- URLConnection.setContentHandlerFactory(factory);
- }
- }
-
- private void uninstallContentHandlerFactory() {
- try {
- Field factoryField = getField(URLConnection.class, java.net.ContentHandlerFactory.class, false);
- if (factoryField == null)
- return; // oh well, we tried.
- synchronized (URLConnection.class) {
- java.net.ContentHandlerFactory factory = (java.net.ContentHandlerFactory) factoryField.get(null);
-
- if (factory == contentHandlerFactory) {
- factory = (java.net.ContentHandlerFactory) contentHandlerFactory.designateSuccessor();
- } else {
- Method unregister = factory.getClass().getMethod("unregister", new Class[] {Object.class}); //$NON-NLS-1$
- unregister.invoke(factory, new Object[] {contentHandlerFactory});
- }
- // null out the field so that we can successfully call setContentHandlerFactory
- factoryField.set(null, null);
- // always attempt to clear the handlers cache
- // This allows an optomization for the single framework use-case
- // Note that the call to setContentHandlerFactory below may clear this cache
- // but we want to be sure to clear it here just incase the parent is null.
- // In this case the call below would not occur.
- // Also it appears most java libraries actually do not clear the cache
- // when setContentHandlerFactory is called, go figure!!
- resetContentHandlers();
- if (factory != null)
- URLConnection.setContentHandlerFactory(factory);
- }
- } catch (Exception e) {
- // ignore and continue closing the framework
- }
- }
-
- private static void resetContentHandlers() throws IllegalAccessException {
- Field handlersField = getField(URLConnection.class, Hashtable.class, false);
- if (handlersField != null) {
- @SuppressWarnings("rawtypes")
- Hashtable<?, ?> handlers = (Hashtable) handlersField.get(null);
- if (handlers != null)
- handlers.clear();
- }
- }
-
- private void installURLStreamHandlerFactory(BundleContext context, FrameworkAdaptor frameworkAdaptor) {
- StreamHandlerFactory shf = new StreamHandlerFactory(context, frameworkAdaptor);
- try {
- // first try the standard way
- URL.setURLStreamHandlerFactory(shf);
- } catch (Error err) {
- try {
- // ok we failed now use more drastic means to set the factory
- forceURLStreamHandlerFactory(shf);
- } catch (Exception ex) {
- adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), ex));
- throw err;
- }
- }
- streamHandlerFactory = shf;
- }
-
- private static void forceURLStreamHandlerFactory(StreamHandlerFactory shf) throws Exception {
- Field factoryField = getField(URL.class, URLStreamHandlerFactory.class, false);
- if (factoryField == null)
- throw new Exception("Could not find URLStreamHandlerFactory field"); //$NON-NLS-1$
- // look for a lock to synchronize on
- Object lock = getURLStreamHandlerFactoryLock();
- synchronized (lock) {
- URLStreamHandlerFactory factory = (URLStreamHandlerFactory) factoryField.get(null);
- // doing a null check here just in case, but it would be really strange if it was null,
- // because we failed to set the factory normally!!
- if (factory != null) {
- try {
- factory.getClass().getMethod("isMultiplexing", (Class[]) null); //$NON-NLS-1$
- Method register = factory.getClass().getMethod("register", new Class[] {Object.class}); //$NON-NLS-1$
- register.invoke(factory, new Object[] {shf});
- } catch (NoSuchMethodException e) {
- // current factory does not support multiplexing, ok we'll wrap it
- shf.setParentFactory(factory);
- factory = shf;
- }
- }
- factoryField.set(null, null);
- // always attempt to clear the handlers cache
- // This allows an optomization for the single framework use-case
- resetURLStreamHandlers();
- URL.setURLStreamHandlerFactory(factory);
- }
- }
-
- private void uninstallURLStreamHandlerFactory() {
- try {
- Field factoryField = getField(URL.class, URLStreamHandlerFactory.class, false);
- if (factoryField == null)
- return; // oh well, we tried
- Object lock = getURLStreamHandlerFactoryLock();
- synchronized (lock) {
- URLStreamHandlerFactory factory = (URLStreamHandlerFactory) factoryField.get(null);
- if (factory == streamHandlerFactory) {
- factory = (URLStreamHandlerFactory) streamHandlerFactory.designateSuccessor();
- } else {
- Method unregister = factory.getClass().getMethod("unregister", new Class[] {Object.class}); //$NON-NLS-1$
- unregister.invoke(factory, new Object[] {streamHandlerFactory});
- }
- factoryField.set(null, null);
- // always attempt to clear the handlers cache
- // This allows an optomization for the single framework use-case
- // Note that the call to setURLStreamHandlerFactory below may clear this cache
- // but we want to be sure to clear it here just in case the parent is null.
- // In this case the call below would not occur.
- resetURLStreamHandlers();
- if (factory != null)
- URL.setURLStreamHandlerFactory(factory);
- }
- } catch (Exception e) {
- // ignore and continue closing the framework
- }
- }
-
- private static Object getURLStreamHandlerFactoryLock() throws IllegalAccessException {
- Object lock;
- try {
- Field streamHandlerLockField = URL.class.getDeclaredField("streamHandlerLock"); //$NON-NLS-1$
- streamHandlerLockField.setAccessible(true);
- lock = streamHandlerLockField.get(null);
- } catch (NoSuchFieldException noField) {
- // could not find the lock, lets sync on the class object
- lock = URL.class;
- }
- return lock;
- }
-
- private static void resetURLStreamHandlers() throws IllegalAccessException {
- Field handlersField = getField(URL.class, Hashtable.class, false);
- if (handlersField != null) {
- @SuppressWarnings("rawtypes")
- Hashtable<?, ?> handlers = (Hashtable) handlersField.get(null);
- if (handlers != null)
- handlers.clear();
- }
- }
-
- /*
- * (non-Javadoc)
- * @see java.lang.Runnable#run()
- * This thread monitors the framework active status and terminates when the framework is
- * shutdown. This is needed to ensure the VM does not exist because of the lack of a
- * non-daemon thread (bug 215730)
- */
- public void run() {
- synchronized (this) {
- while (active)
- try {
- this.wait(1000);
- } catch (InterruptedException e) {
- // do nothing
- }
- }
- }
-
- void setForcedRestart(boolean forcedRestart) {
- this.forcedRestart = forcedRestart;
- }
-
- boolean isForcedRestart() {
- return forcedRestart;
- }
-
- public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
- boolean waitForEver = timeout == 0;
- long start = System.currentTimeMillis();
- long timeLeft = timeout;
- synchronized (this) {
- FrameworkEvent[] event = shutdownEvent;
- while (event != null && event[0] == null) {
- this.wait(timeLeft);
- if (!waitForEver) {
- timeLeft = start + timeout - System.currentTimeMillis();
- // break if we are passed the timeout
- if (timeLeft <= 0)
- break;
- }
- }
- if (event == null || event[0] == null)
- return new FrameworkEvent(FrameworkEvent.WAIT_TIMEDOUT, systemBundle, null);
- return event[0];
- }
- }
-
- /**
- * Used by ServiceReferenceImpl for isAssignableTo
- * @param registrant Bundle registering service
- * @param client Bundle desiring to use service
- * @param className class name to use
- * @param serviceClass class of original service object
- * @return true if assignable given package wiring
- */
- public boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className, Class<?> serviceClass) {
- // always return false for fragments
- AbstractBundle consumer = (AbstractBundle) client;
- if (consumer.isFragment())
- return false;
- // 1) if the registrant == consumer always return true
- AbstractBundle producer = (AbstractBundle) registrant;
- if (consumer == producer)
- return true;
- // 2) get the package name from the specified className
- String pkgName = BundleLoader.getPackageName(className);
- if (pkgName.startsWith("java.")) //$NON-NLS-1$
- return true;
- BundleLoader producerBL = producer.getBundleLoader();
- if (producerBL == null)
- return false;
- BundleLoader consumerBL = consumer.getBundleLoader();
- if (consumerBL == null)
- return false;
- // 3) for the specified bundle, find the wiring for the package. If no wiring is found return true
- PackageSource consumerSource = consumerBL.getPackageSource(pkgName);
- if (consumerSource == null)
- return true;
- // work around the issue when the package is in the EE and we delegate to boot for that package
- if (isBootDelegationPackage(pkgName)) {
- SystemBundleLoader systemLoader = (SystemBundleLoader) systemBundle.getBundleLoader();
- if (systemLoader.isEEPackage(pkgName))
- return true; // in this case we have a common source from the EE
- }
- // 4) For the registrant bundle, find the wiring for the package.
- PackageSource producerSource = producerBL.getPackageSource(pkgName);
- if (producerSource == null) {
- if (serviceClass != null && ServiceFactory.class.isAssignableFrom(serviceClass)) {
- Bundle bundle = packageAdmin.getBundle(serviceClass);
- if (bundle != null && bundle != registrant)
- // in this case we have a wacky ServiceFactory that is doing something we cannot
- // verify if it is correct. Instead of failing we allow the assignment and hope for the best
- // bug 326918
- return true;
- }
- // 5) If no wiring is found for the registrant bundle then find the wiring for the classloader of the service object. If no wiring is found return false.
- producerSource = getPackageSource(serviceClass, pkgName);
- if (producerSource == null)
- return false;
- }
- // 6) If the two wirings found are equal then return true; otherwise return false.
- return producerSource.hasCommonSource(consumerSource);
- }
-
- private PackageSource getPackageSource(Class<?> serviceClass, String pkgName) {
- if (serviceClass == null)
- return null;
- AbstractBundle serviceBundle = (AbstractBundle) packageAdmin.getBundle(serviceClass);
- if (serviceBundle == null)
- return null;
- BundleLoader producerBL = serviceBundle.getBundleLoader();
- if (producerBL == null)
- return null;
- PackageSource producerSource = producerBL.getPackageSource(pkgName);
- if (producerSource != null)
- return producerSource;
- // try the interfaces
- Class<?>[] interfaces = serviceClass.getInterfaces();
- // note that getInterfaces never returns null
- for (int i = 0; i < interfaces.length; i++) {
- producerSource = getPackageSource(interfaces[i], pkgName);
- if (producerSource != null)
- return producerSource;
- }
- // try super class
- return getPackageSource(serviceClass.getSuperclass(), pkgName);
- }
-
- public boolean isBootDelegationPackage(String name) {
- if (bootDelegateAll)
- return true;
- if (bootDelegation != null)
- for (int i = 0; i < bootDelegation.length; i++)
- if (name.equals(bootDelegation[i]))
- return true;
- if (bootDelegationStems != null)
- for (int i = 0; i < bootDelegationStems.length; i++)
- if (name.startsWith(bootDelegationStems[i]))
- return true;
- return false;
- }
-
- SignedContentFactory getSignedContentFactory() {
- ServiceTracker<SignedContentFactory, SignedContentFactory> currentTracker = signedContentFactory;
- return (currentTracker == null ? null : currentTracker.getService());
- }
-
- ContextFinder getContextFinder() {
- return contextFinder;
- }
-
- public boolean isRefreshDuplicateBSNAllowed() {
- return allowRefreshDuplicateBSN;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java
deleted file mode 100644
index fb352f0de..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.security.Permission;
-import java.security.ProtectionDomain;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.osgi.framework.*;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-import org.osgi.framework.wiring.FrameworkWiring;
-
-/**
- * This class subclasses Bundle to provide a system Bundle
- * so that the framework can be represented as a bundle and
- * can access the services provided by other bundles.
- */
-
-public class InternalSystemBundle extends BundleHost implements org.osgi.framework.launch.Framework {
- class SystemBundleHeaders extends Dictionary<String, String> {
- private final Dictionary<String, String> headers;
-
- public SystemBundleHeaders(Dictionary<String, String> headers) {
- this.headers = headers;
- }
-
- public Enumeration<String> elements() {
- return headers.elements();
- }
-
- public String get(Object key) {
- if (!(key instanceof String))
- return null;
- if (org.osgi.framework.Constants.EXPORT_PACKAGE.equalsIgnoreCase((String) key)) {
- return getExtra(org.osgi.framework.Constants.EXPORT_PACKAGE, org.osgi.framework.Constants.FRAMEWORK_SYSTEMPACKAGES, org.osgi.framework.Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
- } else if (org.osgi.framework.Constants.PROVIDE_CAPABILITY.equalsIgnoreCase((String) key)) {
- return getExtra(org.osgi.framework.Constants.PROVIDE_CAPABILITY, org.osgi.framework.Constants.FRAMEWORK_SYSTEMCAPABILITIES, org.osgi.framework.Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);
- }
- return headers.get(key);
- }
-
- private String getExtra(String header, String systemProp, String systemExtraProp) {
- String systemValue = FrameworkProperties.getProperty(systemProp);
- String systemExtraValue = FrameworkProperties.getProperty(systemExtraProp);
- if (systemValue == null)
- systemValue = systemExtraValue;
- else if (systemExtraValue != null && systemExtraValue.trim().length() > 0)
- systemValue += ", " + systemExtraValue; //$NON-NLS-1$
- String result = headers.get(header);
- if (systemValue != null && systemValue.trim().length() > 0) {
- if (result != null)
- result += ", " + systemValue; //$NON-NLS-1$
- else
- result = systemValue;
- }
- return result;
- }
-
- public boolean isEmpty() {
- return headers.isEmpty();
- }
-
- public Enumeration<String> keys() {
- return headers.keys();
- }
-
- public String put(String key, String value) {
- return headers.put(key, value);
- }
-
- public String remove(Object key) {
- return headers.remove(key);
- }
-
- public int size() {
- return headers.size();
- }
-
- }
-
- private final FrameworkStartLevel fsl;
- ProtectionDomain systemDomain;
-
- /**
- * Private SystemBundle object constructor.
- * This method creates the SystemBundle and its BundleContext.
- * The SystemBundle's state is set to STARTING.
- * This method is called when the framework is constructed.
- *
- * @param framework Framework this bundle is running in
- */
- protected InternalSystemBundle(Framework framework) throws BundleException {
- super(framework.adaptor.createSystemBundleData(), framework); // startlevel=0 means framework stopped
- Constants.setInternalSymbolicName(bundledata.getSymbolicName());
- state = Bundle.RESOLVED;
- context = createContext();
- fsl = new EquinoxStartLevel();
- }
-
- /**
- * Load the bundle.
- * This methods overrides the Bundle method and does nothing.
- *
- */
- protected void load() {
- SecurityManager sm = System.getSecurityManager();
-
- if (sm != null) {
- systemDomain = getClass().getProtectionDomain();
- }
- }
-
- /**
- * Reload from a new bundle.
- * This methods overrides the Bundle method and does nothing.
- *
- * @param newBundle
- * @return false
- */
- protected boolean reload(AbstractBundle newBundle) {
- return (false);
- }
-
- /**
- * Refresh the bundle.
- * This methods overrides the Bundle method and does nothing.
- *
- */
- protected void refresh() {
- // do nothing
- }
-
- /**
- * Unload the bundle.
- * This methods overrides the Bundle method and does nothing.
- *
- * @return false
- */
- protected boolean unload() {
- return (false);
- }
-
- /**
- * Close the the Bundle's file.
- * This method closes the BundleContext for the SystemBundle.
- *
- */
- protected void close() {
- context.close();
- context = null;
- }
-
- /**
- * This method loads a class from the bundle.
- *
- * @param name the name of the desired Class.
- * @param checkPermission indicates whether a permission check should be done.
- * @return the resulting Class
- * @exception java.lang.ClassNotFoundException if the class definition was not found.
- */
- protected Class<?> loadClass(String name, boolean checkPermission) throws ClassNotFoundException {
- if (checkPermission) {
- framework.checkAdminPermission(this, AdminPermission.CLASS);
- checkValid();
- }
- return (Class.forName(name));
- }
-
- /**
- * Find the specified resource in this bundle.
- * This methods returns null for the system bundle.
- */
- public URL getResource(String name) {
- return (null);
- }
-
- /**
- * Indicate SystemBundle is resolved.
- *
- */
- protected boolean isUnresolved() {
- return (false);
- }
-
- /**
- * Start this bundle.
- * This methods overrides the Bundle method and does nothing.
- *
- */
- public void start() {
- framework.checkAdminPermission(this, AdminPermission.EXECUTE);
- }
-
- public void start(int options) {
- framework.checkAdminPermission(this, AdminPermission.EXECUTE);
- }
-
- /**
- * Start the SystemBundle.
- * This method launches the framework.
- *
- */
- protected void resume() {
- /* initialize the startlevel service */
- framework.startLevelManager.initialize();
-
- /* Load all installed bundles */
- loadInstalledBundles(framework.startLevelManager.getInstalledBundles(framework.bundles, false));
- /* Start the system bundle */
- try {
- framework.systemBundle.state = Bundle.STARTING;
- framework.systemBundle.context.start();
- framework.publishBundleEvent(BundleEvent.STARTING, framework.systemBundle);
- } catch (BundleException be) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: Bundle resume exception: " + be.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException());
- }
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, be);
- throw new RuntimeException(be.getMessage(), be);
- }
-
- }
-
- private void loadInstalledBundles(AbstractBundle[] installedBundles) {
-
- for (int i = 0; i < installedBundles.length; i++) {
- AbstractBundle bundle = installedBundles[i];
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: Trying to load bundle " + bundle); //$NON-NLS-1$
- }
- bundle.load();
- }
- }
-
- /**
- * Stop the framework.
- * This method spawns a thread which will call framework.shutdown.
- *
- */
- public void stop() {
- framework.checkAdminPermission(this, AdminPermission.EXECUTE);
-
- if ((state & (ACTIVE | STARTING)) != 0) {
- Thread shutdown = framework.secureAction.createThread(new Runnable() {
- public void run() {
- try {
- framework.close();
- } catch (Throwable t) {
- // allow the adaptor to handle this unexpected error
- framework.adaptor.handleRuntimeError(t);
- }
- }
- }, "System Bundle Shutdown", framework.getContextFinder()); //$NON-NLS-1$
-
- shutdown.start();
- }
- }
-
- public void stop(int options) {
- stop();
- }
-
- /**
- * Stop the SystemBundle.
- * This method shuts down the framework.
- *
- */
- protected void suspend() {
-
- framework.startLevelManager.shutdown();
- framework.startLevelManager.cleanup();
-
- /* clean up the exporting loaders */
- framework.packageAdmin.cleanup();
-
- if (Debug.DEBUG_GENERAL) {
- Debug.println("->Framework shutdown"); //$NON-NLS-1$
- }
- // fire the STOPPED event here.
- // All bundles have been unloaded, but there may be a boot strap listener that is interested (bug 182742)
- framework.publishBundleEvent(BundleEvent.STOPPED, this);
- }
-
- protected void suspend(boolean lock) {
- // do nothing
- }
-
- /**
- * Update this bundle.
- * This method spawns a thread which will call framework.shutdown
- * followed by framework.launch.
- *
- */
- public void update() {
- framework.checkAdminPermission(this, AdminPermission.LIFECYCLE);
-
- if ((state & (ACTIVE | STARTING)) != 0) {
- Thread restart = framework.secureAction.createThread(new Runnable() {
- public void run() {
- int sl = framework.startLevelManager.getStartLevel();
- FrameworkProperties.setProperty(Constants.PROP_OSGI_RELAUNCH, ""); //$NON-NLS-1$
- framework.shutdown(FrameworkEvent.STOPPED_UPDATE);
- framework.launch();
- if (sl > 0)
- framework.startLevelManager.doSetStartLevel(sl);
- FrameworkProperties.clearProperty(Constants.PROP_OSGI_RELAUNCH);
- }
- }, "System Bundle Update", framework.getContextFinder()); //$NON-NLS-1$
-
- restart.start();
- }
- }
-
- /**
- * Update this bundle from an InputStream.
- * This methods overrides the Bundle method and does nothing.
- *
- * @param in The InputStream from which to read the new bundle.
- */
- public void update(InputStream in) {
- update();
-
- try {
- in.close();
- } catch (IOException e) {
- // do nothing
- }
- }
-
- /**
- * Uninstall this bundle.
- * This methods overrides the Bundle method and throws an exception.
- *
- */
- public void uninstall() throws BundleException {
- framework.checkAdminPermission(this, AdminPermission.LIFECYCLE);
-
- throw new BundleException(Msg.BUNDLE_SYSTEMBUNDLE_UNINSTALL_EXCEPTION, BundleException.INVALID_OPERATION);
- }
-
- /**
- * Determine whether the bundle has the requested
- * permission.
- * This methods overrides the Bundle method and returns <code>true</code>.
- *
- * @param permission The requested permission.
- * @return <code>true</code>
- */
- public boolean hasPermission(Object permission) {
- if (systemDomain != null) {
- if (permission instanceof Permission) {
- return systemDomain.implies((Permission) permission);
- }
-
- return false;
- }
-
- return true;
- }
-
- /**
- * No work to do for the SystemBundle.
- *
- * @param refreshedBundles
- * A list of bundles which have been refreshed as a result
- * of a packageRefresh
- */
- protected void unresolvePermissions(AbstractBundle[] refreshedBundles) {
- // Do nothing
- }
-
- public Dictionary<String, String> getHeaders(String localeString) {
- return new SystemBundleHeaders(super.getHeaders(localeString));
- }
-
- public void init() {
- // no op for internal representation
- }
-
- public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
- return framework.waitForStop(timeout);
- }
-
- public ClassLoader getClassLoader() {
- return getClass().getClassLoader();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected <A> A adapt0(Class<A> adapterType) {
- if (FrameworkStartLevel.class.equals(adapterType))
- return (A) fsl;
- else if (FrameworkWiring.class.equals(adapterType))
- return (A) framework.getPackageAdmin();
- return super.adapt0(adapterType);
- }
-
- class EquinoxStartLevel implements FrameworkStartLevel {
- public void setStartLevel(int startlevel, FrameworkListener... listeners) {
- framework.startLevelManager.setStartLevel(startlevel, InternalSystemBundle.this, listeners);
- }
-
- public int getInitialBundleStartLevel() {
- return framework.startLevelManager.getInitialBundleStartLevel();
- }
-
- public void setInitialBundleStartLevel(int startlevel) {
- framework.startLevelManager.setInitialBundleStartLevel(startlevel);
- }
-
- public Bundle getBundle() {
- return InternalSystemBundle.this;
- }
-
- public int getStartLevel() {
- return framework.startLevelManager.getStartLevel();
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/PackageAdminImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/PackageAdminImpl.java
deleted file mode 100644
index f9e14605d..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/PackageAdminImpl.java
+++ /dev/null
@@ -1,766 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
-import org.eclipse.osgi.internal.profile.Profile;
-import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.service.resolver.VersionRange;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.framework.wiring.FrameworkWiring;
-import org.osgi.service.packageadmin.*;
-
-/**
- * PackageAdmin service for the OSGi specification.
- *
- * Framework service which allows bundle programmers to inspect the packages
- * exported in the framework and eagerly update or uninstall bundles.
- *
- * If present, there will only be a single instance of this service
- * registered in the framework.
- *
- * <p> The term <i>exported package</i> (and the corresponding interface
- * {@link ExportedPackage}) refers to a package that has actually been
- * exported (as opposed to one that is available for export).
- *
- * <p> Note that the information about exported packages returned by this
- * service is valid only until the next time {@link #refreshPackages(org.osgi.framework.Bundle[])} is
- * called.
- * If an ExportedPackage becomes stale, (that is, the package it references
- * has been updated or removed as a result of calling
- * PackageAdmin.refreshPackages()),
- * its getName() and getSpecificationVersion() continue to return their
- * old values, isRemovalPending() returns true, and getExportingBundle()
- * and getImportingBundles() return null.
- */
-public class PackageAdminImpl implements PackageAdmin, FrameworkWiring {
- /** framework object */
- protected Framework framework;
-
- /*
- * We need to make sure that the GetBundleAction class loads early to prevent a ClassCircularityError when checking permissions.
- * See bug 161561
- */
- static {
- Class<?> c;
- c = GetBundleAction.class;
- c.getName(); // to prevent compiler warnings
- }
-
- static class GetBundleAction implements PrivilegedAction<Bundle> {
- private Class<?> clazz;
- private PackageAdminImpl impl;
-
- public GetBundleAction(PackageAdminImpl impl, Class<?> clazz) {
- this.impl = impl;
- this.clazz = clazz;
- }
-
- public Bundle run() {
- return impl.getBundlePriv(clazz);
- }
- }
-
- /**
- * Constructor.
- *
- * @param framework Framework object.
- */
- protected PackageAdminImpl(Framework framework) {
- this.framework = framework;
- }
-
- public ExportedPackage[] getExportedPackages(Bundle bundle) {
- List<ExportedPackage> allExports = new ArrayList<ExportedPackage>();
- FrameworkAdaptor adaptor = framework.adaptor;
- if (adaptor == null)
- return null;
- ExportPackageDescription[] allDescriptions = adaptor.getState().getExportedPackages();
- for (int i = 0; i < allDescriptions.length; i++) {
- ExportedPackageImpl exportedPackage = createExportedPackage(allDescriptions[i]);
- if (exportedPackage == null)
- continue;
- if (bundle == null || exportedPackage.getBundle() == bundle)
- allExports.add(exportedPackage);
- }
- return (allExports.size() == 0 ? null : allExports.toArray(new ExportedPackage[allExports.size()]));
- }
-
- private ExportedPackageImpl createExportedPackage(ExportPackageDescription description) {
- BundleDescription exporter = description.getExporter();
- if (exporter == null || exporter.getHost() != null)
- return null;
- Object userObject = exporter.getUserObject();
- if (!(userObject instanceof BundleLoaderProxy)) {
- BundleHost bundle = (BundleHost) framework.getBundle(exporter.getBundleId());
- if (bundle == null)
- return null;
- userObject = bundle.getLoaderProxy();
- }
- return new ExportedPackageImpl(description, (BundleLoaderProxy) userObject);
- }
-
- public ExportedPackage getExportedPackage(String name) {
- ExportedPackage[] allExports = getExportedPackages((Bundle) null);
- if (allExports == null)
- return null;
- ExportedPackage result = null;
- for (int i = 0; i < allExports.length; i++) {
- if (name.equals(allExports[i].getName())) {
- if (result == null) {
- result = allExports[i];
- } else {
- Version curVersion = result.getVersion();
- Version newVersion = allExports[i].getVersion();
- if (newVersion.compareTo(curVersion) >= 0)
- result = allExports[i];
- }
- }
- }
- return result;
- }
-
- public ExportedPackage[] getExportedPackages(String name) {
- ExportedPackage[] allExports = getExportedPackages((Bundle) null);
- if (allExports == null)
- return null;
- List<ExportedPackage> result = new ArrayList<ExportedPackage>(1); // rare to have more than one
- for (int i = 0; i < allExports.length; i++)
- if (name.equals(allExports[i].getName()))
- result.add(allExports[i]);
- return (result.size() == 0 ? null : result.toArray(new ExportedPackage[result.size()]));
- }
-
- public void refreshPackages(Bundle[] input) {
- refreshPackages(input, false, null);
- }
-
- public void refreshPackages(Bundle[] input, boolean synchronously, final FrameworkListener[] listeners) {
- framework.checkAdminPermission(framework.systemBundle, AdminPermission.RESOLVE);
-
- final AbstractBundle[] copy;
- if (input != null) {
- synchronized (input) {
- copy = new AbstractBundle[input.length];
- System.arraycopy(input, 0, copy, 0, input.length);
- }
- } else
- copy = null;
-
- if (synchronously) {
- doResolveBundles(copy, true, listeners);
- if (framework.isForcedRestart())
- framework.systemBundle.stop();
- } else {
- Thread refresh = framework.secureAction.createThread(new Runnable() {
- public void run() {
- doResolveBundles(copy, true, listeners);
- if (framework.isForcedRestart())
- framework.shutdown(FrameworkEvent.STOPPED_BOOTCLASSPATH_MODIFIED);
- }
- }, "Refresh Packages", framework.getContextFinder()); //$NON-NLS-1$
- refresh.start();
- }
- }
-
- public boolean resolveBundles(Bundle[] bundles) {
- return resolveBundles(bundles, false);
- }
-
- boolean resolveBundles(Bundle[] bundles, boolean propagateError) {
- framework.checkAdminPermission(framework.systemBundle, AdminPermission.RESOLVE);
- if (bundles == null)
- bundles = framework.getAllBundles();
- try {
- doResolveBundles(bundles, false, null);
- } catch (ResolverHookException e) {
- if (propagateError)
- throw e;
- }
- for (int i = 0; i < bundles.length; i++)
- if (!((AbstractBundle) bundles[i]).isResolved())
- return false;
-
- return true;
- }
-
- // This method is protected to enable a work around to bug 245251
- synchronized protected void doResolveBundles(Bundle[] bundles, boolean refreshPackages, FrameworkListener[] listeners) {
- try {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logEnter("resolve bundles"); //$NON-NLS-1$
- framework.publishBundleEvent(Framework.BATCHEVENT_BEGIN, framework.systemBundle);
- State systemState = framework.adaptor.getState();
- BundleDescription[] descriptions = null;
- int numBundles = bundles == null ? 0 : bundles.length;
- if (!refreshPackages) {
- List<BundleDescription> resolving = new ArrayList<BundleDescription>();
- for (Bundle bundle : bundles) {
- BundleDescription description = ((AbstractBundle) bundle).getBundleDescription();
- if (((bundle.getState() & Bundle.INSTALLED) != 0) && description != null)
- resolving.add(description);
- }
- descriptions = resolving.toArray(new BundleDescription[resolving.size()]);
- } else if (numBundles > 0) {
- // populate the resolved hosts package sources first (do this outside sync block: bug 280929)
- populateLoaders(framework.getAllBundles());
- synchronized (framework.bundles) {
- // now collect the descriptions to refresh
- List<BundleDescription> results = new ArrayList<BundleDescription>(numBundles);
- for (int i = 0; i < numBundles; i++) {
- BundleDescription description = ((AbstractBundle) bundles[i]).getBundleDescription();
- if (description != null && description.getBundleId() != 0 && !results.contains(description))
- results.add(description);
- if (framework.isRefreshDuplicateBSNAllowed()) {
- // add in any bundles that have the same symbolic name see bug (169593)
- AbstractBundle[] sameNames = framework.bundles.getBundles(bundles[i].getSymbolicName());
- if (sameNames != null && sameNames.length > 1) {
- for (int j = 0; j < sameNames.length; j++)
- if (sameNames[j] != bundles[i]) {
- BundleDescription sameName = sameNames[j].getBundleDescription();
- if (sameName != null && sameName.getBundleId() != 0 && !results.contains(sameName)) {
- if (checkExtensionBundle(sameName))
- results.add(sameName);
- }
- }
- }
- }
- }
- descriptions = (results.size() == 0 ? null : results.toArray(new BundleDescription[results.size()]));
- }
- }
- StateDelta stateDelta = systemState.resolve(descriptions, refreshPackages);
- BundleDelta[] delta = stateDelta.getChanges();
- processDelta(delta, refreshPackages, systemState);
- if (stateDelta.getResovlerHookException() != null)
- throw stateDelta.getResovlerHookException();
- } catch (Throwable t) {
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("PackageAdminImpl.doResolveBundles: Error occured :"); //$NON-NLS-1$
- Debug.printStackTrace(t);
- }
- if (t instanceof RuntimeException)
- throw (RuntimeException) t;
- if (t instanceof Error)
- throw (Error) t;
- } finally {
- if (Profile.PROFILE && Profile.STARTUP)
- Profile.logExit("resolve bundles"); //$NON-NLS-1$
- if (framework.isActive()) {
- framework.publishBundleEvent(Framework.BATCHEVENT_END, framework.systemBundle);
- if (refreshPackages)
- framework.publishFrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, framework.systemBundle, null, listeners);
- }
- }
- }
-
- private void populateLoaders(AbstractBundle[] bundles) {
- // populate all the loaders with their package source information
- // this is needed to fix bug 259903.
- for (int i = 0; i < bundles.length; i++) {
- // only need to do this for host bundles which are resolved
- if (bundles[i] instanceof BundleHost && bundles[i].isResolved()) {
- // getting the BundleLoader object populates the require-bundle sources
- BundleLoader loader = ((BundleHost) bundles[i]).getBundleLoader();
- if (loader != null)
- // need to explicitly get the import package sources
- loader.getImportedSources(null);
- }
- }
- }
-
- private boolean checkExtensionBundle(BundleDescription sameName) {
- if (sameName.getHost() == null || !sameName.isResolved())
- return true; // only do this extra check for resolved fragment bundles
- // only add fragments if they are not for the system bundle
- if (((BundleDescription) sameName.getHost().getSupplier()).getBundleId() != 0)
- return true;
- // never do this for resolved system bundle fragments
- return false;
- }
-
- private void resumeBundles(AbstractBundle[] bundles, boolean refreshPackages, int[] previousStates) {
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("PackageAdminImpl: restart the bundles"); //$NON-NLS-1$
- }
- if (bundles == null)
- return;
- for (int i = 0; i < bundles.length; i++) {
- if (!bundles[i].isResolved() || (!refreshPackages && ((bundles[i].getBundleData().getStatus() & Constants.BUNDLE_LAZY_START) == 0 || bundles[i].testStateChanging(Thread.currentThread()))))
- // skip bundles that are not resolved or
- // if we are doing resolveBundles then skip non-lazy start bundles and bundles currently changing state by this thread
- continue;
- if (previousStates[i] == Bundle.ACTIVE)
- try {
- bundles[i].start(Bundle.START_TRANSIENT);
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundles[i], e);
- }
- else
- framework.resumeBundle(bundles[i]);
- }
- }
-
- private void suspendBundle(AbstractBundle bundle) {
- // attempt to suspend the bundle or obtain the state change lock
- // Note that this may fail but we cannot quit the
- // refreshPackages operation because of it. (bug 84169)
- if (bundle.isActive() && !bundle.isFragment()) {
- framework.suspendBundle(bundle, true);
- } else {
- if (bundle.getStateChanging() != Thread.currentThread())
- try {
- bundle.beginStateChange();
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
- }
- }
-
- if (Debug.DEBUG_PACKAGEADMIN) {
- if (bundle.stateChanging == null) {
- Debug.println("Bundle state change lock is clear! " + bundle); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- }
- }
-
- private void applyRemovalPending(BundleDelta bundleDelta) throws BundleException {
- if ((bundleDelta.getType() & BundleDelta.REMOVAL_COMPLETE) != 0) {
- BundleDescription bundle = bundleDelta.getBundle();
- if (bundle.getDependents() != null && bundle.getDependents().length > 0) {
- /* Reaching here is an internal error */
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("Bundles still depend on removed bundle! " + bundle); //$NON-NLS-1$
- Debug.printStackTrace(new Exception("Stack trace")); //$NON-NLS-1$
- }
- throw new BundleException(Msg.OSGI_INTERNAL_ERROR);
- }
- Object userObject = bundle.getUserObject();
- if (userObject instanceof BundleLoaderProxy) {
- BundleLoader.closeBundleLoader((BundleLoaderProxy) userObject);
- try {
- ((BundleLoaderProxy) userObject).getBundleData().close();
- } catch (IOException e) {
- // ignore
- }
- } else if (userObject instanceof BundleData) {
- try {
- ((BundleData) userObject).close();
- } catch (IOException e) {
- // ignore
- }
- }
- }
- }
-
- private AbstractBundle setResolved(BundleDescription bundleDescription) {
- if (!bundleDescription.isResolved())
- return null;
- AbstractBundle bundle = framework.getBundle(bundleDescription.getBundleId());
- if (bundle == null) {
- BundleException be = new BundleException(NLS.bind(Msg.BUNDLE_NOT_IN_FRAMEWORK, bundleDescription));
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, be);
- return null;
- }
- boolean resolve = true;
- if (bundle.isFragment()) {
- BundleDescription[] hosts = bundleDescription.getHost().getHosts();
- for (int i = 0; i < hosts.length; i++) {
- BundleHost host = (BundleHost) framework.getBundle(hosts[i].getBundleId());
- resolve = ((BundleFragment) bundle).addHost(host);
- }
- }
- if (resolve)
- bundle.resolve();
- return bundle;
- }
-
- private void applyDeltas(BundleDelta[] bundleDeltas) throws BundleException {
- Arrays.sort(bundleDeltas, new Comparator<BundleDelta>() {
- public int compare(BundleDelta delta0, BundleDelta delta1) {
- return (int) (delta0.getBundle().getBundleId() - delta1.getBundle().getBundleId());
- }
- });
- for (int i = 0; i < bundleDeltas.length; i++) {
- int type = bundleDeltas[i].getType();
- if ((type & (BundleDelta.REMOVAL_PENDING | BundleDelta.REMOVAL_COMPLETE)) != 0)
- applyRemovalPending(bundleDeltas[i]);
- if ((type & BundleDelta.RESOLVED) != 0) {
- AbstractBundle bundle = setResolved(bundleDeltas[i].getBundle());
- if (bundle != null && bundle.isResolved()) {
- NativeCodeSpecification nativeCode = bundleDeltas[i].getBundle().getNativeCodeSpecification();
- if (nativeCode != null && nativeCode.getSupplier() != null)
- try {
- BundleData data = bundle.getBundleData();
- data.installNativeCode(((NativeCodeDescription) nativeCode.getSupplier()).getNativePaths());
- } catch (BundleException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
- }
- }
- }
- }
- }
-
- private AbstractBundle[] processDelta(BundleDelta[] bundleDeltas, boolean refreshPackages, State systemState) {
- List<AbstractBundle> bundlesList = new ArrayList<AbstractBundle>(bundleDeltas.length);
- // get all the bundles that are going to be refreshed
- for (int i = 0; i < bundleDeltas.length; i++) {
- if ((bundleDeltas[i].getType() & BundleDelta.REMOVAL_COMPLETE) != 0 && (bundleDeltas[i].getType() & BundleDelta.REMOVED) == 0)
- // this means the bundle was previously pending removal; do not add to list because it was already removed from before.
- continue;
- AbstractBundle changedBundle = framework.getBundle(bundleDeltas[i].getBundle().getBundleId());
- if (changedBundle != null && !bundlesList.contains(changedBundle))
- bundlesList.add(changedBundle);
- }
- AbstractBundle[] refresh = bundlesList.toArray(new AbstractBundle[bundlesList.size()]);
- // first sort by id/start-level order
- Util.sort(refresh, 0, refresh.length);
- // then sort by dependency order
- framework.startLevelManager.sortByDependency(refresh);
- boolean[] previouslyResolved = new boolean[refresh.length];
- int[] previousStates = new int[refresh.length];
- try {
- try {
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("refreshPackages: Suspend each bundle and acquire its state change lock"); //$NON-NLS-1$
- }
- // find which bundles were previously resolved and handle extension bundles
- boolean restart = false;
- for (int i = refresh.length - 1; i >= 0; i--) {
- previouslyResolved[i] = refresh[i].isResolved();
- if (refresh[i] == framework.systemBundle)
- restart = true;
- else if (((refresh[i].bundledata.getType() & BundleData.TYPE_FRAMEWORK_EXTENSION) != 0) && previouslyResolved[i])
- restart = true;
- else if ((refresh[i].bundledata.getType() & BundleData.TYPE_BOOTCLASSPATH_EXTENSION) != 0)
- restart = true;
- else if ((refresh[i].bundledata.getType() & BundleData.TYPE_EXTCLASSPATH_EXTENSION) != 0 && previouslyResolved[i])
- restart = true;
- }
- if (restart) {
- FrameworkProperties.setProperty("osgi.forcedRestart", "true"); //$NON-NLS-1$ //$NON-NLS-2$
- framework.setForcedRestart(true);
- // do not shutdown the framework while holding the PackageAdmin lock (bug 194149)
- return null;
- }
- // now suspend each bundle and grab its state change lock.
- if (refreshPackages)
- for (int i = refresh.length - 1; i >= 0; i--) {
- previousStates[i] = refresh[i].getState();
- suspendBundle(refresh[i]);
- }
- /*
- * Refresh the bundles which will unexport the packages.
- * This will move RESOLVED bundles to the INSTALLED state.
- */
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("refreshPackages: refresh the bundles"); //$NON-NLS-1$
- }
-
- synchronized (framework.bundles) {
- for (int i = refresh.length - 1; i >= 0; i--)
- refresh[i].refresh();
- }
- // send out unresolved events outside synch block (defect #80610)
- // send out unresolved events in reverse dependency order (defect #207505)
- for (int i = refresh.length - 1; i >= 0; i--) {
- // send out unresolved events
- if (previouslyResolved[i])
- framework.publishBundleEvent(BundleEvent.UNRESOLVED, refresh[i]);
- }
-
- /*
- * apply Deltas.
- */
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("refreshPackages: applying deltas to bundles"); //$NON-NLS-1$
- }
- synchronized (framework.bundles) {
- applyDeltas(bundleDeltas);
- }
-
- } finally {
- /*
- * Release the state change locks.
- */
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("refreshPackages: release the state change locks"); //$NON-NLS-1$
- }
- if (refreshPackages)
- for (int i = 0; i < refresh.length; i++) {
- AbstractBundle changedBundle = refresh[i];
- changedBundle.completeStateChange();
- }
- }
- /*
- * Take this opportunity to clean up the adaptor storage.
- */
- if (refreshPackages) {
- if (Debug.DEBUG_PACKAGEADMIN)
- Debug.println("refreshPackages: clean up adaptor storage"); //$NON-NLS-1$
- try {
- framework.adaptor.compactStorage();
- } catch (IOException e) {
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("refreshPackages exception: " + e.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(e);
- }
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, new BundleException(Msg.BUNDLE_REFRESH_FAILURE, e));
- }
- }
- } catch (BundleException e) {
- if (Debug.DEBUG_PACKAGEADMIN) {
- Debug.println("refreshPackages exception: " + e.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(e.getNestedException() == null ? e : e.getNestedException());
- }
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, new BundleException(Msg.BUNDLE_REFRESH_FAILURE, e));
- }
-
- // send out any resolved. This must be done after the state change locks have been release.
- if (Debug.DEBUG_PACKAGEADMIN)
- Debug.println("refreshPackages: send out RESOLVED events"); //$NON-NLS-1$
- for (int i = 0; i < refresh.length; i++)
- if (refresh[i].isResolved())
- framework.publishBundleEvent(BundleEvent.RESOLVED, refresh[i]);
-
- // if we end up refreshing the system bundle or one of its fragments the framework will be shutdown and
- // should be re-started. This call should return without doing further work.
- if (!framework.isActive())
- return refresh;
- if (refreshPackages) {
- // must clear permission class and condition cache
- framework.securityAdmin.clearCaches();
- // increment the system state timestamp if we are refreshing packages.
- // this is needed incase we suspended a bundle from processing the delta (bug 167483)
- if (bundleDeltas.length > 0)
- systemState.setTimeStamp(systemState.getTimeStamp() == Long.MAX_VALUE ? 0 : systemState.getTimeStamp() + 1);
- }
- // always resume bundles incase we have lazy-start bundles
- resumeBundles(refresh, refreshPackages, previousStates);
- return refresh;
- }
-
- public RequiredBundle[] getRequiredBundles(String symbolicName) {
- AbstractBundle[] bundles;
- if (symbolicName == null)
- bundles = framework.getAllBundles();
- else
- bundles = framework.getBundleBySymbolicName(symbolicName);
- if (bundles == null || bundles.length == 0)
- return null;
-
- List<RequiredBundle> result = new ArrayList<RequiredBundle>(bundles.length);
- for (int i = 0; i < bundles.length; i++) {
- if (bundles[i].isFragment() || !bundles[i].isResolved() || bundles[i].getSymbolicName() == null)
- continue;
- if (bundles[i].hasPermission(new BundlePermission(bundles[i].getSymbolicName(), BundlePermission.PROVIDE)))
- result.add(((BundleHost) bundles[i]).getLoaderProxy());
- }
- return result.size() == 0 ? null : result.toArray(new RequiredBundle[result.size()]);
- }
-
- public Bundle[] getBundles(String symbolicName, String versionRange) {
- if (symbolicName == null) {
- throw new IllegalArgumentException();
- }
- AbstractBundle bundles[] = framework.getBundleBySymbolicName(symbolicName);
- if (bundles == null)
- return null;
-
- if (versionRange == null) {
- AbstractBundle[] result = new AbstractBundle[bundles.length];
- System.arraycopy(bundles, 0, result, 0, result.length);
- return result;
- }
-
- // This code depends on the array of bundles being in descending
- // version order.
- List<AbstractBundle> result = new ArrayList<AbstractBundle>(bundles.length);
- VersionRange range = new VersionRange(versionRange);
- for (int i = 0; i < bundles.length; i++) {
- if (range.isIncluded(bundles[i].getVersion())) {
- result.add(bundles[i]);
- }
- }
-
- if (result.size() == 0)
- return null;
- return result.toArray(new AbstractBundle[result.size()]);
- }
-
- public Bundle[] getFragments(Bundle bundle) {
- return ((AbstractBundle) bundle).getFragments();
- }
-
- public Bundle[] getHosts(Bundle bundle) {
- BundleHost[] hosts = ((AbstractBundle) bundle).getHosts();
- if (hosts == null)
- return null;
- // copy the array to protect modification
- Bundle[] result = new Bundle[hosts.length];
- for (int i = 0; i < hosts.length; i++)
- result[i] = hosts[i];
- return result;
- }
-
- Bundle getBundlePriv(Class<?> clazz) {
- ClassLoader cl = clazz.getClassLoader();
- if (cl instanceof BundleClassLoader) {
- ClassLoaderDelegate delegate = ((BundleClassLoader) cl).getDelegate();
- if (delegate instanceof BundleLoader)
- return ((BundleLoader) delegate).getBundle();
- }
- if (cl == getClass().getClassLoader())
- return framework.systemBundle;
- return null;
- }
-
- public Bundle getBundle(@SuppressWarnings("rawtypes") final Class clazz) {
- if (System.getSecurityManager() == null)
- return getBundlePriv(clazz);
- return AccessController.doPrivileged(new GetBundleAction(this, clazz));
- }
-
- public int getBundleType(Bundle bundle) {
- return ((AbstractBundle) bundle).isFragment() ? PackageAdmin.BUNDLE_TYPE_FRAGMENT : 0;
- }
-
- protected void cleanup() {
- //This is only called when the framework is shutting down
- }
-
- protected void setResolvedBundles(InternalSystemBundle systemBundle) {
- checkSystemBundle(systemBundle);
- // Now set the actual state of the bundles from the persisted state.
- State state = framework.adaptor.getState();
- BundleDescription[] descriptions = state.getBundles();
- for (int i = 0; i < descriptions.length; i++) {
- if (descriptions[i].getBundleId() == 0)
- setFrameworkVersion(descriptions[i]);
- else
- setResolved(descriptions[i]);
- }
- }
-
- private void checkSystemBundle(InternalSystemBundle systemBundle) {
- try {
- // first check that the system bundle has not changed since last saved state.
- State state = framework.adaptor.getState();
- BundleDescription oldSystemBundle = state.getBundle(0);
- boolean different = false;
- if (oldSystemBundle == null || !systemBundle.getBundleData().getVersion().equals(oldSystemBundle.getVersion()))
- different = true;
- if (!different && FrameworkProperties.getProperty("osgi.dev") == null) //$NON-NLS-1$
- return; // return quick if not in dev mode; system bundle version changes with each build
- BundleDescription newSystemBundle = state.getFactory().createBundleDescription(state, systemBundle.getHeaders(""), systemBundle.getLocation(), 0); //$NON-NLS-1$
- if (newSystemBundle == null)
- throw new BundleException(Msg.OSGI_SYSTEMBUNDLE_DESCRIPTION_ERROR);
- if (!different) {
- // need to check to make sure the system bundle description is up to date in the state.
- ExportPackageDescription[] oldPackages = oldSystemBundle.getExportPackages();
- ExportPackageDescription[] newPackages = newSystemBundle.getExportPackages();
- if (oldPackages.length >= newPackages.length) {
- for (int i = 0; i < newPackages.length && !different; i++) {
- if (oldPackages[i].getName().equals(newPackages[i].getName())) {
- Object oldVersion = oldPackages[i].getVersion();
- Object newVersion = newPackages[i].getVersion();
- different = oldVersion == null ? newVersion != null : !oldVersion.equals(newVersion);
- } else {
- different = true;
- }
- }
- } else {
- different = true;
- }
- }
- if (different) {
- state.removeBundle(0);
- state.addBundle(newSystemBundle);
- // force resolution so packages are properly linked
- state.resolve(false);
- }
- } catch (BundleException e) /* fatal error */{
- e.printStackTrace();
- throw new RuntimeException(NLS.bind(Msg.OSGI_SYSTEMBUNDLE_CREATE_EXCEPTION, e.getMessage()), e);
- }
- }
-
- private void setFrameworkVersion(BundleDescription systemBundle) {
- ExportPackageDescription[] packages = systemBundle.getExportPackages();
- for (int i = 0; i < packages.length; i++)
- if (packages[i].getName().equals(Constants.OSGI_FRAMEWORK_PACKAGE)) {
- FrameworkProperties.setProperty(Constants.FRAMEWORK_VERSION, packages[i].getVersion().toString());
- break;
- }
- FrameworkProperties.setProperty(Constants.OSGI_IMPL_VERSION_KEY, systemBundle.getVersion().toString());
- }
-
- public Bundle getBundle() {
- return framework.getBundle(0);
- }
-
- public void refreshBundles(Collection<Bundle> bundles, FrameworkListener... listeners) {
- refreshPackages(bundles == null ? null : bundles.toArray(new Bundle[bundles.size()]), false, listeners);
- }
-
- public boolean resolveBundles(Collection<Bundle> bundles) {
- return resolveBundles(bundles == null ? null : bundles.toArray(new Bundle[bundles.size()]));
- }
-
- public Collection<Bundle> getRemovalPendingBundles() {
- // TODO need to consolidate our removal pending tracking.
- // We currently have three places this is kept (PackageAdminImpl, StateImpl and ResolverImpl)
- // Using the state's because it has easy access to the uninstalled Bundle objects
- BundleDescription[] removals = framework.adaptor.getState().getRemovalPending();
- Set<Bundle> result = new HashSet<Bundle>();
- for (int i = 0; i < removals.length; i++) {
- Object ref = removals[i].getUserObject();
- if (ref instanceof BundleReference)
- result.add(((BundleReference) ref).getBundle());
- }
- return result;
- }
-
- public Collection<Bundle> getDependencyClosure(Collection<Bundle> bundles) {
- Collection<BundleDescription> descriptions = getDescriptionClosure(bundles);
- Set<Bundle> result = new HashSet<Bundle>();
- for (BundleDescription description : descriptions) {
- Object userObject = description.getUserObject();
- if (userObject instanceof BundleReference) {
- Bundle bundle = ((BundleReference) userObject).getBundle();
- if (bundle != null)
- result.add(bundle);
- }
- }
- return result;
- }
-
- private Collection<BundleDescription> getDescriptionClosure(Collection<Bundle> bundles) {
- State state = framework.adaptor.getState();
- Collection<BundleDescription> descriptions = new ArrayList<BundleDescription>();
- for (Bundle bundle : bundles) {
- BundleDescription description = state.getBundle(bundle.getBundleId());
- if (description != null)
- descriptions.add(description);
- }
- return state.getDependencyClosure(descriptions);
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelEvent.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelEvent.java
deleted file mode 100644
index 10636bc64..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelEvent.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.util.EventObject;
-import org.osgi.framework.FrameworkListener;
-
-/**
- * StartLevel Event for the OSGi framework.
- *
- * Event which signifies that a start level change has been requested for the framework or for a bundle.
- *
- */
-class StartLevelEvent extends EventObject {
- private static final long serialVersionUID = 3258125839085155891L;
- public final static int CHANGE_BUNDLE_SL = 0x00000000;
- public final static int CHANGE_FW_SL = 0x00000001;
-
- /**
- * Event Type
- */
- private final transient int type;
-
- /**
- * StartLevel - value depends on event type:
- * CHANGE_BUNDLE_SL - value is the new bundle startlevel
- * CHANGE_FW_SL - value is the new framework startlevel
- *
- */
- private final transient int newSl;
-
- /**
- * For a change in bundle startlevel, this is the bundle to be changed.
- * For a change in framework startlevel, this is the bundle requesting the change.
- */
- private final transient AbstractBundle bundle;
-
- /**
- * A list of framework listeners that must be called at the end of the operation.
- */
- private final transient FrameworkListener[] listeners;
-
- /**
- * Creates a StartLevel event regarding the specified bundle.
- *
- * @param type The type of startlevel event (inc or dec)
- * @param newSl the ultimate requested startlevel we are on our way to
- * @param bundle The affected bundle, or system bundle if it is for the framework
- */
- public StartLevelEvent(int type, int newSl, AbstractBundle bundle, FrameworkListener... listeners) {
- super(bundle);
- this.type = type;
- this.newSl = newSl;
- this.bundle = bundle;
- this.listeners = listeners;
- }
-
- public int getType() {
- return this.type;
- }
-
- public int getNewSL() {
- return this.newSl;
- }
-
- public AbstractBundle getBundle() {
- return this.bundle;
- }
-
- public FrameworkListener[] getListeners() {
- return listeners;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java
deleted file mode 100644
index efd697c99..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/StartLevelManager.java
+++ /dev/null
@@ -1,678 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.IOException;
-import java.security.*;
-import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.eventmgr.*;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.service.startlevel.StartLevel;
-
-/**
- * StartLevel service implementation for the OSGi specification.
- *
- * Framework service which allows management of framework and bundle startlevels.
- *
- * This class also acts as the StartLevel service factory class, providing StartLevel objects
- * to those requesting org.osgi.service.startlevel.StartLevel service.
- *
- * If present, there will only be a single instance of this service
- * registered in the framework.
- */
-public class StartLevelManager implements EventDispatcher<Object, Object, StartLevelEvent>, StartLevel {
- protected static EventManager eventManager;
- protected static Map<Object, Object> startLevelListeners;
-
- /** The initial bundle start level for newly installed bundles */
- protected int initialBundleStartLevel = 1;
- // default value is 1 for compatibility mode
-
- /** The currently active framework start level */
- private int activeSL = 0;
-
- /** An object used to lock the active startlevel while it is being referenced */
- private final Object lock = new Object();
- private final Framework framework;
-
- /** This constructor is called by the Framework */
- protected StartLevelManager(Framework framework) {
- this.framework = framework;
- }
-
- protected void initialize() {
- initialBundleStartLevel = framework.adaptor.getInitialBundleStartLevel();
-
- // create an event manager and a start level listener
- // note that we do not pass the ContextFinder because it is set each time doSetStartLevel is called
- eventManager = new EventManager("Start Level Event Dispatcher"); //$NON-NLS-1$
- startLevelListeners = new CopyOnWriteIdentityMap<Object, Object>();
- startLevelListeners.put(this, this);
- }
-
- protected void cleanup() {
- eventManager.close();
- eventManager = null;
- startLevelListeners.clear();
- startLevelListeners = null;
- }
-
- /**
- * Return the initial start level value that is assigned
- * to a Bundle when it is first installed.
- *
- * @return The initial start level value for Bundles.
- * @see #setInitialBundleStartLevel
- */
- public int getInitialBundleStartLevel() {
- return initialBundleStartLevel;
- }
-
- /**
- * Set the initial start level value that is assigned
- * to a Bundle when it is first installed.
- *
- * <p>The initial bundle start level will be set to the specified start level. The
- * initial bundle start level value will be persistently recorded
- * by the Framework.
- *
- * <p>When a Bundle is installed via <tt>BundleContext.installBundle</tt>,
- * it is assigned the initial bundle start level value.
- *
- * <p>The default initial bundle start level value is 1
- * unless this method has been
- * called to assign a different initial bundle
- * start level value.
- *
- * <p>This method does not change the start level values of installed
- * bundles.
- *
- * @param startlevel The initial start level for newly installed bundles.
- * @throws IllegalArgumentException If the specified start level is less than or
- * equal to zero.
- * @throws SecurityException if the caller does not have the
- * <tt>AdminPermission</tt> and the Java runtime environment supports
- * permissions.
- */
- public void setInitialBundleStartLevel(int startlevel) {
- framework.checkAdminPermission(framework.systemBundle, AdminPermission.STARTLEVEL);
- if (startlevel <= 0) {
- throw new IllegalArgumentException();
- }
- initialBundleStartLevel = startlevel;
- framework.adaptor.setInitialBundleStartLevel(startlevel);
- }
-
- /**
- * Return the active start level value of the Framework.
- *
- * If the Framework is in the process of changing the start level
- * this method must return the active start level if this
- * differs from the requested start level.
- *
- * @return The active start level value of the Framework.
- */
- public int getStartLevel() {
- return activeSL;
- }
-
- /**
- * Modify the active start level of the Framework.
- *
- * <p>The Framework will move to the requested start level. This method
- * will return immediately to the caller and the start level
- * change will occur asynchronously on another thread.
- *
- * <p>If the specified start level is
- * higher than the active start level, the
- * Framework will continue to increase the start level
- * until the Framework has reached the specified start level,
- * starting bundles at each
- * start level which are persistently marked to be started as described in the
- * <tt>Bundle.start</tt> method.
- *
- * At each intermediate start level value on the
- * way to and including the target start level, the framework must:
- * <ol>
- * <li>Change the active start level to the intermediate start level value.
- * <li>Start bundles at the intermediate start level in
- * ascending order by <tt>Bundle.getBundleId</tt>.
- * </ol>
- * When this process completes after the specified start level is reached,
- * the Framework will broadcast a Framework event of
- * type <tt>FrameworkEvent.STARTLEVEL_CHANGED</tt> to announce it has moved to the specified
- * start level.
- *
- * <p>If the specified start level is lower than the active start level, the
- * Framework will continue to decrease the start level
- * until the Framework has reached the specified start level
- * stopping bundles at each
- * start level as described in the <tt>Bundle.stop</tt> method except that their
- * persistently recorded state indicates that they must be restarted in the
- * future.
- *
- * At each intermediate start level value on the
- * way to and including the specified start level, the framework must:
- * <ol>
- * <li>Stop bundles at the intermediate start level in
- * descending order by <tt>Bundle.getBundleId</tt>.
- * <li>Change the active start level to the intermediate start level value.
- * </ol>
- * When this process completes after the specified start level is reached,
- * the Framework will broadcast a Framework event of
- * type <tt>FrameworkEvent.STARTLEVEL_CHANGED</tt> to announce it has moved to the specified
- * start level.
- *
- * <p>If the specified start level is equal to the active start level, then
- * no bundles are started or stopped, however, the Framework must broadcast
- * a Framework event of type <tt>FrameworkEvent.STARTLEVEL_CHANGED</tt> to
- * announce it has finished moving to the specified start level. This
- * event may arrive before the this method return.
- *
- * @param newSL The requested start level for the Framework.
- * @throws IllegalArgumentException If the specified start level is less than or
- * equal to zero.
- * @throws SecurityException If the caller does not have the
- * <tt>AdminPermission</tt> and the Java runtime environment supports
- * permissions.
- */
- public void setStartLevel(int newSL, org.osgi.framework.Bundle callerBundle, FrameworkListener... listeners) {
- if (newSL <= 0) {
- throw new IllegalArgumentException(NLS.bind(Msg.STARTLEVEL_EXCEPTION_INVALID_REQUESTED_STARTLEVEL, "" + newSL)); //$NON-NLS-1$
- }
- framework.checkAdminPermission(framework.systemBundle, AdminPermission.STARTLEVEL);
-
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("StartLevelImpl: setStartLevel: " + newSL + "; callerBundle = " + callerBundle.getBundleId()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- issueEvent(new StartLevelEvent(StartLevelEvent.CHANGE_FW_SL, newSL, (AbstractBundle) callerBundle, listeners));
-
- }
-
- public void setStartLevel(int newSL) {
- setStartLevel(newSL, framework.systemBundle);
- }
-
- /**
- * Internal method to shut down the framework synchronously by setting the startlevel to zero
- * and calling the StartLevelListener worker calls directly
- *
- * This method does not return until all bundles are stopped and the framework is shut down.
- */
- protected void shutdown() {
- doSetStartLevel(0);
- }
-
- /**
- * Internal worker method to set the startlevel
- *
- * @param newSL start level value
- * @param callerBundle - the bundle initiating the change in start level
- */
- void doSetStartLevel(int newSL, FrameworkListener... listeners) {
- synchronized (lock) {
- ClassLoader previousTCCL = Thread.currentThread().getContextClassLoader();
- ClassLoader contextFinder = framework.getContextFinder();
- if (contextFinder == previousTCCL)
- contextFinder = null;
- else
- Thread.currentThread().setContextClassLoader(contextFinder);
- try {
- int tempSL = activeSL;
- if (newSL > tempSL) {
- boolean launching = tempSL == 0;
- for (int i = tempSL; i < newSL; i++) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("sync - incrementing Startlevel from " + tempSL); //$NON-NLS-1$
- }
- tempSL++;
- // Note that we must get a new list of installed bundles each time;
- // this is because additional bundles could have been installed from the previous start-level
- incFWSL(i + 1, getInstalledBundles(framework.bundles, false));
- }
- if (launching) {
- framework.systemBundle.state = Bundle.ACTIVE;
- framework.publishBundleEvent(BundleEvent.STARTED, framework.systemBundle);
- framework.publishFrameworkEvent(FrameworkEvent.STARTED, framework.systemBundle, null);
- }
- } else {
- AbstractBundle[] sortedBundles = getInstalledBundles(framework.bundles, true);
- for (int i = tempSL; i > newSL; i--) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("sync - decrementing Startlevel from " + tempSL); //$NON-NLS-1$
- }
- tempSL--;
- decFWSL(i - 1, sortedBundles);
- }
- if (newSL == 0) {
- // unload all bundles
- unloadAllBundles(framework.bundles);
- stopSystemBundle();
- }
- }
- framework.publishFrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, framework.systemBundle, null, listeners);
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("StartLevelImpl: doSetStartLevel: STARTLEVEL_CHANGED event published"); //$NON-NLS-1$
- }
- } catch (Error e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e, listeners);
- throw e;
- } catch (RuntimeException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e, listeners);
- throw e;
- } finally {
- if (contextFinder != null)
- Thread.currentThread().setContextClassLoader(previousTCCL);
- }
- }
- }
-
- /**
- * This method is used within the package to save the actual active startlevel value for the framework.
- * Externally the setStartLevel method must be used.
- *
- * @param newSL - the new startlevel to save
- */
- protected void saveActiveStartLevel(int newSL) {
- synchronized (lock) {
- activeSL = newSL;
- }
- }
-
- /**
- * Return the persistent state of the specified bundle.
- *
- * <p>This method returns the persistent state of a bundle.
- * The persistent state of a bundle indicates whether a bundle
- * is persistently marked to be started when it's start level is
- * reached.
- *
- * @return <tt>true</tt> if the bundle is persistently marked to be started,
- * <tt>false</tt> if the bundle is not persistently marked to be started.
- * @exception java.lang.IllegalArgumentException If the specified bundle has been uninstalled.
- */
- public boolean isBundlePersistentlyStarted(org.osgi.framework.Bundle bundle) {
- return ((AbstractBundle) bundle).isPersistentlyStarted();
- }
-
- public boolean isBundleActivationPolicyUsed(Bundle bundle) {
- return ((AbstractBundle) bundle).isActivationPolicyUsed();
- }
-
- /**
- * Return the assigned start level value for the specified Bundle.
- *
- * @param bundle The target bundle.
- * @return The start level value of the specified Bundle.
- * @exception java.lang.IllegalArgumentException If the specified bundle has been uninstalled.
- */
- public int getBundleStartLevel(org.osgi.framework.Bundle bundle) {
- return ((AbstractBundle) bundle).getStartLevel();
- }
-
- /**
- * Assign a start level value to the specified Bundle.
- *
- * <p>The specified bundle will be assigned the specified start level. The
- * start level value assigned to the bundle will be persistently recorded
- * by the Framework.
- *
- * If the new start level for the bundle is lower than or equal to the active start level of
- * the Framework, the Framework will start the specified bundle as described
- * in the <tt>Bundle.start</tt> method if the bundle is persistently marked
- * to be started. The actual starting of this bundle must occur asynchronously.
- *
- * If the new start level for the bundle is higher than the active start level of
- * the Framework, the Framework will stop the specified bundle as described
- * in the <tt>Bundle.stop</tt> method except that the persistently recorded
- * state for the bundle indicates that the bundle must be restarted in the
- * future. The actual stopping of this bundle must occur asynchronously.
- *
- * @param bundle The target bundle.
- * @param newSL The new start level for the specified Bundle.
- * @throws IllegalArgumentException
- * If the specified bundle has been uninstalled or
- * if the specified start level is less than or equal to zero, or the specified bundle is
- * the system bundle.
- * @throws SecurityException if the caller does not have the
- * <tt>AdminPermission</tt> and the Java runtime environment supports
- * permissions.
- */
- public void setBundleStartLevel(org.osgi.framework.Bundle bundle, int newSL) {
-
- String exceptionText = null;
- if (bundle.getBundleId() == 0) { // system bundle has id=0
- exceptionText = Msg.STARTLEVEL_CANT_CHANGE_SYSTEMBUNDLE_STARTLEVEL;
- } else if (bundle.getState() == Bundle.UNINSTALLED) {
- exceptionText = NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation());
- } else if (newSL <= 0) {
- exceptionText = NLS.bind(Msg.STARTLEVEL_EXCEPTION_INVALID_REQUESTED_STARTLEVEL, "" + newSL); //$NON-NLS-1$
- }
- if (exceptionText != null)
- throw new IllegalArgumentException(exceptionText);
- // first check the permission of the caller
- framework.checkAdminPermission(bundle, AdminPermission.EXECUTE);
- try {
- // if the bundle's startlevel is not already at the requested startlevel
- if (newSL != ((org.eclipse.osgi.framework.internal.core.AbstractBundle) bundle).getInternalStartLevel()) {
- final AbstractBundle b = (AbstractBundle) bundle;
- b.getBundleData().setStartLevel(newSL);
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- b.getBundleData().save();
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- if (e.getException() instanceof IOException) {
- throw (IOException) e.getException();
- }
- throw (RuntimeException) e.getException();
- }
- // handle starting or stopping the bundle asynchronously
- issueEvent(new StartLevelEvent(StartLevelEvent.CHANGE_BUNDLE_SL, newSL, (AbstractBundle) bundle));
- }
- } catch (IOException e) {
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
- }
-
- }
-
- /**
- * This method sends the StartLevelEvent to the EventManager for dispatching
- *
- * @param sle The event to be queued to the Event Manager
- */
- private void issueEvent(StartLevelEvent sle) {
-
- /* queue to hold set of listeners */
- ListenerQueue<Object, Object, StartLevelEvent> queue = new ListenerQueue<Object, Object, StartLevelEvent>(eventManager);
-
- /* add set of StartLevelListeners to queue */
- queue.queueListeners(startLevelListeners.entrySet(), this);
-
- /* dispatch event to set of listeners */
- queue.dispatchEventAsynchronous(sle.getType(), sle);
- }
-
- /**
- * This method is the call back that is called once for each listener.
- * This method must cast the EventListener object to the appropriate listener
- * class for the event type and call the appropriate listener method.
- *
- * @param listener This listener must be cast to the appropriate listener
- * class for the events created by this source and the appropriate listener method
- * must then be called.
- * @param listenerObject This is the optional object that was passed to
- * EventListeners.addListener when the listener was added to the EventListeners.
- * @param eventAction This value was passed to the ListenerQueue object via one of its
- * dispatchEvent* method calls. It can provide information (such
- * as which listener method to call) so that this method
- * can complete the delivery of the event to the listener.
- * @param event This object was passed to the ListenerQueue object via one of its
- * dispatchEvent* method calls. This object was created by the event source and
- * is passed to this method. It should contain all the necessary information (such
- * as what event object to pass) so that this method
- * can complete the delivery of the event to the listener.
- */
- public void dispatchEvent(Object listener, Object listenerObject, int eventAction, StartLevelEvent event) {
- try {
- switch (eventAction) {
- case StartLevelEvent.CHANGE_BUNDLE_SL :
- setBundleSL(event);
- break;
- case StartLevelEvent.CHANGE_FW_SL :
- doSetStartLevel(event.getNewSL(), event.getListeners());
- break;
- }
- } catch (Throwable t) {
- // allow the adaptor to handle this unexpected error
- framework.adaptor.handleRuntimeError(t);
- }
- }
-
- /**
- * Increment the active startlevel by one
- */
- protected void incFWSL(int incToSL, AbstractBundle[] launchBundles) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: incFWSL: saving activeSL of " + incToSL); //$NON-NLS-1$
- }
- // save the startlevel
- saveActiveStartLevel(incToSL);
- // resume all bundles at the startlevel
- resumeBundles(launchBundles, incToSL);
- }
-
- /**
- * Build an array of all installed bundles to be launch.
- * The returned array is sorted by increasing startlevel/id order.
- * @param bundles - the bundles installed in the framework
- * @return A sorted array of bundles
- */
- AbstractBundle[] getInstalledBundles(BundleRepository bundles, boolean sortByDependency) {
-
- /* make copy of bundles vector in case it is modified during launch */
- AbstractBundle[] installedBundles;
-
- synchronized (bundles) {
- List<AbstractBundle> allBundles = bundles.getBundles();
- installedBundles = new AbstractBundle[allBundles.size()];
- allBundles.toArray(installedBundles);
-
- /* sort bundle array in ascending startlevel / bundle id order
- * so that bundles are started in ascending order.
- */
- Util.sort(installedBundles, 0, installedBundles.length);
- if (sortByDependency)
- sortByDependency(installedBundles);
- }
- return installedBundles;
- }
-
- void sortByDependency(AbstractBundle[] bundles) {
- synchronized (framework.bundles) {
- if (bundles.length <= 1)
- return;
- int currentSL = bundles[0].getInternalStartLevel();
- int currentSLindex = 0;
- boolean lazy = false;
- for (int i = 0; i < bundles.length; i++) {
- if (currentSL != bundles[i].getInternalStartLevel()) {
- if (lazy)
- sortByDependencies(bundles, currentSLindex, i);
- currentSL = bundles[i].getInternalStartLevel();
- currentSLindex = i;
- lazy = false;
- }
- lazy |= (bundles[i].getBundleData().getStatus() & Constants.BUNDLE_LAZY_START) != 0;
- }
- // sort the last set of bundles
- if (lazy)
- sortByDependencies(bundles, currentSLindex, bundles.length);
- }
- }
-
- private void sortByDependencies(AbstractBundle[] bundles, int start, int end) {
- if (end - start <= 1)
- return;
- List<BundleDescription> descList = new ArrayList<BundleDescription>(end - start);
- List<AbstractBundle> missingDescs = new ArrayList<AbstractBundle>(0);
- for (int i = start; i < end; i++) {
- BundleDescription desc = bundles[i].getBundleDescription();
- if (desc != null)
- descList.add(desc);
- else
- missingDescs.add(bundles[i]);
- }
- if (descList.size() <= 1)
- return;
- BundleDescription[] descriptions = descList.toArray(new BundleDescription[descList.size()]);
- framework.adaptor.getPlatformAdmin().getStateHelper().sortBundles(descriptions);
- for (int i = start; i < descriptions.length + start; i++)
- bundles[i] = framework.bundles.getBundle(descriptions[i - start].getBundleId());
- if (missingDescs.size() > 0) {
- Iterator<AbstractBundle> missing = missingDescs.iterator();
- for (int i = start + descriptions.length; i < end && missing.hasNext(); i++)
- bundles[i] = missing.next();
- }
- }
-
- /**
- * Resume all bundles in the launch list at the specified start-level
- * @param launch a list of Bundle Objects to launch
- * @param currentSL the current start-level that the bundles must meet to be resumed
- */
- private void resumeBundles(AbstractBundle[] launch, int currentSL) {
- // Resume all bundles that were previously started and whose startlevel is <= the active startlevel
- // first resume the lazy activated bundles
- resumeBundles(launch, true, currentSL);
- // now resume all non lazy bundles
- resumeBundles(launch, false, currentSL);
- }
-
- private void resumeBundles(AbstractBundle[] launch, boolean lazyOnly, int currentSL) {
- for (int i = 0; i < launch.length && !framework.isForcedRestart(); i++) {
- int bsl = launch[i].getInternalStartLevel();
- if (bsl < currentSL) {
- // skip bundles who should have already been started
- continue;
- } else if (bsl == currentSL) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: Active sl = " + currentSL + "; Bundle " + launch[i].getBundleId() + " sl = " + bsl); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- boolean isLazyStart = launch[i].isLazyStart();
- if (lazyOnly ? isLazyStart : !isLazyStart)
- framework.resumeBundle(launch[i]);
- } else {
- // can stop resuming bundles since any remaining bundles have a greater startlevel than the framework active startlevel
- break;
- }
- }
- }
-
- /**
- * Decrement the active startlevel by one
- * @param decToSL - the startlevel value to set the framework to
- */
- protected void decFWSL(int decToSL, AbstractBundle[] shutdown) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: decFWSL: saving activeSL of " + decToSL); //$NON-NLS-1$
- }
-
- saveActiveStartLevel(decToSL);
-
- // just decrementing the active startlevel - framework is not shutting down
- // Do not check framework.isForcedRestart here because we want to stop the active bundles regardless.
- for (int i = shutdown.length - 1; i >= 0; i--) {
- int bsl = shutdown[i].getInternalStartLevel();
- if (bsl > decToSL + 1)
- // skip bundles who should have already been stopped
- continue;
- else if (bsl <= decToSL)
- // stopped all bundles we are going to for this start level
- break;
- else if (shutdown[i].isActive()) {
- // if bundle is active or starting, then stop the bundle
- if (Debug.DEBUG_STARTLEVEL)
- Debug.println("SLL: stopping bundle " + shutdown[i].getBundleId()); //$NON-NLS-1$
- framework.suspendBundle(shutdown[i], false);
- }
- }
- }
-
- /**
- * Stops the system bundle
- */
- private void stopSystemBundle() {
- try {
- framework.systemBundle.context.stop();
- } catch (BundleException sbe) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: Bundle suspend exception: " + sbe.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(sbe.getNestedException() == null ? sbe : sbe.getNestedException());
- }
-
- framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, sbe);
- }
-
- framework.systemBundle.state = Bundle.RESOLVED;
- framework.publishBundleEvent(BundleEvent.STOPPED, framework.systemBundle);
- }
-
- /**
- * Unloads all bundles in the vector passed in.
- * @param bundles list of Bundle objects to be unloaded
- */
- private void unloadAllBundles(BundleRepository bundles) {
- synchronized (bundles) {
- /* unload all installed bundles */
- List<AbstractBundle> allBundles = bundles.getBundles();
- int size = allBundles.size();
-
- for (int i = 0; i < size; i++) {
- AbstractBundle bundle = allBundles.get(i);
-
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: Trying to unload bundle " + bundle); //$NON-NLS-1$
- }
- bundle.refresh();
- try {
- // make sure we close all the bundle data objects
- bundle.getBundleData().close();
- } catch (IOException e) {
- // ignore, we are shutting down anyway
- }
- }
- }
- }
-
- /**
- * Set the bundle's startlevel to the new value
- * This may cause the bundle to start or stop based on the active framework startlevel
- * @param startLevelEvent - the event requesting change in bundle startlevel
- */
- protected void setBundleSL(StartLevelEvent startLevelEvent) {
- synchronized (lock) {
- int currentSL = getStartLevel();
- int newSL = startLevelEvent.getNewSL();
- AbstractBundle bundle = startLevelEvent.getBundle();
-
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.print("SLL: bundle active=" + bundle.isActive()); //$NON-NLS-1$
- Debug.print("; newSL = " + newSL); //$NON-NLS-1$
- Debug.println("; activeSL = " + currentSL); //$NON-NLS-1$
- }
-
- if (bundle.isActive() && (newSL > currentSL)) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: stopping bundle " + bundle.getBundleId()); //$NON-NLS-1$
- }
- framework.suspendBundle(bundle, false);
- } else {
- if (!bundle.isActive() && (newSL <= currentSL)) {
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: starting bundle " + bundle.getBundleId()); //$NON-NLS-1$
- }
- framework.resumeBundle(bundle);
- }
- }
- if (Debug.DEBUG_STARTLEVEL) {
- Debug.println("SLL: Bundle Startlevel set to " + newSL); //$NON-NLS-1$
- }
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/SystemBundleActivator.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/SystemBundleActivator.java
deleted file mode 100644
index f3233207d..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/SystemBundleActivator.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
-import org.eclipse.osgi.internal.resolver.StateImpl;
-import org.eclipse.osgi.service.resolver.State;
-import org.osgi.framework.*;
-import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
-
-/**
- * This class activates the System Bundle.
- */
-
-public class SystemBundleActivator implements BundleActivator {
- private BundleContext context;
- private InternalSystemBundle bundle;
- private Framework framework;
- private ServiceRegistration<?> packageAdmin;
- private ServiceRegistration<?> securityAdmin;
- private ServiceRegistration<?> startLevel;
- private ServiceRegistration<?> debugOptions;
- private ServiceRegistration<?> contextFinder;
-
- public void start(BundleContext bc) throws Exception {
- this.context = bc;
- bundle = (InternalSystemBundle) bc.getBundle();
- framework = bundle.framework;
-
- if (framework.packageAdmin != null)
- packageAdmin = register(new String[] {Constants.OSGI_PACKAGEADMIN_NAME}, framework.packageAdmin, null);
- if (framework.securityAdmin != null)
- securityAdmin = register(new String[] {Constants.OSGI_PERMISSIONADMIN_NAME, ConditionalPermissionAdmin.class.getName()}, framework.securityAdmin, null);
- if (framework.startLevelManager != null)
- startLevel = register(new String[] {Constants.OSGI_STARTLEVEL_NAME}, framework.startLevelManager, null);
- FrameworkDebugOptions dbgOptions = null;
- if ((dbgOptions = FrameworkDebugOptions.getDefault()) != null) {
- dbgOptions.start(bc);
- debugOptions = register(new String[] {org.eclipse.osgi.service.debug.DebugOptions.class.getName()}, dbgOptions, null);
- }
- ClassLoader tccl = framework.getContextFinder();
- if (tccl != null) {
- Dictionary<String, Object> props = new Hashtable<String, Object>(7);
- props.put("equinox.classloader.type", "contextClassLoader"); //$NON-NLS-1$ //$NON-NLS-2$
- contextFinder = register(new String[] {ClassLoader.class.getName()}, tccl, props);
- }
-
- // Always call the adaptor.frameworkStart() at the end of this method.
- framework.adaptor.frameworkStart(bc);
- State state = framework.adaptor.getState();
- if (state instanceof StateImpl)
- ((StateImpl) state).setResolverHookFactory(new CoreResolverHookFactory((BundleContextImpl) context, framework.getServiceRegistry()));
- // attempt to resolve all bundles
- // this is done after the adaptor.frameworkStart has been called
- // this should be the first time the resolver State is accessed
- framework.packageAdmin.setResolvedBundles(bundle);
- // reinitialize the system bundles localization to take into account system bundle fragments
- framework.systemBundle.manifestLocalization = null;
- }
-
- public void stop(BundleContext bc) throws Exception {
- // Always call the adaptor.frameworkStop() at the begining of this method.
- framework.adaptor.frameworkStop(bc);
-
- if (packageAdmin != null)
- packageAdmin.unregister();
- if (securityAdmin != null)
- securityAdmin.unregister();
- if (startLevel != null)
- startLevel.unregister();
- if (debugOptions != null) {
- FrameworkDebugOptions dbgOptions = FrameworkDebugOptions.getDefault();
- if (dbgOptions != null)
- dbgOptions.stop(bc);
- debugOptions.unregister();
- }
- if (contextFinder != null)
- contextFinder.unregister();
-
- framework = null;
- bundle = null;
- this.context = null;
- }
-
- /**
- * Register a service object.
- *
- */
- private ServiceRegistration<?> register(String[] names, Object service, Dictionary<String, Object> properties) {
- if (properties == null)
- properties = new Hashtable<String, Object>(7);
- Dictionary<String, String> headers = bundle.getHeaders();
- properties.put(Constants.SERVICE_VENDOR, headers.get(Constants.BUNDLE_VENDOR));
- properties.put(Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE));
- properties.put(Constants.SERVICE_PID, bundle.getBundleId() + "." + service.getClass().getName()); //$NON-NLS-1$
- return context.registerService(names, service, properties);
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Util.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Util.java
deleted file mode 100644
index 63ccfd2d7..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Util.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-/**
- * This class contains utility functions.
- */
-public class Util {
- /**
- * Performs a quicksort of the given objects
- * by their string representation in ascending order.
- * <p>
- *
- * @param array The array of objects to sort
- */
- public static void sortByString(Object[] array) {
- qSortByString(array, 0, array.length - 1);
- }
-
- /**
- * Sorts the array of objects by their string representation
- * in ascending order.
- * <p>
- * This is a version of C.A.R Hoare's Quick Sort algorithm.
- *
- * @param array the array of objects to sort
- * @param start the start index to begin sorting
- * @param stop the end index to stop sorting
- *
- * @exception ArrayIndexOutOfBoundsException when <code>start < 0</code>
- * or <code>end >= array.length</code>
- */
- public static void qSortByString(Object[] array, int start, int stop) {
- if (start >= stop)
- return;
-
- int left = start; // left index
- int right = stop; // right index
- Object temp; // for swapping
-
- // arbitrarily establish a partition element as the midpoint of the array
- String mid = String.valueOf(array[(start + stop) / 2]);
-
- // loop through the array until indices cross
- while (left <= right) {
- // find the first element that is smaller than the partition element from the left
- while ((left < stop) && (String.valueOf(array[left]).compareTo(mid) < 0)) {
- ++left;
- }
- // find an element that is smaller than the partition element from the right
- while ((right > start) && (mid.compareTo(String.valueOf(array[right])) < 0)) {
- --right;
- }
- // if the indices have not crossed, swap
- if (left <= right) {
- temp = array[left];
- array[left] = array[right];
- array[right] = temp;
- ++left;
- --right;
- }
- }
- // sort the left partition, if the right index has not reached the left side of array
- if (start < right) {
- qSortByString(array, start, right);
- }
- // sort the right partition, if the left index has not reached the right side of array
- if (left < stop) {
- qSortByString(array, left, stop);
- }
- }
-
- /**
- * Sorts the specified range in the array in ascending order.
- *
- * @param array the Object array to be sorted
- * @param start the start index to sort
- * @param end the last + 1 index to sort
- *
- * @exception ClassCastException when an element in the array does not
- * implement Comparable or elements cannot be compared to each other
- * @exception IllegalArgumentException when <code>start > end</code>
- * @exception ArrayIndexOutOfBoundsException when <code>start < 0</code>
- * or <code>end > array.size()</code>
- */
- @SuppressWarnings("unchecked")
- public static void sort(Object[] array, int start, int end) {
- int middle = (start + end) / 2;
- if (start + 1 < middle)
- sort(array, start, middle);
- if (middle + 1 < end)
- sort(array, middle, end);
- if (start + 1 >= end)
- return; // this case can only happen when this method is called by the user
- if (((Comparable<Object>) array[middle - 1]).compareTo(array[middle]) <= 0)
- return;
- if (start + 2 == end) {
- Object temp = array[start];
- array[start] = array[middle];
- array[middle] = temp;
- return;
- }
- int i1 = start, i2 = middle, i3 = 0;
- Object[] merge = new Object[end - start];
- while (i1 < middle && i2 < end) {
- merge[i3++] = ((Comparable<Object>) array[i1]).compareTo(array[i2]) <= 0 ? array[i1++] : array[i2++];
- }
- if (i1 < middle)
- System.arraycopy(array, i1, merge, i3, middle - i1);
- System.arraycopy(merge, 0, array, start, i2 - start);
- }
-
- /**
- * Sorts the specified range in the array in descending order.
- *
- * @param array the Object array to be sorted
- * @param start the start index to sort
- * @param end the last + 1 index to sort
- *
- * @exception ClassCastException when an element in the array does not
- * implement Comparable or elements cannot be compared to each other
- * @exception IllegalArgumentException when <code>start > end</code>
- * @exception ArrayIndexOutOfBoundsException when <code>start < 0</code>
- * or <code>end > array.size()</code>
- */
- public static void dsort(Object[] array, int start, int end) {
- // first sort in ascending order
- sort(array, start, end);
- // then swap the elements in the array
- swap(array);
- }
-
- /**
- * Reverse the elements in the array.
- *
- * @param array the Object array to be reversed
- */
- public static void swap(Object[] array) {
- int start = 0;
- int end = array.length - 1;
- while (start < end) {
- Object temp = array[start];
- array[start++] = array[end];
- array[end--] = temp;
- }
- }
-
- /**
- * Returns a string representation of the object
- * in the given length.
- * If the string representation of the given object
- * is longer then it is truncated.
- * If it is shorter then it is padded with the blanks
- * to the given total length.
- * If the given object is a number then the padding
- * is done on the left, otherwise on the right.
- *
- * @param object the object to convert
- * @param length the length the output string
- */
- public static String toString(Object object, int length) {
- boolean onLeft = object instanceof Number;
- return toString(object, length, ' ', onLeft);
- }
-
- /**
- * Returns a string representation of the object
- * in the given length.
- * If the string representation of the given object
- * is longer then it is truncated.
- * If it is shorter then it is padded to the left or right
- * with the given character to the given total length.
- *
- * @param object the object to convert
- * @param length the length the output string
- * @param pad the pad character
- * @param onLeft if <code>true</code> pad on the left, otherwise an the right
- */
- public static String toString(Object object, int length, char pad, boolean onLeft) {
- String input = String.valueOf(object);
- int size = input.length();
- if (size >= length) {
- int start = (onLeft) ? size - length : 0;
- return input.substring(start, length);
- }
-
- StringBuffer padding = new StringBuffer(length - size);
- for (int i = size; i < length; i++)
- padding.append(pad);
-
- StringBuffer stringBuffer = new StringBuffer(length);
- if (onLeft)
- stringBuffer.append(padding.toString());
- stringBuffer.append(input);
- if (!onLeft)
- stringBuffer.append(padding.toString());
- return stringBuffer.toString();
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerFactoryProxyFor15.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerFactoryProxyFor15.java
deleted file mode 100644
index ddfaf80f3..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/protocol/URLStreamHandlerFactoryProxyFor15.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.protocol;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.*;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.url.URLStreamHandlerService;
-
-public class URLStreamHandlerFactoryProxyFor15 extends URLStreamHandlerProxy {
-
- public URLStreamHandlerFactoryProxyFor15(String protocol, ServiceReference<URLStreamHandlerService> reference, BundleContext context) {
- super(protocol, reference, context);
- }
-
- protected URLConnection openConnection(URL u, Proxy p) throws IOException {
- try {
- Method openConn = realHandlerService.getClass().getMethod("openConnection", new Class[] {URL.class, Proxy.class}); //$NON-NLS-1$
- return (URLConnection) openConn.invoke(realHandlerService, new Object[] {u, p});
- } catch (InvocationTargetException e) {
- if (e.getTargetException() instanceof IOException)
- throw (IOException) e.getTargetException();
- throw (RuntimeException) e.getTargetException();
- } catch (Exception e) {
- // expected on JRE < 1.5
- throw (UnsupportedOperationException) new UnsupportedOperationException().initCause(e);
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoaderProxy.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoaderProxy.java
deleted file mode 100644
index fa30a83b3..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/BundleLoaderProxy.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.loader;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.List;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.util.KeyedHashSet;
-import org.eclipse.osgi.framework.util.SecureAction;
-import org.eclipse.osgi.internal.composite.CompositeBase;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.ExportPackageDescription;
-import org.osgi.framework.*;
-import org.osgi.service.packageadmin.RequiredBundle;
-
-/*
- * The BundleLoaderProxy proxies a BundleLoader object for a Bundle. This
- * allows for a Bundle's depedencies to be linked without forcing the
- * creating of the BundleLoader or BundleClassLoader objects. This class
- * keeps track of the depedencies between the bundles installed in the
- * Framework.
- */
-public class BundleLoaderProxy implements RequiredBundle, BundleReference {
- static SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
- // The BundleLoader that this BundleLoaderProxy is managing
- private BundleLoader loader;
- // The Bundle that this BundleLoaderProxy is for
- final private BundleHost bundle;
- // the BundleDescription for the Bundle
- final private BundleDescription description;
- // the BundleData for the bundle revision
- final private BundleData data;
- // Indicates if this BundleLoaderProxy is stale;
- // this is true when the bundle is updated or uninstalled.
- private boolean stale = false;
- // cached of package sources for the bundle
- final private KeyedHashSet pkgSources;
-
- public BundleLoaderProxy(BundleHost bundle, BundleDescription description) {
- this.bundle = bundle;
- this.description = description;
- this.pkgSources = new KeyedHashSet(false);
- this.data = bundle.getBundleData();
- }
-
- public BundleLoader getBundleLoader() {
- if (System.getSecurityManager() == null)
- return getBundleLoader0();
- return AccessController.doPrivileged(new PrivilegedAction<BundleLoader>() {
- public BundleLoader run() {
- return getBundleLoader0();
- }
- });
- }
-
- synchronized BundleLoader getBundleLoader0() {
- if (loader != null)
- return loader;
- if (bundle.isResolved()) {
- try {
- if (bundle.getBundleId() == 0) // this is the system bundle
- loader = new SystemBundleLoader(bundle, this);
- else
- loader = new BundleLoader(bundle, this);
- } catch (BundleException e) {
- bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
- return null;
- }
- }
- return loader;
- }
-
- public BundleLoader getBasicBundleLoader() {
- return loader;
- }
-
- public AbstractBundle getBundleHost() {
- return bundle;
- }
-
- void setStale() {
- stale = true;
- }
-
- public boolean isStale() {
- return stale;
- }
-
- public String toString() {
- String symbolicName = bundle.getSymbolicName();
- StringBuffer sb = new StringBuffer(symbolicName == null ? bundle.getBundleData().getLocation() : symbolicName);
- sb.append("; ").append(Constants.BUNDLE_VERSION_ATTRIBUTE); //$NON-NLS-1$
- sb.append("=\"").append(description.getVersion().toString()).append("\""); //$NON-NLS-1$//$NON-NLS-2$
- return sb.toString();
- }
-
- public org.osgi.framework.Bundle getBundle() {
- if (isStale())
- return null;
-
- return bundle;
- }
-
- public BundleData getBundleData() {
- return data;
- }
-
- public Bundle[] getRequiringBundles() {
- if (isStale())
- return null;
- // This is VERY slow; but never gets called in regular execution.
- BundleDescription[] dependents = description.getDependents();
- if (dependents == null || dependents.length == 0)
- return new Bundle[0];
- List<Bundle> result = new ArrayList<Bundle>(dependents.length);
- for (int i = 0; i < dependents.length; i++)
- addRequirers(dependents[i], result);
- return result.toArray(new org.osgi.framework.Bundle[result.size()]);
- }
-
- void addRequirers(BundleDescription dependent, List<Bundle> result) {
- if (dependent.getHost() != null) // don't look in fragments.
- return;
- BundleLoaderProxy dependentProxy = getBundleLoader().getLoaderProxy(dependent);
- if (dependentProxy == null)
- return; // bundle must have been uninstalled
- if (result.contains(dependentProxy.bundle))
- return; // prevent endless recusion
- BundleLoader dependentLoader = dependentProxy.getBundleLoader();
- BundleLoaderProxy[] requiredBundles = dependentLoader.requiredBundles;
- int[] reexportTable = dependentLoader.reexportTable;
- if (requiredBundles == null)
- return;
- int size = reexportTable == null ? 0 : reexportTable.length;
- int reexportIndex = 0;
- for (int i = 0; i < requiredBundles.length; i++) {
- if (requiredBundles[i] == this) {
- result.add(dependentProxy.bundle);
- if (reexportIndex < size && reexportTable[reexportIndex] == i) {
- reexportIndex++;
- BundleDescription[] dependents = dependent.getDependents();
- if (dependents == null)
- return;
- for (int j = 0; j < dependents.length; j++)
- dependentProxy.addRequirers(dependents[j], result);
- }
- return;
- }
- }
- return;
- }
-
- public String getSymbolicName() {
- return description.getSymbolicName();
- }
-
- public Version getVersion() {
- return description.getVersion();
- }
-
- public boolean isRemovalPending() {
- return description.isRemovalPending();
- }
-
- public BundleDescription getBundleDescription() {
- return description;
- }
-
- PackageSource getPackageSource(String pkgName) {
- // getByKey is called outside of a synch block because we really do not
- // care too much of duplicates getting created. Only the first one will
- // successfully get stored into pkgSources
- PackageSource pkgSource = (PackageSource) pkgSources.getByKey(pkgName);
- if (pkgSource == null) {
- pkgSource = new SingleSourcePackage(pkgName, this);
- synchronized (pkgSources) {
- pkgSources.add(pkgSource);
- }
- }
- return pkgSource;
- }
-
- public boolean inUse() {
- return (description.getDependents().length > 0) || ((bundle instanceof CompositeBase) && description.getResolvedImports().length > 0);
- }
-
- boolean forceSourceCreation(ExportPackageDescription export) {
- boolean strict = Constants.STRICT_MODE.equals(secureAction.getProperty(Constants.OSGI_RESOLVER_MODE));
- return (export.getDirective(Constants.INCLUDE_DIRECTIVE) != null) || (export.getDirective(Constants.EXCLUDE_DIRECTIVE) != null) || (strict && export.getDirective(Constants.FRIENDS_DIRECTIVE) != null);
- }
-
- // creates a PackageSource from an ExportPackageDescription. This is called when initializing
- // a BundleLoader to ensure that the proper PackageSource gets created and used for
- // filtered and reexport packages. The storeSource flag is used by initialize to indicate
- // that the source for special case package sources (filtered or re-exported should be stored
- // in the cache. if this flag is set then a normal SinglePackageSource will not be created
- // (i.e. it will be created lazily)
- public PackageSource createPackageSource(ExportPackageDescription export, boolean storeSource) {
- PackageSource pkgSource = null;
-
- // check to see if it is a filtered export
- String includes = (String) export.getDirective(Constants.INCLUDE_DIRECTIVE);
- String excludes = (String) export.getDirective(Constants.EXCLUDE_DIRECTIVE);
- String[] friends = (String[]) export.getDirective(Constants.FRIENDS_DIRECTIVE);
- if (friends != null) {
- boolean strict = Constants.STRICT_MODE.equals(secureAction.getProperty(Constants.OSGI_RESOLVER_MODE));
- if (!strict)
- friends = null; // do not pay attention to friends if not in strict mode
- }
- if (includes != null || excludes != null || friends != null) {
- pkgSource = new FilteredSourcePackage(export.getName(), this, includes, excludes, friends);
- }
-
- if (storeSource) {
- // if the package source is not null then store the source only if it is not already present;
- // getByKey is called outside of a synch block because we really do not
- // care too much of duplicates getting created. Only the first one will
- // successfully get stored into pkgSources
- if (pkgSource != null && pkgSources.getByKey(export.getName()) == null)
- synchronized (pkgSources) {
- pkgSources.add(pkgSource);
- }
- } else {
- // we are not storing the special case sources, but pkgSource == null this means this
- // is a normal package source; get it and return it.
- if (pkgSource == null) {
- pkgSource = getPackageSource(export.getName());
- // the first export cached may not be a simple single source like we need.
- if (pkgSource.getClass() != SingleSourcePackage.class)
- return new SingleSourcePackage(export.getName(), this);
- }
- }
-
- return pkgSource;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/PackageSource.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/PackageSource.java
deleted file mode 100644
index 0f2d98835..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/PackageSource.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.loader;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Enumeration;
-import org.eclipse.osgi.framework.util.KeyedElement;
-
-public abstract class PackageSource implements KeyedElement {
- protected String id;
-
- public PackageSource(String id) {
- // others depend on the id being interned; see SingleSourcePackage.equals
- this.id = id.intern();
- }
-
- public String getId() {
- return id;
- }
-
- public abstract SingleSourcePackage[] getSuppliers();
-
- public boolean compare(KeyedElement other) {
- return id.equals(((PackageSource) other).getId());
- }
-
- public int getKeyHashCode() {
- return id.hashCode();
- }
-
- public Object getKey() {
- return id;
- }
-
- public boolean isNullSource() {
- return false;
- }
-
- public boolean isFriend(String symbolicName) {
- return true;
- }
-
- public abstract Class<?> loadClass(String name) throws ClassNotFoundException;
-
- public abstract URL getResource(String name);
-
- public abstract Enumeration<URL> getResources(String name) throws IOException;
-
- //TODO See how this relates with FilteredSourcePackage. Overwriting or doing a double dispatch might be good.
- // This is intentionally lenient; we don't force all suppliers to match (only one)
- // it is better to get class cast exceptions in split package cases than miss an event
- public boolean hasCommonSource(PackageSource other) {
- if (other == null)
- return false;
- if (this == other)
- return true;
- SingleSourcePackage[] suppliers1 = getSuppliers();
- SingleSourcePackage[] suppliers2 = other.getSuppliers();
- if (suppliers1 == null || suppliers2 == null)
- return false;
- // This will return true if the specified source has at least one
- // of the suppliers of this source.
- for (int i = 0; i < suppliers1.length; i++)
- for (int j = 0; j < suppliers2.length; j++)
- if (suppliers2[j].equals(suppliers1[i]))
- return true;
- return false;
- }
-
- public abstract Collection<String> listResources(String path, String filePattern);
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SystemBundleLoader.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SystemBundleLoader.java
deleted file mode 100644
index 252fdb2cb..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/loader/SystemBundleLoader.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.loader;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.internal.core.BundleFragment;
-import org.eclipse.osgi.framework.internal.core.BundleHost;
-import org.eclipse.osgi.service.resolver.ExportPackageDescription;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.wiring.BundleWiring;
-
-/**
- * The System Bundle's BundleLoader. This BundleLoader is used by ImportClassLoaders
- * to load a resource that is exported by the System Bundle.
- */
-public class SystemBundleLoader extends BundleLoader {
- public static final String EQUINOX_EE = "x-equinox-ee"; //$NON-NLS-1$
- final ClassLoader classLoader;
- private final Set<String> eePackages;
- private final Set<String> extPackages;
- private final ClassLoader extClassLoader;
-
- /**
- * @param bundle The system bundle.
- * @param proxy The BundleLoaderProxy for the system bundle
- * @throws BundleException On any error.
- */
- protected SystemBundleLoader(BundleHost bundle, BundleLoaderProxy proxy) throws BundleException {
- super(bundle, proxy);
- ExportPackageDescription[] exports = proxy.getBundleDescription().getSelectedExports();
- if (exports == null || exports.length == 0)
- eePackages = null;
- else {
- eePackages = new HashSet<String>(exports.length);
- for (int i = 0; i < exports.length; i++)
- if (((Integer) exports[i].getDirective(EQUINOX_EE)).intValue() >= 0)
- eePackages.add(exports[i].getName());
- }
- this.classLoader = getClass().getClassLoader();
- extPackages = new HashSet<String>(0); // not common; start with 0
- BundleFragment[] fragments = bundle.getFragments();
- if (fragments != null)
- for (int i = 0; i < fragments.length; i++)
- addExtPackages(fragments[i]);
- ClassLoader extCL = ClassLoader.getSystemClassLoader();
- if (extCL == null)
- extClassLoader = null;
- else {
- while (extCL.getParent() != null)
- extCL = extCL.getParent();
- // make sure extCL is not already on the parent chain of the system classloader
- boolean found = false;
- ClassLoader systemExtCL = this.classLoader;
- while (systemExtCL.getParent() != null && !found) {
- if (systemExtCL.getParent() == extCL)
- found = true;
- else
- systemExtCL = systemExtCL.getParent();
- }
- extClassLoader = found ? null : extCL;
- }
- }
-
- private void addExtPackages(BundleFragment fragment) {
- if ((fragment.getBundleData().getType() & BundleData.TYPE_EXTCLASSPATH_EXTENSION) == 0)
- return;
- ExportPackageDescription[] extExports = fragment.getBundleDescription().getExportPackages();
- for (int j = 0; j < extExports.length; j++)
- extPackages.add(extExports[j].getName());
- }
-
- synchronized public void attachFragment(BundleFragment fragment) throws BundleException {
- super.attachFragment(fragment);
- synchronized (extPackages) {
- addExtPackages(fragment);
- }
- }
-
- /**
- * The ClassLoader that loads OSGi framework classes is used to find the class.
- * This method never gets called because there is no BundleClassLoader for the framework.
- */
- public Class<?> findClass(String name) throws ClassNotFoundException {
- Class<?> result = findLocalClass(name);
- if (result == null)
- throw new ClassNotFoundException(name);
- return result;
- }
-
- /**
- * This method will always return null.
- * This method never gets called because there is no BundleClassLoader for the framework.
- */
- public String findLibrary(String name) {
- return null;
- }
-
- /**
- * The ClassLoader that loads OSGi framework classes is used to find the class.
- */
- Class<?> findLocalClass(String name) {
- try {
- return classLoader.loadClass(name);
- } catch (ClassNotFoundException e) {
- if (extClassLoader != null)
- synchronized (extPackages) {
- if (extPackages.size() > 0 && extPackages.contains(BundleLoader.getPackageName(name)))
- try {
- return extClassLoader.loadClass(name);
- } catch (ClassNotFoundException e2) {
- return null;
- }
- }
- }
- return null;
- }
-
- /**
- * The ClassLoader that loads OSGi framework classes is used to find the resource.
- */
- URL findLocalResource(String name) {
- URL result = classLoader.getResource(name);
- if (result == null && extClassLoader != null)
- synchronized (extPackages) {
- if (extPackages.size() > 0 && extPackages.contains(BundleLoader.getResourcePackageName(name)))
- result = extClassLoader.getResource(name);
- }
- return result;
- }
-
- /**
- * The ClassLoader that loads OSGi framework classes is used to find the resource.
- */
- Enumeration<URL> findLocalResources(String name) {
- Enumeration<URL> result = null;
- try {
- result = classLoader.getResources(name);
- } catch (IOException e) {
- // do nothing
- }
- if ((result == null || !result.hasMoreElements()) && extClassLoader != null)
- synchronized (extPackages) {
- if (extPackages.size() > 0 && extPackages.contains(BundleLoader.getResourcePackageName(name)))
- try {
- result = extClassLoader.getResources(name);
- } catch (IOException e) {
- // do nothing
- }
- }
- return result;
- }
-
- /**
- * The ClassLoader that loads OSGi framework classes is used to find the resource.
- * This method never gets called because there is no BundleClassLoader for the framework.
- */
- public URL findResource(String name) {
- return findLocalResource(name);
- }
-
- /**
- * The ClassLoader that loads OSGi framework classes is used to find the resource.
- * This method never gets called because there is no BundleClassLoader for the framework.
- * @throws IOException
- */
- public Enumeration<URL> findResources(String name) throws IOException {
- return findLocalResources(name);
- }
-
- /**
- * Do nothing on a close.
- */
- protected void close() {
- // Do nothing.
- }
-
- public boolean isEEPackage(String pkgName) {
- return eePackages.contains(pkgName);
- }
-
- BundleClassLoader createBCL(BundleProtectionDomain pd, String[] cp) {
- return new BundleClassLoader() {
-
- public Bundle getBundle() {
- return SystemBundleLoader.this.getBundle();
- }
-
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- return SystemBundleLoader.this.loadClass(name);
- }
-
- public void initialize() {
- // nothing
- }
-
- /**
- * @throws IOException
- */
- public Enumeration<URL> getResources(String name) throws IOException {
- return findLocalResources(name);
- }
-
- public URL getResource(String name) {
- return SystemBundleLoader.this.findLocalResource(name);
- }
-
- public ClassLoader getParent() {
- return SystemBundleLoader.this.classLoader.getParent();
- }
-
- public ClassLoaderDelegate getDelegate() {
- return SystemBundleLoader.this;
- }
-
- public Enumeration<URL> findLocalResources(String resource) {
- return SystemBundleLoader.this.findLocalResources(resource);
- }
-
- public URL findLocalResource(String resource) {
- return getResource(resource);
- }
-
- /**
- * @throws ClassNotFoundException
- */
- public Class<?> findLocalClass(String classname) throws ClassNotFoundException {
- return SystemBundleLoader.this.findLocalClass(classname);
- }
-
- public void close() {
- // nothing
- }
-
- public void attachFragment(BundleData bundledata, ProtectionDomain domain, String[] classpath) {
- // nothing
- }
-
- public List<URL> findEntries(String path, String filePattern, int options) {
- Bundle systemBundle = SystemBundleLoader.this.getBundle();
- boolean recurse = (options & BundleWiring.FINDENTRIES_RECURSE) != 0;
- @SuppressWarnings("unchecked")
- List<URL> result = Collections.EMPTY_LIST;
- Enumeration<URL> entries = systemBundle.findEntries(path, filePattern, recurse);
- if (entries != null) {
- result = new ArrayList<URL>();
- while (entries.hasMoreElements())
- result.add(entries.nextElement());
- }
- return Collections.unmodifiableList(result);
- }
-
- @SuppressWarnings("unchecked")
- public Collection<String> listResources(String path, String filePattern, int options) {
- return Collections.EMPTY_LIST;
- }
-
- @SuppressWarnings("unchecked")
- public Collection<String> listLocalResources(String path, String filePattern, int options) {
- return Collections.EMPTY_LIST;
- }
- };
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurePermissionStorage.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurePermissionStorage.java
deleted file mode 100644
index 270212b85..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurePermissionStorage.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.permadmin;
-
-import java.io.IOException;
-import java.security.*;
-import org.eclipse.osgi.framework.adaptor.PermissionStorage;
-
-/**
- * PermissionStorage privileged action class. This class is not thread safe. Callers
- * must ensure multiple threads do not call methods on this class at the same time.
- */
-public class SecurePermissionStorage implements PermissionStorage, PrivilegedExceptionAction<String[]> {
- private final PermissionStorage storage;
- private String location;
- private String[] data;
- private String[] infos;
- private int action;
- private static final int GET = 1;
- private static final int SET = 2;
- private static final int LOCATION = 3;
- private static final int GET_INFOS = 4;
- private static final int SAVE_INFOS = 5;
-
- public SecurePermissionStorage(PermissionStorage storage) {
- this.storage = storage;
- }
-
- public String[] run() throws IOException {
- switch (action) {
- case GET :
- return storage.getPermissionData(location);
- case SET :
- storage.setPermissionData(location, data);
- return null;
- case LOCATION :
- return storage.getLocations();
- case SAVE_INFOS :
- storage.saveConditionalPermissionInfos(infos);
- return null;
- case GET_INFOS :
- return storage.getConditionalPermissionInfos();
- }
-
- throw new UnsupportedOperationException();
- }
-
- public String[] getPermissionData(String loc) throws IOException {
- this.location = loc;
- this.action = GET;
-
- try {
- return AccessController.doPrivileged(this);
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
- }
- }
-
- public String[] getLocations() throws IOException {
- this.action = LOCATION;
-
- try {
- return AccessController.doPrivileged(this);
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
- }
- }
-
- public void setPermissionData(String location, String[] data) throws IOException {
- this.location = location;
- this.data = data;
- this.action = SET;
-
- try {
- AccessController.doPrivileged(this);
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
- }
- }
-
- public void saveConditionalPermissionInfos(String[] updatedInfos) throws IOException {
- this.action = SAVE_INFOS;
- this.infos = updatedInfos;
- try {
- AccessController.doPrivileged(this);
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
- }
-
- }
-
- public String[] getConditionalPermissionInfos() throws IOException {
- this.action = GET_INFOS;
- try {
- return AccessController.doPrivileged(this);
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/default.permissions b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/default.permissions
deleted file mode 100644
index e04a88990..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/default.permissions
+++ /dev/null
@@ -1,25 +0,0 @@
-########################################################################
-# Copyright (c) 2003, 2005 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-########################################################################
-
-# Lines beginning with '#' or '//' are comments
-#
-# This file contains the default permissions to be granted
-# to bundles with no specific permission if there are no
-# default permission set. This file must be UTF8 encoded.
-#
-# In this file, FilePermissions with relative names are not
-# mapped to an individual bundle's data directory.
-#
-# The permissions are listed one per
-# line in PermissionInfo encoded format.
-# See org.osgi.service.permissionadmin.PermissionInfo
-
-(java.security.AllPermission)
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/DefaultProfileLogger.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/DefaultProfileLogger.java
deleted file mode 100644
index 00d60d93d..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/DefaultProfileLogger.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.profile;
-
-import java.io.*;
-import java.util.*;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-
-public class DefaultProfileLogger implements ProfileLogger {
- protected static final String DEFAULTPROFILE_PROP = "osgi.defaultprofile."; //$NON-NLS-1$
- protected static final String PROP_FILENAME = DEFAULTPROFILE_PROP + "logfilename"; //$NON-NLS-1$
- protected static final String PROP_LOGSYNCHRONOUSLY = DEFAULTPROFILE_PROP + "logsynchronously"; //$NON-NLS-1$
- protected static final String PROP_BUFFERSIZE = DEFAULTPROFILE_PROP + "buffersize"; //$NON-NLS-1$
-
- protected static final String DEFAULTPROFILE_OPTION = "org.eclipse.osgi/defaultprofile/"; //$NON-NLS-1$
- protected static final String OPTION_FILENAME = DEFAULTPROFILE_OPTION + "logfilename"; //$NON-NLS-1$
- protected static final String OPTION_LOGSYNCHRONOUSLY = DEFAULTPROFILE_OPTION + "logsynchronously"; //$NON-NLS-1$
- protected static final String OPTION_BUFFERSIZE = DEFAULTPROFILE_OPTION + "buffersize"; //$NON-NLS-1$
-
- protected boolean logSynchronously = false;
- protected long startTime = 0;
- protected static final int DEFAULT_BUFFER_SIZE = 256;
-
- protected TimeEntry[] timeLogEntries = null;
- protected int timeEntriesIndex = 0;
- protected StringBuffer timelog = null;
-
- protected long launchTime = -1;
- protected int bufferSize = DEFAULT_BUFFER_SIZE;
- protected String logFileName = null;
- protected File logFile = null;
- private StringBuffer entryReport = new StringBuffer(120);
- private StringBuffer padsb = new StringBuffer(16); // to prevent creating this over and over
- protected int indent;
- protected int timePaddingLength;
- protected Stack<AccumPerfScope> scopeStack;
- protected Map<String, AccumPerfData> scopeToAccumPerfDataMap;
-
- public DefaultProfileLogger() {
- initProps();
-
- int size = getBufferSize();
- timeLogEntries = new TimeEntry[size];
- timelog = new StringBuffer(4096);
- for (int i = 0; i < size; i++) {
- timeLogEntries[i] = timeEntryFactory();
- }
- timeEntriesIndex = 0;
-
- launchTime = getLaunchTime();
- if (launchTime == -1) {
- startTime = getMainStartTime();
- } else {
- startTime = launchTime;
- }
-
- long freq = getTimerFrequency();
- for (timePaddingLength = 3; freq > 9; timePaddingLength++) {
- freq /= 10;
- }
-
- logInitMessages();
- }
-
- protected void logInitMessages() {
- int index = 0;
- if (launchTime != -1L) {
- logTime(Profile.FLAG_NONE, "DefaultProfileLogger.init()", "launch time initialized", null); //$NON-NLS-1$//$NON-NLS-2$
- timeLogEntries[index++].time = launchTime;
- }
-
- logTime(Profile.FLAG_NONE, "DefaultProfileLogger.init()", "start time initialized", null); //$NON-NLS-1$//$NON-NLS-2$
- timeLogEntries[index++].time = getMainStartTime();
- }
-
- protected long getLaunchTime() {
- String launchTimeString = FrameworkProperties.getProperty("launch.startMillis"); //$NON-NLS-1$
- if (launchTimeString != null) {
- return Long.parseLong(launchTimeString);
- }
- return -1L;
- }
-
- protected long getMainStartTime() {
- String timeString = FrameworkProperties.getProperty("eclipse.startTime"); //$NON-NLS-1$
- if (timeString != null)
- return Long.parseLong(timeString);
-
- return System.currentTimeMillis();
- }
-
- public void initProps() {
- String prop;
- FrameworkDebugOptions dbgOptions = null;
- // if osgi.debug is not available, don't force DebugOptions
- // to init as this variable may be set later on where
- // DebugOptions will succeed.
- if (FrameworkProperties.getProperty("osgi.debug") != null) { //$NON-NLS-1$
- dbgOptions = FrameworkDebugOptions.getDefault();
- if (dbgOptions != null) {
- logFileName = dbgOptions.getOption(OPTION_FILENAME);
- logSynchronously = dbgOptions.getBooleanOption(OPTION_LOGSYNCHRONOUSLY, false);
- int size = dbgOptions.getIntegerOption(OPTION_BUFFERSIZE, 0);
- if (size > 0)
- bufferSize = size;
- }
- }
-
- if ((prop = FrameworkProperties.getProperty(PROP_FILENAME)) != null) {
- logFileName = prop;
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_FILENAME, logFileName);
- }
- if ((prop = FrameworkProperties.getProperty(PROP_LOGSYNCHRONOUSLY)) != null) {
- logSynchronously = Boolean.valueOf(prop).booleanValue();
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_LOGSYNCHRONOUSLY, new Boolean(logSynchronously).toString());
- }
- if ((prop = FrameworkProperties.getProperty(PROP_BUFFERSIZE)) != null) {
- try {
- int value = Integer.parseInt(prop);
- if (value > 0) {
- bufferSize = value;
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_BUFFERSIZE, Integer.toString(bufferSize));
- }
- } catch (NumberFormatException e) {
- // do nothing
- }
- }
- }
-
- public synchronized void logTime(int flag, String id, String msg, String description) {
- if (timeEntriesIndex == timeLogEntries.length) {
- makeLog();
- logTime(Profile.FLAG_NONE, "Profile.logTime()", "log entries rolled", null); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- TimeEntry entry = timeLogEntries[timeEntriesIndex++];
- entry.time = getTime();
- entry.id = id;
- entry.msg = msg;
- entry.flag = flag;
- entry.description = description;
-
- if (logSynchronously) {
- System.out.print(getProfileLog().substring(2));
- }
- }
-
- public synchronized String getProfileLog() {
- String log;
- log = getProfileLogReport();
- writeToProfileLogFile(log);
- return log;
- }
-
- public synchronized void accumLogEnter(String scope) {
- // Initialize our data structures
- if (scopeStack == null)
- scopeStack = new Stack<AccumPerfScope>();
- if (scopeToAccumPerfDataMap == null)
- scopeToAccumPerfDataMap = new TreeMap<String, AccumPerfData>();
-
- // We want getTime() to evaluate as late as possible
- scopeStack.push(new AccumPerfScope(scope, getTime()));
- }
-
- public synchronized void accumLogExit(String scope) {
- // What time is it?
- long exit = getTime();
-
- // Initialize our data structures
- if (scopeStack == null)
- scopeStack = new Stack<AccumPerfScope>();
- if (scopeToAccumPerfDataMap == null)
- scopeToAccumPerfDataMap = new TreeMap<String, AccumPerfData>();
-
- // Do our calculations
- AccumPerfScope then = scopeStack.pop();
- if (then == null)
- System.err.println("ACCUM PERF ERROR: Scope stack empty: " + scope); //$NON-NLS-1$
- else {
- if (!then.scope.equals(scope))
- System.err.println("ACCUM PERF ERROR: Scope mismatch: then='" + then.scope + "', now='" + scope + "'"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
-
- AccumPerfData now = scopeToAccumPerfDataMap.get(scope);
- if (now == null) {
- now = new AccumPerfData(scope);
- scopeToAccumPerfDataMap.put(scope, now);
- }
-
- now.time += exit - then.enter;
- now.enters++;
- }
- }
-
- protected long getTime() {
- return System.currentTimeMillis();
- }
-
- protected long getTimerFrequency() {
- return 1000L; // millisecond
- }
-
- protected TimeEntry findCompareEntry(int index, String id, int flag) {
- if (index > 0)
- index--;
- int prev = index;
- if (flag != Profile.FLAG_ENTER) {
- while (index >= 0) {
- TimeEntry entry = timeLogEntries[index];
- if (entry.id.equals(id)) {
- switch (flag) {
- case Profile.FLAG_NONE :
- return entry;
- case Profile.FLAG_EXIT :
- if (entry.flag == Profile.FLAG_ENTER)
- return entry;
- break;
- }
- }
- index--;
- }
- }
- return timeLogEntries[prev];
- }
-
- protected String entryReport(TimeEntry entry, TimeEntry compareWith) {
- // indent level:
- entryReport.setLength(0);
- if (entry.flag == Profile.FLAG_ENTER)
- indent++;
- long zeroTime = getRelativeTime(getStartTime());
-
- entryReport.append('-');
- long entryTime = getRelativeTime(entry.time);
- long diff = entryTime - zeroTime;
- entryReport.append(pad(Long.toString(diff), timePaddingLength));
- entryReport.append(" :"); //$NON-NLS-1$
- diff = entry.time - compareWith.time;
- entryReport.append(pad(Long.toString(diff), timePaddingLength));
- entryReport.append(pad("", indent * 2)); // indent before displaying the entry.id //$NON-NLS-1$
-
- if (entry.flag == Profile.FLAG_ENTER)
- entryReport.append(" >> "); //$NON-NLS-1$
- else if (entry.flag == Profile.FLAG_EXIT)
- entryReport.append(" << "); //$NON-NLS-1$
- else if (entry.flag == Profile.FLAG_NONE)
- entryReport.append(" -- "); //$NON-NLS-1$
-
- entryReport.append(entry.id);
- entryReport.append(" > "); //$NON-NLS-1$
- entryReport.append(entry.msg);
- if (entry.description != null) {
- entryReport.append(" :: "); //$NON-NLS-1$
- entryReport.append(entry.description);
- }
- entryReport.append("\r\n"); //$NON-NLS-1$
-
- if (entry.flag == Profile.FLAG_EXIT)
- indent -= 1;
- return entryReport.toString();
- }
-
- protected String accumEntryReport(AccumPerfData d) {
- return (" " + d.scope + ":enters=" + d.enters + ";time=" + d.time + ";\r\n"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
- }
-
- protected void makeLog() {
- indent = 0;
- timelog.append("\r\n"); //$NON-NLS-1$
- for (int i = 0; i < timeEntriesIndex; i++) {
- TimeEntry entry = timeLogEntries[i];
- TimeEntry cmpEntry = findCompareEntry(i, entry.id, entry.flag);
- timelog.append(entryReport(entry, cmpEntry));
- }
- timeEntriesIndex = 0;
-
- if (scopeToAccumPerfDataMap == null || scopeToAccumPerfDataMap.isEmpty())
- return; // No data; nothing to do
- timelog.append("\r\n"); //$NON-NLS-1$
- timelog.append("Cumulative Log:\r\n"); //$NON-NLS-1$
- for (AccumPerfData d : scopeToAccumPerfDataMap.values()) {
- timelog.append(accumEntryReport(d));
- }
- scopeToAccumPerfDataMap.clear();
- }
-
- protected String pad(String str, int size) {
- padsb.setLength(0);
- int len = str.length();
- int count = size - len;
- for (int i = 0; i < count; i++)
- padsb.append(' ');
- padsb.append(str);
- return padsb.toString();
- }
-
- protected String getProfileLogReport() {
- if (timelog == null)
- return ""; //$NON-NLS-1$
- makeLog();
- String log = timelog.toString();
- timelog.setLength(0);
- return log;
- }
-
- protected void writeToProfileLogFile(String log) {
- File profileLog = getProfileLogFile();
- if (profileLog == null)
- return;
- FileWriter fw = null;
- try {
- fw = new FileWriter(profileLog.getAbsolutePath(), true);
- fw.write(log);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (fw != null)
- try {
- fw.close();
- } catch (IOException e) {
- // do nothing
- }
- }
- }
-
- protected File getProfileLogFile() {
- if (logFile == null)
- if ((logFileName != null) && (logFileName.length() > 0))
- logFile = new File(logFileName);
- return logFile;
- }
-
- protected long getStartTime() {
- return startTime;
- }
-
- protected long getRelativeTime(long absoluteTime) {
- return absoluteTime;
- }
-
- protected int getBufferSize() {
- if (bufferSize < 2)
- return DEFAULT_BUFFER_SIZE;
- return bufferSize;
- }
-
- protected TimeEntry timeEntryFactory() {
- return new TimeEntry();
- }
-
- protected class TimeEntry {
- public long time;
- public String id;
- public String msg;
- public String description;
- public int flag;
- }
-
- protected static class AccumPerfData {
- public AccumPerfData(String scope) {
- this.scope = scope;
- }
-
- public String scope;
- public long time;
- public long enters;
- }
-
- protected static class AccumPerfScope {
- public AccumPerfScope(String scope, long enter) {
- this.scope = scope;
- this.enter = enter;
- }
-
- public String scope;
- public long enter;
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/Profile.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/Profile.java
deleted file mode 100644
index aed3e7eca..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/Profile.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.profile;
-
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-
-/**
- * This class is a development tool that provides a simple way to log
- * programmer defined timmings for performance evaluations. This profiling
- * allows logging of a timestamp with a corresponding message to a trace
- * buffer.
- */
-
-public class Profile {
- /**
- * Profiling is enabled and available.
- */
- public static final boolean PROFILE = true; // enable profile compiling
- /**
- * The logging state of <tt>STARTUP</tt> messages
- */
- public static boolean STARTUP = false; // enable startup profiling
- /**
- * The logging state of <tt>BENCHMARK</tt> messages
- */
- public static boolean BENCHMARK = false; // enable all benchmarking
- /**
- * The logging state of <tt>DEBUG</tt> messages
- */
- public static boolean DEBUG = false; // enable general debug profiling
-
- private static final String OSGI_PROP = "osgi.profile."; //$NON-NLS-1$
- private static final String PROP_STARTUP = OSGI_PROP + "startup"; //$NON-NLS-1$
- private static final String PROP_BENCHMARK = OSGI_PROP + "benchmark"; //$NON-NLS-1$
- private static final String PROP_DEBUG = OSGI_PROP + "debug"; //$NON-NLS-1$
- private static final String PROP_IMPL = OSGI_PROP + "impl"; //$NON-NLS-1$
-
- private static final String OSGI_OPTION = "org.eclipse.osgi/profile/"; //$NON-NLS-1$
- private static final String OPTION_STARTUP = OSGI_OPTION + "startup"; //$NON-NLS-1$
- private static final String OPTION_BENCHMARK = OSGI_OPTION + "benchmark"; //$NON-NLS-1$
- private static final String OPTION_DEBUG = OSGI_OPTION + "debug"; //$NON-NLS-1$
- private static final String OPTION_IMPL = OSGI_OPTION + "impl"; //$NON-NLS-1$
-
- /**
- * The default logging flag.
- */
- public static final int FLAG_NONE = 0;
- /**
- * The logging flag for <strong>method enter</strong>
- */
- public static final int FLAG_ENTER = 1;
- /**
- * The logging flag for <strong>method exit</strong>
- */
- public static final int FLAG_EXIT = 2;
- /**
- * The description for <strong>method enter</strong>
- */
- public static final String ENTER_DESCRIPTION = "enter"; //$NON-NLS-1$
- /**
- * The description for <strong>method exit</strong>
- */
- public static final String EXIT_DESCRIPTION = "exit"; //$NON-NLS-1$
-
- private static ProfileLogger profileLogger = null;
- private static String profileLoggerClassName = null;
-
- static {
- initProps();
- }
-
- /**
- * Initialize/update profiling properties.
- *
- * If profiling properties are updated, this method is called to update
- * the profile states.
- */
- public static void initProps() {
- String prop;
- FrameworkDebugOptions dbgOptions = null;
-
- // if osgi.debug is not available, don't force DebugOptions
- // to init as this variable may be set later on where
- // DebugOptions will succeed.
- if (FrameworkProperties.getProperty("osgi.debug") != null) { //$NON-NLS-1$
- dbgOptions = FrameworkDebugOptions.getDefault();
- if (dbgOptions != null) {
- STARTUP = dbgOptions.getBooleanOption(OPTION_STARTUP, false);
- BENCHMARK = dbgOptions.getBooleanOption(OPTION_BENCHMARK, false);
- DEBUG = dbgOptions.getBooleanOption(OPTION_DEBUG, false);
- if (profileLogger == null)
- profileLoggerClassName = dbgOptions.getOption(OPTION_IMPL);
- }
- }
-
- // System properties will always override anything in .options file
- if ((prop = FrameworkProperties.getProperty(PROP_STARTUP)) != null) {
- STARTUP = Boolean.valueOf(prop).booleanValue();
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_STARTUP, new Boolean(STARTUP).toString());
- }
- if ((prop = FrameworkProperties.getProperty(PROP_BENCHMARK)) != null) {
- BENCHMARK = Boolean.valueOf(prop).booleanValue();
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_BENCHMARK, new Boolean(BENCHMARK).toString());
- }
- if ((prop = FrameworkProperties.getProperty(PROP_DEBUG)) != null) {
- DEBUG = Boolean.valueOf(prop).booleanValue();
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_DEBUG, new Boolean(DEBUG).toString());
- }
-
- if (profileLogger == null) {
- if ((prop = FrameworkProperties.getProperty(PROP_IMPL)) != null) {
- profileLoggerClassName = prop;
- if (dbgOptions != null)
- dbgOptions.setOption(OPTION_IMPL, profileLoggerClassName);
- }
- } else {
- profileLogger.initProps();
- }
- }
-
- /**
- * Log a method enter.
- *
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- */
- public static void logEnter(String id) {
- logTime(FLAG_ENTER, id, ENTER_DESCRIPTION, null);
- }
-
- /**
- * Log a method enter.
- *
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- * @param description A description of the method.
- */
- public static void logEnter(String id, String description) {
- logTime(FLAG_ENTER, id, ENTER_DESCRIPTION, description);
- }
-
- /**
- * Log a method exit.
- *
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- */
- public static void logExit(String id) {
- logTime(FLAG_EXIT, id, EXIT_DESCRIPTION, null);
- }
-
- /**
- * Log a method exit.
- *
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- * @param description A description of the method.
- */
- public static void logExit(String id, String description) {
- logTime(FLAG_EXIT, id, EXIT_DESCRIPTION, description);
- }
-
- /**
- * Log a message.
- *
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- * @param msg The message.
- */
- public static void logTime(String id, String msg) {
- logTime(FLAG_NONE, id, msg, null);
- }
-
- /**
- * Log a message.
- *
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- * @param msg The message.
- * @param description A description of the method.
- */
- public static void logTime(String id, String msg, String description) {
- logTime(FLAG_NONE, id, msg, description);
- }
-
- /**
- * Log a message.
- *
- * @param flag A profile logging flag.
- * @param id The method's unique identification (e.g. org.eclipse.class#name).
- * @param msg The message.
- * @param description A description of the method.
- *
- * @see #FLAG_ENTER
- * @see #FLAG_EXIT
- * @see #FLAG_NONE
- */
- public static void logTime(int flag, String id, String msg, String description) {
- if (profileLogger == null)
- profileLogger = createProfileLogger();
- profileLogger.logTime(flag, id, msg, description);
- }
-
- /**
- * Use cumulative logging to record the entrance from this scope.
- *
- * @param scope The entering scope
- */
- public static void accumLogEnter(String scope) {
- if (profileLogger == null)
- profileLogger = createProfileLogger();
- profileLogger.accumLogEnter(scope);
- }
-
- /**
- * Use cumulative logging to record the exit from this scope.
- *
- * @param scope The exiting scope
- */
- public static void accumLogExit(String scope) {
- if (profileLogger == null)
- profileLogger = createProfileLogger();
- profileLogger.accumLogExit(scope);
- }
-
- /**
- * Get the profiling log report and reset the trace buffer.
- *
- * @return The profiling log report.
- */
- public static String getProfileLog() {
- if (profileLogger != null)
- return profileLogger.getProfileLog();
- return ""; //$NON-NLS-1$
- }
-
- /**
- * Create an instance of the appropriate profile logger
- */
- private static ProfileLogger createProfileLogger() {
- ProfileLogger result = null;
-
- // Try to create it by class name
- if (profileLoggerClassName != null) {
- Class<?> profileImplClass = null;
- try {
- profileImplClass = Class.forName(profileLoggerClassName);
- result = (ProfileLogger) profileImplClass.newInstance();
- } catch (Exception e) {
- // could not find the class
- e.printStackTrace();
- }
- }
-
- // Use the default
- if (result == null)
- result = new DefaultProfileLogger();
-
- return (result);
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/ProfileLogger.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/ProfileLogger.java
deleted file mode 100644
index 31cab05ea..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/profile/ProfileLogger.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.profile;
-
-public interface ProfileLogger {
-
- /**
- *
- *@see Profile#initProps()
- */
- public void initProps();
-
- /**
- *@see Profile#logTime(int, String, String, String)
- */
- public void logTime(int flag, String id, String msg, String description);
-
- /**
- * @see Profile#accumLogEnter(String)
- */
- public void accumLogEnter(String scope);
-
- /**
- * @see Profile#accumLogExit(String)
- */
- public void accumLogExit(String scope);
-
- /**
- *
- * @see Profile#getProfileLog()
- */
- public String getProfileLog();
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/Equinox.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/Equinox.java
deleted file mode 100644
index d24ff52a2..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/Equinox.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.launch;
-
-import java.io.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.net.*;
-import java.security.*;
-import java.security.cert.X509Certificate;
-import java.util.*;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.util.Headers;
-import org.eclipse.osgi.internal.baseadaptor.DevClassPathHelper;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.*;
-import org.osgi.framework.launch.Framework;
-
-/**
- * The System Bundle implementation for the Equinox Framework.
- *
- * @since 3.5
- */
-public class Equinox implements Framework {
- private static final String implName = "org.eclipse.osgi.framework.internal.core.EquinoxLauncher"; //$NON-NLS-1$
- /**@GuardedBy this*/
- private Framework impl;
- private final boolean useSeparateCL;
- private final Map<String, Object> configuration;
-
- public Equinox(Map<String, ?> configuration) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new AllPermission());
- useSeparateCL = FrameworkProperties.inUse();
- @SuppressWarnings("unchecked")
- final Map<String, Object> empty = Collections.EMPTY_MAP;
- this.configuration = configuration == null ? empty : new HashMap<String, Object>(configuration);
- }
-
- private Framework createImpl() {
- if (System.getSecurityManager() == null)
- return createImpl0();
- return AccessController.doPrivileged(new PrivilegedAction<Framework>() {
- public Framework run() {
- return createImpl0();
- }
- });
- }
-
- Framework createImpl0() {
- try {
- Class<?> implClazz = getImplClass();
- Constructor<?> constructor = implClazz.getConstructor(new Class[] {Map.class});
- return (Framework) constructor.newInstance(new Object[] {configuration});
- } catch (ClassNotFoundException e) {
- throw new NoClassDefFoundError(implName);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e.getMessage(), e);
- } catch (NoSuchMethodException e) {
- throw new NoSuchMethodError(e.getMessage());
- } catch (InstantiationException e) {
- throw new RuntimeException(e.getMessage(), e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-
- private Class<?> getImplClass() throws ClassNotFoundException {
- ClassLoader thisCL = this.getClass().getClassLoader();
- if (!(useSeparateCL && (thisCL instanceof URLClassLoader)))
- return Class.forName(implName);
- URL[] cp = getFrameworkURLs((URLClassLoader) thisCL);
- EquinoxFWClassLoader fwCL = new EquinoxFWClassLoader(cp, thisCL);
- return fwCL.loadClass(implName);
- }
-
- private URL[] getFrameworkURLs(URLClassLoader frameworkLoader) {
- // use the classpath of the framework class loader
- URL[] cp = frameworkLoader.getURLs();
- List<URL> result = new ArrayList<URL>(cp.length);
- for (int i = 0; i < cp.length; i++) {
- // need to add only the urls for the framework and any framework fragments
- InputStream manifest = null;
- try {
- if (cp[i].getFile().endsWith("/")) { //$NON-NLS-1$
- manifest = new URL(cp[i], org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST).openStream();
- } else {
- manifest = new URL("jar:" + cp[i].toExternalForm() + "!/" + org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST).openStream(); //$NON-NLS-1$ //$NON-NLS-2$
- }
- Map<String, String> headers = ManifestElement.parseBundleManifest(manifest, new Headers<String, String>(10));
- String bsnSpec = getValue(headers, Constants.BUNDLE_SYMBOLICNAME);
- if (bsnSpec == null)
- continue;
- String internalBSN = org.eclipse.osgi.framework.internal.core.Constants.getInternalSymbolicName();
- if (internalBSN.equals(bsnSpec)) {
- // this is the framework
- addDevClassPaths(cp[i], bsnSpec, result);
- result.add(cp[i]);
- } else {
- if (!isFrameworkFragment(headers, internalBSN))
- continue;
- // this is for a framework extension
- addDevClassPaths(cp[i], bsnSpec, result);
- result.add(cp[i]);
- }
- } catch (IOException e) {
- continue; // no manifest;
- } catch (BundleException e) {
- continue; // bad manifest;
- } finally {
- if (manifest != null)
- try {
- manifest.close();
- } catch (IOException e) {
- // ignore
- }
- }
- }
- return result.toArray(new URL[result.size()]);
- }
-
- private void addDevClassPaths(URL cp, String bsn, List<URL> result) {
- if (!cp.getPath().endsWith("/")) //$NON-NLS-1$
- return;
- String[] devPaths = DevClassPathHelper.getDevClassPath(bsn);
- if (devPaths == null)
- return;
- for (int i = 0; i < devPaths.length; i++)
- try {
- char lastChar = devPaths[i].charAt(devPaths[i].length() - 1);
- URL url;
- if ((devPaths[i].endsWith(".jar") || (lastChar == '/' || lastChar == '\\'))) //$NON-NLS-1$
- url = new URL(cp, devPaths[i]);
- else
- url = new URL(cp, devPaths[i] + "/"); //$NON-NLS-1$
- result.add(url);
- } catch (MalformedURLException e) {
- continue;
- }
- }
-
- private boolean isFrameworkFragment(Map<String, String> headers, String internalBSN) {
- String hostBSN = getValue(headers, Constants.FRAGMENT_HOST);
- return internalBSN.equals(hostBSN) || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(hostBSN);
- }
-
- private String getValue(Map<String, String> headers, String key) {
- String headerSpec = headers.get(key);
- if (headerSpec == null)
- return null;
- ManifestElement[] elements;
- try {
- elements = ManifestElement.parseHeader(key, headerSpec);
- } catch (BundleException e) {
- return null;
- }
- if (elements == null)
- return null;
- return elements[0].getValue();
- }
-
- private synchronized Framework getImpl() {
- if (impl == null)
- impl = createImpl();
- return impl;
- }
-
- public void init() throws BundleException {
- getImpl().init();
- }
-
- public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
- return getImpl().waitForStop(timeout);
- }
-
- public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
- return getImpl().findEntries(path, filePattern, recurse);
- }
-
- public BundleContext getBundleContext() {
- return getImpl().getBundleContext();
- }
-
- public long getBundleId() {
- return getImpl().getBundleId();
- }
-
- public URL getEntry(String path) {
- return getImpl().getEntry(path);
- }
-
- public Enumeration<String> getEntryPaths(String path) {
- return getImpl().getEntryPaths(path);
- }
-
- public Dictionary<String, String> getHeaders() {
- return getImpl().getHeaders();
- }
-
- public Dictionary<String, String> getHeaders(String locale) {
- return getImpl().getHeaders(locale);
- }
-
- public long getLastModified() {
- return getImpl().getLastModified();
- }
-
- public String getLocation() {
- return getImpl().getLocation();
- }
-
- public ServiceReference<?>[] getRegisteredServices() {
- return getImpl().getRegisteredServices();
- }
-
- public URL getResource(String name) {
- return getImpl().getResource(name);
- }
-
- public Enumeration<URL> getResources(String name) throws IOException {
- return getImpl().getResources(name);
- }
-
- public ServiceReference<?>[] getServicesInUse() {
- return getImpl().getServicesInUse();
- }
-
- public int getState() {
- return getImpl().getState();
- }
-
- public String getSymbolicName() {
- return getImpl().getSymbolicName();
- }
-
- public boolean hasPermission(Object permission) {
- return getImpl().hasPermission(permission);
- }
-
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- return getImpl().loadClass(name);
- }
-
- public void start(int options) throws BundleException {
- getImpl().start(options);
- }
-
- public void start() throws BundleException {
- getImpl().start();
- }
-
- public void stop(int options) throws BundleException {
- getImpl().stop(options);
- }
-
- public void stop() throws BundleException {
- getImpl().stop();
- }
-
- public void uninstall() throws BundleException {
- getImpl().uninstall();
- }
-
- public void update() throws BundleException {
- getImpl().update();
- }
-
- public void update(InputStream in) throws BundleException {
- getImpl().update(in);
- }
-
- public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
- return getImpl().getSignerCertificates(signersType);
- }
-
- public Version getVersion() {
- return getImpl().getVersion();
- }
-
- public <A> A adapt(Class<A> adapterType) {
- return getImpl().adapt(adapterType);
- }
-
- public int compareTo(Bundle o) {
- return getImpl().compareTo(o);
- }
-
- public File getDataFile(String filename) {
- return getImpl().getDataFile(filename);
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFWClassLoader.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFWClassLoader.java
deleted file mode 100644
index 7011b5b13..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/launch/EquinoxFWClassLoader.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.launch;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-
-class EquinoxFWClassLoader extends URLClassLoader {
-
- private static final String[] DELEGATE_PARENT_FIRST = {"java.", "org.osgi.", "org.eclipse.osgi.launch.", "org.eclipse.osgi.service.", "org.eclipse.osgi.framework.log", "org.eclipse.osgi.framework.adaptor", "org.eclipse.osgi.framework.internal.core.ReferenceInputStream"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
- private static final String[] DELEGATE_CHILD_FIRST = new String[0]; // nothing right now is skipped
-
- private final ClassLoader parent;
-
- public EquinoxFWClassLoader(URL[] urls, ClassLoader parent) {
- super(urls, parent);
- this.parent = parent;
- }
-
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- Class<?> clazz = findLoadedClass(name);
- if (clazz != null)
- return clazz;
-
- boolean childFirst = childFirst(name);
- ClassNotFoundException cnfe = null;
-
- if (childFirst)
- try {
- clazz = findClass(name);
- } catch (ClassNotFoundException e) {
- // continue
- cnfe = e;
- }
-
- if (clazz == null)
- try {
- clazz = parent.loadClass(name);
- } catch (ClassNotFoundException e) {
- // continue
- }
-
- if (clazz == null && cnfe != null)
- throw cnfe;
- if (clazz == null && !childFirst)
- clazz = findClass(name);
-
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
-
- private boolean childFirst(String name) {
- for (int i = DELEGATE_CHILD_FIRST.length - 1; i >= 0; i--)
- if (name.startsWith(DELEGATE_CHILD_FIRST[i]))
- return true;
- for (int i = DELEGATE_PARENT_FIRST.length - 1; i >= 0; i--)
- if (name.startsWith(DELEGATE_PARENT_FIRST[i]))
- return false;
- return true;
-
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java
deleted file mode 100644
index 0c2aebb92..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java
+++ /dev/null
@@ -1,699 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.*;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.hooks.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.baseadaptor.*;
-import org.eclipse.osgi.service.resolver.PlatformAdmin;
-import org.eclipse.osgi.service.resolver.State;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-import org.osgi.framework.wiring.BundleWiring;
-
-/**
- * A Framework adaptor implementation that allows additional functionality to be
- * hooked in. Hooks are configured using {@link HookConfigurator}
- * objects. A framework extension may add hook configurators which can be used
- * to add hooks to the {@link HookRegistry}.
- * @see HookConfigurator
- * @see HookRegistry
- * @see AdaptorHook
- * @since 3.2
- */
-public class BaseAdaptor implements FrameworkAdaptor {
- // System property used to set the parent classloader type (boot is the default)
- private static final String PROP_PARENT_CLASSLOADER = "osgi.parentClassloader"; //$NON-NLS-1$
- // A parent classloader type that specifies the application classloader
- private static final String PARENT_CLASSLOADER_APP = "app"; //$NON-NLS-1$
- // A parent classloader type that specifies the extension classlaoder
- private static final String PARENT_CLASSLOADER_EXT = "ext"; //$NON-NLS-1$
- // A parent classloader type that specifies the boot classlaoder
- private static final String PARENT_CLASSLOADER_BOOT = "boot"; //$NON-NLS-1$
- // A parent classloader type that specifies the framework classlaoder
- private static final String PARENT_CLASSLOADER_FWK = "fwk"; //$NON-NLS-1$
- // The BundleClassLoader parent to use when creating BundleClassLoaders.
- private static ClassLoader bundleClassLoaderParent;
- static {
- // check property for specified parent
- // check the osgi defined property first
- String type = FrameworkProperties.getProperty(Constants.FRAMEWORK_BUNDLE_PARENT);
- if (type != null) {
- if (Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK.equals(type))
- type = PARENT_CLASSLOADER_FWK;
- } else {
- type = FrameworkProperties.getProperty(BaseAdaptor.PROP_PARENT_CLASSLOADER, BaseAdaptor.PARENT_CLASSLOADER_BOOT);
- }
-
- if (BaseAdaptor.PARENT_CLASSLOADER_FWK.equalsIgnoreCase(type))
- bundleClassLoaderParent = FrameworkAdaptor.class.getClassLoader();
- else if (BaseAdaptor.PARENT_CLASSLOADER_APP.equalsIgnoreCase(type))
- bundleClassLoaderParent = ClassLoader.getSystemClassLoader();
- else if (BaseAdaptor.PARENT_CLASSLOADER_EXT.equalsIgnoreCase(type)) {
- ClassLoader appCL = ClassLoader.getSystemClassLoader();
- if (appCL != null)
- bundleClassLoaderParent = appCL.getParent();
- }
- // default to boot classloader
- if (bundleClassLoaderParent == null)
- bundleClassLoaderParent = new ClassLoader(Object.class.getClassLoader()) {/* boot class loader*/};
- }
-
- private Framework eventPublisher;
- private boolean stopping;
- private HookRegistry hookRegistry;
- private FrameworkLog log;
- private BundleContext context;
- private BaseStorage storage;
- private BundleWatcher bundleWatcher;
-
- /**
- * Constructs a BaseAdaptor.
- * @param args arguments passed to the adaptor by the framework.
- */
- public BaseAdaptor(String[] args) {
- if (LocationManager.getConfigurationLocation() == null)
- LocationManager.initializeLocations();
- hookRegistry = new HookRegistry(this);
- FrameworkLogEntry[] errors = hookRegistry.initialize();
- if (errors.length > 0)
- for (int i = 0; i < errors.length; i++)
- getFrameworkLog().log(errors[i]);
- // get the storage after the registry has been initialized
- storage = getStorage();
- // TODO consider passing args to BaseAdaptorHooks
- }
-
- /**
- * This method will call all configured adaptor hooks {@link AdaptorHook#initialize(BaseAdaptor)} method.
- * @see FrameworkAdaptor#initialize(EventPublisher)
- */
- public void initialize(EventPublisher publisher) {
- this.eventPublisher = (Framework) publisher;
- // set the adaptor for the adaptor hooks
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++)
- adaptorHooks[i].initialize(this);
- }
-
- /**
- * @see FrameworkAdaptor#initializeStorage()
- */
- public void initializeStorage() throws IOException {
- storage.initialize(this);
- }
-
- /**
- * @throws IOException
- * @see FrameworkAdaptor#compactStorage()
- */
- public void compactStorage() throws IOException {
- storage.compact();
- }
-
- /**
- * This method will call all the configured adaptor hook {@link AdaptorHook#addProperties(Properties)} methods.
- * @see FrameworkAdaptor#getProperties()
- */
- public Properties getProperties() {
- Properties props = new Properties();
- String resource = FrameworkProperties.getProperty(Constants.OSGI_PROPERTIES, Constants.DEFAULT_OSGI_PROPERTIES);
- try {
- InputStream in = null;
- File file = new File(resource);
- if (file.exists())
- in = new FileInputStream(file);
- if (in == null)
- in = getClass().getResourceAsStream(resource);
- if (in != null) {
- try {
- props.load(new BufferedInputStream(in));
- } finally {
- try {
- in.close();
- } catch (IOException ee) {
- // nothing to do
- }
- }
- } else {
- if (Debug.DEBUG_GENERAL)
- Debug.println("Skipping osgi.properties: " + resource); //$NON-NLS-1$
- }
- } catch (IOException e) {
- if (Debug.DEBUG_GENERAL)
- Debug.println("Unable to load osgi.properties: " + e.getMessage()); //$NON-NLS-1$
- }
- // add the storage properties
- storage.addProperties(props);
- // add the properties from each adaptor hook
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++)
- adaptorHooks[i].addProperties(props);
- return props;
- }
-
- /**
- * @see FrameworkAdaptor#getInstalledBundles()
- */
- public BundleData[] getInstalledBundles() {
- return storage.getInstalledBundles();
- }
-
- /**
- * This method will call each configured adaptor hook {@link AdaptorHook#mapLocationToURLConnection(String)} method
- * until one returns a non-null value. If none of the adaptor hooks return a non-null value then the
- * string is used to construct a new URL object to open a new url connection.
- *
- * @see FrameworkAdaptor#mapLocationToURLConnection(String)
- */
- public URLConnection mapLocationToURLConnection(String location) throws BundleException {
- try {
- URLConnection result = null;
- // try the adaptor hooks first;
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++) {
- result = adaptorHooks[i].mapLocationToURLConnection(location);
- if (result != null)
- return result;
- }
- // just do the default
- return (new URL(location).openConnection());
- } catch (IOException e) {
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, location), e);
- }
- }
-
- /**
- * @see FrameworkAdaptor#installBundle(String, URLConnection)
- */
- public BundleOperation installBundle(String location, URLConnection source) {
- return storage.installBundle(location, source);
- }
-
- /**
- * @see FrameworkAdaptor#updateBundle(BundleData, URLConnection)
- */
- public BundleOperation updateBundle(BundleData bundledata, URLConnection source) {
- return storage.updateBundle((BaseData) bundledata, source);
- }
-
- /**
- * @see FrameworkAdaptor#uninstallBundle(BundleData)
- */
- public BundleOperation uninstallBundle(BundleData bundledata) {
- return storage.uninstallBundle((BaseData) bundledata);
- }
-
- /**
- * @see FrameworkAdaptor#getTotalFreeSpace()
- */
- public long getTotalFreeSpace() throws IOException {
- return storage.getFreeSpace();
- }
-
- /**
- * @throws IOException
- * @see FrameworkAdaptor#getPermissionStorage()
- */
- public PermissionStorage getPermissionStorage() throws IOException {
- return storage.getPermissionStorage();
- }
-
- /**
- * This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStart(BundleContext)} methods.
- * @see FrameworkAdaptor#frameworkStart(BundleContext)
- */
- public void frameworkStart(BundleContext fwContext) throws BundleException {
- this.context = fwContext;
- stopping = false;
- // always start the storage first
- storage.frameworkStart(fwContext);
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++)
- adaptorHooks[i].frameworkStart(fwContext);
- }
-
- /**
- * This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStop(BundleContext)} methods.
- * @see FrameworkAdaptor#frameworkStop(BundleContext)
- */
- public void frameworkStop(BundleContext fwContext) throws BundleException {
- // first inform all configured adaptor hooks
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++)
- adaptorHooks[i].frameworkStop(fwContext);
- // stop the storage last
- storage.frameworkStop(fwContext);
- }
-
- /**
- * This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStopping(BundleContext)} methods.
- * @see FrameworkAdaptor#frameworkStopping(BundleContext)
- */
- public void frameworkStopping(BundleContext fwContext) {
- stopping = true;
- // always tell storage of stopping first
- storage.frameworkStopping(fwContext);
- // inform all configured adaptor hooks last
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++)
- adaptorHooks[i].frameworkStopping(fwContext);
- }
-
- /**
- * @see FrameworkAdaptor#getInitialBundleStartLevel()
- */
- public int getInitialBundleStartLevel() {
- return storage.getInitialBundleStartLevel();
- }
-
- /**
- * @see FrameworkAdaptor#setInitialBundleStartLevel(int)
- */
- public void setInitialBundleStartLevel(int value) {
- storage.setInitialBundleStartLevel(value);
- }
-
- /**
- * This method calls all configured adaptor hook {@link AdaptorHook#createFrameworkLog()} methods
- * until the first one returns a non-null value. If none of the adaptor hooks return a non-null
- * value then a framework log implementation which does nothing is returned.
- * @see FrameworkAdaptor#getFrameworkLog()
- */
- public FrameworkLog getFrameworkLog() {
- if (log != null)
- return log;
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++) {
- log = adaptorHooks[i].createFrameworkLog();
- if (log != null)
- return log;
- }
- log = new FrameworkLog() {
- public void log(FrameworkEvent frameworkEvent) {
- log(new FrameworkLogEntry(frameworkEvent.getBundle().getSymbolicName() == null ? frameworkEvent.getBundle().getLocation() : frameworkEvent.getBundle().getSymbolicName(), FrameworkLogEntry.ERROR, 0, "FrameworkEvent.ERROR", 0, frameworkEvent.getThrowable(), null)); //$NON-NLS-1$
- }
-
- public void log(FrameworkLogEntry logEntry) {
- System.err.print(logEntry.getEntry() + " "); //$NON-NLS-1$
- System.err.println(logEntry.getMessage());
- if (logEntry.getThrowable() != null)
- logEntry.getThrowable().printStackTrace(System.err);
- }
-
- public void setWriter(Writer newWriter, boolean append) {
- // do nothing
- }
-
- /**
- * @throws IOException
- */
- public void setFile(File newFile, boolean append) throws IOException {
- // do nothing
- }
-
- public File getFile() {
- // do nothing
- return null;
- }
-
- public void setConsoleLog(boolean consoleLog) {
- // do nothing
- }
-
- public void close() {
- // do nothing
- }
- };
- return log;
- }
-
- /**
- * @see FrameworkAdaptor#createSystemBundleData()
- */
- public BundleData createSystemBundleData() throws BundleException {
- return new SystemBundleData(this);
- }
-
- /**
- * @see FrameworkAdaptor#getBundleWatcher()
- */
- public BundleWatcher getBundleWatcher() {
- if (bundleWatcher != null)
- return bundleWatcher;
- final BundleWatcher[] watchers = hookRegistry.getWatchers();
- if (watchers.length == 0)
- return null;
- bundleWatcher = new BundleWatcher() {
- public void watchBundle(Bundle bundle, int type) {
- for (int i = 0; i < watchers.length; i++)
- watchers[i].watchBundle(bundle, type);
- }
- };
- return bundleWatcher;
- }
-
- /**
- * @see FrameworkAdaptor#getPlatformAdmin()
- */
- public PlatformAdmin getPlatformAdmin() {
- return storage.getStateManager();
- }
-
- /**
- * @see FrameworkAdaptor#getState()
- */
- public State getState() {
- return storage.getStateManager().getSystemState();
- }
-
- /**
- * This method calls all the configured classloading hooks {@link ClassLoadingHook#getBundleClassLoaderParent()} methods
- * until one returns a non-null value.
- * @see FrameworkAdaptor#getBundleClassLoaderParent()
- */
- public ClassLoader getBundleClassLoaderParent() {
- // ask the configured adaptor hooks first
- ClassLoader result = null;
- ClassLoadingHook[] cpManagerHooks = getHookRegistry().getClassLoadingHooks();
- for (int i = 0; i < cpManagerHooks.length; i++) {
- result = cpManagerHooks[i].getBundleClassLoaderParent();
- if (result != null)
- return result;
- }
- // none of the configured adaptor hooks gave use a parent loader; use the default
- return bundleClassLoaderParent;
- }
-
- /**
- * This method calls all the configured adaptor hooks {@link AdaptorHook#handleRuntimeError(Throwable)} methods.
- * @see FrameworkAdaptor#handleRuntimeError(Throwable)
- */
- public void handleRuntimeError(Throwable error) {
- AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
- for (int i = 0; i < adaptorHooks.length; i++)
- adaptorHooks[i].handleRuntimeError(error);
- }
-
- /**
- * Returns true if the {@link #frameworkStopping(BundleContext)} method has been called
- * @return true if the framework is stopping
- */
- public boolean isStopping() {
- return stopping;
- }
-
- /**
- * Returns the event publisher for this BaseAdaptor
- * @return the event publisher for this BaseAdaptor
- */
- public EventPublisher getEventPublisher() {
- return eventPublisher;
- }
-
- /**
- * Returns the <code>HookRegistry</code> object for this adaptor.
- * @return the <code>HookRegistry</code> object for this adaptor.
- */
- public HookRegistry getHookRegistry() {
- return hookRegistry;
- }
-
- /**
- * Returns the system bundle's context
- * @return the system bundle's context
- */
- public BundleContext getContext() {
- return context;
- }
-
- /**
- * Returns the bundle with the specified identifier. This method
- * does not invoke and bundle find hooks and therefore does not
- * allow bundle find hooks to hide a bundle from the caller.
- *
- * @param id The identifier of the bundle to retrieve.
- * @return A {@code Bundle} object or {@code null} if the identifier does
- * not match any installed bundle.
- */
- public Bundle getBundle(long id) {
- return eventPublisher.getBundle(id);
- }
-
- /**
- * Creates a bundle file object for the given content and base data.
- * This method must delegate to each configured bundle file factory
- * {@link BundleFileFactoryHook#createBundleFile(Object, BaseData, boolean)} method until one
- * factory returns a non-null value. If no bundle file factory returns a non-null value
- * then the the default behavior will be performed.
- * <p>
- * If the specified content is <code>null</code> then the base content of the specified
- * bundledata must be found before calling any bundle file factories.
- * </p>
- * <p>
- * After the bundle file has been created each configured bundle file wrapper factory
- * {@link BundleFileWrapperFactoryHook#wrapBundleFile(BundleFile, Object, BaseData, boolean)}
- * method is called to wrap the bundle file.
- * </p>
- * @param content The object which contains the content of a bundle file. A value of
- * <code>null</code> indicates that the storage must find the base content for the
- * specified BaseData.
- * @param data The BaseData associated with the content
- * @return a BundleFile object.
- * @throws IOException if an error occured while creating the BundleFile
- */
- public BundleFile createBundleFile(Object content, BaseData data) throws IOException {
- return storage.createBundleFile(content, data);
- }
-
- /**
- * Returns true if the persistent storage is read-only
- * @return true if the persistent storage is read-only
- */
- public boolean isReadOnly() {
- return storage.isReadOnly();
- }
-
- /*
- * This is an experimental method to allow adaptors to replace the storage implementation by
- * extending BaseAdaptor and overriding this method. This method is experimental.
- * @return a base storage object.
- */
- protected BaseStorage getStorage() {
- if (storage != null)
- return storage;
- // this bit of code assumes the registry is initialized with a BaseStorageHook
- // we want to make sure we are using the same BaseStorage instance as the BaseStorageHook
- StorageHook[] hooks = hookRegistry.getStorageHooks();
- for (int i = 0; i < hooks.length && storage == null; i++)
- if (hooks[i] instanceof BaseStorageHook)
- storage = ((BaseStorageHook) hooks[i]).getStorage();
- return storage;
- }
-
- /**
- * @see FrameworkAdaptor#findEntries(List, String, String, int)
- */
- public Enumeration<URL> findEntries(List<BundleData> datas, String path, String filePattern, int options) {
- List<BundleFile> bundleFiles = new ArrayList<BundleFile>(datas.size());
- for (BundleData data : datas)
- bundleFiles.add(((BaseData) data).getBundleFile());
- // search all the bundle files
- List<String> pathList = listEntryPaths(bundleFiles, path, filePattern, options);
- // return null if no entries found
- if (pathList.size() == 0)
- return null;
- // create an enumeration to enumerate the pathList
- final String[] pathArray = pathList.toArray(new String[pathList.size()]);
- final BundleData[] dataArray = datas.toArray(new BundleData[datas.size()]);
- return new Enumeration<URL>() {
- private int curPathIndex = 0;
- private int curDataIndex = 0;
- private URL nextElement = null;
-
- public boolean hasMoreElements() {
- if (nextElement != null)
- return true;
- getNextElement();
- return nextElement != null;
- }
-
- public URL nextElement() {
- if (!hasMoreElements())
- throw new NoSuchElementException();
- URL result = nextElement;
- // force the next element search
- getNextElement();
- return result;
- }
-
- private void getNextElement() {
- nextElement = null;
- if (curPathIndex >= pathArray.length)
- // reached the end of the pathArray; no more elements
- return;
- while (nextElement == null && curPathIndex < pathArray.length) {
- String curPath = pathArray[curPathIndex];
- // search the datas until we have searched them all
- while (nextElement == null && curDataIndex < dataArray.length)
- nextElement = dataArray[curDataIndex++].getEntry(curPath);
- // we have searched all datas then advance to the next path
- if (curDataIndex >= dataArray.length) {
- curPathIndex++;
- curDataIndex = 0;
- }
- }
- }
- };
- }
-
- /**
- * Returns the names of resources available from a list of bundle files.
- * No duplicate resource names are returned, each name is unique.
- * @param bundleFiles the list of bundle files to search in
- * @param path The path name in which to look.
- * @param filePattern The file name pattern for selecting resource names in
- * the specified path.
- * @param options The options for listing resource names.
- * @return a list of resource names. If no resources are found then
- * the empty list is returned.
- * @see BundleWiring#listResources(String, String, int)
- */
- public List<String> listEntryPaths(List<BundleFile> bundleFiles, String path, String filePattern, int options) {
- // a list used to store the results of the search
- List<String> pathList = new ArrayList<String>();
- Filter patternFilter = null;
- Hashtable<String, String> patternProps = null;
- if (filePattern != null) {
- // Optimization: If the file pattern does not include a wildcard or escape char then it must represent a single file.
- // Avoid pattern matching and use BundleFile.getEntry() if recursion was not requested.
- if ((options & BundleWiring.FINDENTRIES_RECURSE) == 0 && filePattern.indexOf('*') == -1 && filePattern.indexOf('\\') == -1) {
- if (path.length() == 0)
- path = filePattern;
- else
- path += path.charAt(path.length() - 1) == '/' ? filePattern : '/' + filePattern;
- for (BundleFile bundleFile : bundleFiles) {
- if (bundleFile.getEntry(path) != null && !pathList.contains(path))
- pathList.add(path);
- }
- return pathList;
- }
- // For when the file pattern includes a wildcard.
- try {
- // create a file pattern filter with 'filename' as the key
- patternFilter = FilterImpl.newInstance("(filename=" + sanitizeFilterInput(filePattern) + ")"); //$NON-NLS-1$ //$NON-NLS-2$
- // create a single hashtable to be shared during the recursive search
- patternProps = new Hashtable<String, String>(2);
- } catch (InvalidSyntaxException e) {
- // something unexpected happened; log error and return nothing
- Bundle b = context == null ? null : context.getBundle();
- eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, b, e);
- return pathList;
- }
- }
- // find the entry paths for the datas
- for (BundleFile bundleFile : bundleFiles) {
- listEntryPaths(bundleFile, path, patternFilter, patternProps, options, pathList);
- }
- return pathList;
- }
-
- private String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException {
- StringBuffer buffer = null;
- boolean foundEscape = false;
- for (int i = 0; i < filePattern.length(); i++) {
- char c = filePattern.charAt(i);
- switch (c) {
- case '\\' :
- // we either used the escape found or found a new escape.
- foundEscape = foundEscape ? false : true;
- if (buffer != null)
- buffer.append(c);
- break;
- case '(' :
- case ')' :
- if (!foundEscape) {
- if (buffer == null) {
- buffer = new StringBuffer(filePattern.length() + 16);
- buffer.append(filePattern.substring(0, i));
- }
- // must escape with '\'
- buffer.append('\\');
- } else {
- foundEscape = false; // used the escape found
- }
- if (buffer != null)
- buffer.append(c);
- break;
- default :
- // if we found an escape it has been used
- foundEscape = false;
- if (buffer != null)
- buffer.append(c);
- break;
- }
- }
- if (foundEscape)
- throw new InvalidSyntaxException("Trailing escape characters must be escaped.", filePattern); //$NON-NLS-1$
- return buffer == null ? filePattern : buffer.toString();
- }
-
- private List<String> listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable<String, String> patternProps, int options, List<String> pathList) {
- if (pathList == null)
- pathList = new ArrayList<String>();
- Enumeration<String> entryPaths = bundleFile.getEntryPaths(path);
- if (entryPaths == null)
- return pathList;
- while (entryPaths.hasMoreElements()) {
- String entry = entryPaths.nextElement();
- int lastSlash = entry.lastIndexOf('/');
- if (patternProps != null) {
- int secondToLastSlash = entry.lastIndexOf('/', lastSlash - 1);
- int fileStart;
- int fileEnd = entry.length();
- if (lastSlash < 0)
- fileStart = 0;
- else if (lastSlash != entry.length() - 1)
- fileStart = lastSlash + 1;
- else {
- fileEnd = lastSlash; // leave the lastSlash out
- if (secondToLastSlash < 0)
- fileStart = 0;
- else
- fileStart = secondToLastSlash + 1;
- }
- String fileName = entry.substring(fileStart, fileEnd);
- // set the filename to the current entry
- patternProps.put("filename", fileName); //$NON-NLS-1$
- }
- // prevent duplicates and match on the patternFilter
- if (!pathList.contains(entry) && (patternFilter == null || patternFilter.matchCase(patternProps)))
- pathList.add(entry);
- // recurse only into entries that are directories
- if (((options & BundleWiring.FINDENTRIES_RECURSE) != 0) && !entry.equals(path) && entry.length() > 0 && lastSlash == (entry.length() - 1))
- listEntryPaths(bundleFile, entry, patternFilter, patternProps, options, pathList);
- }
- return pathList;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseData.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseData.java
deleted file mode 100644
index d7a910be6..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseData.java
+++ /dev/null
@@ -1,530 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.protocol.bundleentry.Handler;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.baseadaptor.ArrayMap;
-import org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.*;
-
-/**
- * The BundleData implementation used by the BaseAdaptor.
- * @see BaseAdaptor
- * @see BundleData
- * @see StorageHook
- * @see ClassLoadingHook
- * @since 3.2
- */
-public class BaseData implements BundleData {
- private final static boolean COPY_NATIVES = Boolean.valueOf(FrameworkProperties.getProperty("osgi.classloader.copy.natives")).booleanValue(); //$NON-NLS-1$
- private long id;
- private BaseAdaptor adaptor;
- private Bundle bundle;
- private int startLevel = -1;
- private int status = 0;
- private StorageHook[] storageHooks;
- private String location;
- private long lastModified;
- protected BundleFile bundleFile;
- private ArrayMap<Object, BundleFile> bundleFiles;
- private boolean dirty = false;
- protected Dictionary<String, String> manifest;
- // This field is only used by PDE source lookup, and is set by a hook (bug 126517). It serves no purpose at runtime.
- protected String fileName;
- // This is only used to keep track of when the same native library is loaded more than once
- protected Collection<String> loadedNativeCode;
-
- ///////////////////// Begin values from Manifest /////////////////////
- private String symbolicName;
- private Version version;
- private String activator;
- private String classpath;
- private String executionEnvironment;
- private String dynamicImports;
- private int type;
-
- ///////////////////// End values from Manifest /////////////////////
-
- /**
- * Constructs a new BaseData with the specified id for the specified adaptor
- * @param id the id of the BaseData
- * @param adaptor the adaptor of the BaseData
- */
- public BaseData(long id, BaseAdaptor adaptor) {
- this.id = id;
- this.adaptor = adaptor;
- }
-
- /**
- * This method calls all the configured class loading hooks {@link ClassLoadingHook#createClassLoader(ClassLoader, ClassLoaderDelegate, BundleProtectionDomain, BaseData, String[])}
- * methods until on returns a non-null value. If none of the class loading hooks returns a non-null value
- * then the default classloader implementation is used.
- * @see BundleData#createClassLoader(ClassLoaderDelegate, BundleProtectionDomain, String[])
- */
- public BundleClassLoader createClassLoader(ClassLoaderDelegate delegate, BundleProtectionDomain domain, String[] bundleclasspath) {
- ClassLoadingHook[] hooks = adaptor.getHookRegistry().getClassLoadingHooks();
- ClassLoader parent = adaptor.getBundleClassLoaderParent();
- BaseClassLoader cl = null;
- for (int i = 0; i < hooks.length && cl == null; i++)
- cl = hooks[i].createClassLoader(parent, delegate, domain, this, bundleclasspath);
- if (cl == null)
- cl = new DefaultClassLoader(parent, delegate, domain, this, bundleclasspath);
- return cl;
- }
-
- public final URL getEntry(final String path) {
- if (System.getSecurityManager() == null)
- return getEntry0(path);
- return AccessController.doPrivileged(new PrivilegedAction<URL>() {
- public URL run() {
- return getEntry0(path);
- }
- });
- }
-
- final URL getEntry0(String path) {
- BundleEntry entry = getBundleFile().getEntry(path);
- if (entry == null)
- return null;
- path = BundleFile.fixTrailingSlash(path, entry);
- try {
- //use the constant string for the protocol to prevent duplication
- return new URL(Constants.OSGI_ENTRY_URL_PROTOCOL, Long.toString(id) + BundleResourceHandler.BID_FWKID_SEPARATOR + Integer.toString(adaptor.hashCode()), 0, path, new Handler(entry, adaptor));
- } catch (MalformedURLException e) {
- return null;
- }
- }
-
- public final Enumeration<String> getEntryPaths(String path) {
- return getBundleFile().getEntryPaths(path);
- }
-
- /**
- * This method calls each configured classloading hook {@link ClassLoadingHook#findLibrary(BaseData, String)} method
- * until the first one returns a non-null value.
- * @see BundleData#findLibrary(String)
- */
- public String findLibrary(String libname) {
- ClassLoadingHook[] hooks = adaptor.getHookRegistry().getClassLoadingHooks();
- String result = null;
- for (int i = 0; i < hooks.length; i++) {
- result = hooks[i].findLibrary(this, libname);
- if (result != null)
- break;
- }
- // check to see if this library has been loaded by another class loader
- if (result != null)
- synchronized (this) {
- if (loadedNativeCode == null)
- loadedNativeCode = new ArrayList<String>(1);
- if (loadedNativeCode.contains(result) || COPY_NATIVES) {
- // we must copy the library to a temp space to allow another class loader to load the library
- String temp = copyToTempLibrary(result);
- if (temp != null)
- result = temp;
- } else {
- loadedNativeCode.add(result);
- }
- }
- return result;
- }
-
- private String copyToTempLibrary(String result) {
- try {
- return adaptor.getStorage().copyToTempLibrary(this, result);
- } catch (IOException e) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
- }
- return null;
- }
-
- public void installNativeCode(String[] nativepaths) throws BundleException {
- adaptor.getStorage().installNativeCode(this, nativepaths);
- }
-
- public File getDataFile(String path) {
- return adaptor.getStorage().getDataFile(this, path);
- }
-
- public Dictionary<String, String> getManifest() throws BundleException {
- if (manifest == null)
- manifest = adaptor.getStorage().loadManifest(this);
- return manifest;
- }
-
- public long getBundleID() {
- return id;
- }
-
- public final String getLocation() {
- return location;
- }
-
- /**
- * Sets the location of this bundledata
- * @param location the location of this bundledata
- */
- public final void setLocation(String location) {
- this.location = location;
- }
-
- public final long getLastModified() {
- return lastModified;
- }
-
- /**
- * Sets the last modified time stamp of this bundledata
- * @param lastModified the last modified time stamp of this bundledata
- */
- public final void setLastModified(long lastModified) {
- this.lastModified = lastModified;
- }
-
- public synchronized void close() throws IOException {
- if (bundleFile != null)
- getBundleFile().close(); // only close the bundleFile if it already exists.
- if (bundleFiles != null) {
- for (BundleFile bundlefile : bundleFiles.getValues())
- bundlefile.close();
- bundleFiles.clear();
- }
- }
-
- public void open() throws IOException {
- getBundleFile().open();
- }
-
- public final void setBundle(Bundle bundle) {
- this.bundle = bundle;
- }
-
- /**
- * Returns the bundle object of this BaseData
- * @return the bundle object of this BaseData
- */
- public final Bundle getBundle() {
- return bundle;
- }
-
- public int getStartLevel() {
- return startLevel;
- }
-
- public int getStatus() {
- return status;
- }
-
- /**
- * This method calls each configured storage hook {@link StorageHook#forgetStartLevelChange(int)} method.
- * If one returns true then this bundledata is not marked dirty.
- * @see BundleData#setStartLevel(int)
- */
- public void setStartLevel(int value) {
- startLevel = setPersistentData(value, true, startLevel);
- }
-
- /**
- * This method calls each configured storage hook {@link StorageHook#forgetStatusChange(int)} method.
- * If one returns true then this bundledata is not marked dirty.
- * @see BundleData#setStatus(int)
- */
- public void setStatus(int value) {
- status = setPersistentData(value, false, status);
- }
-
- private int setPersistentData(int value, boolean isStartLevel, int orig) {
- StorageHook[] hooks = getStorageHooks();
- for (int i = 0; i < hooks.length; i++)
- if (isStartLevel) {
- if (hooks[i].forgetStartLevelChange(value))
- return value;
- } else {
- if (hooks[i].forgetStatusChange(value))
- return value;
- }
- if (value != orig)
- dirty = true;
- return value;
- }
-
- /**
- * @throws IOException
- */
- public void save() throws IOException {
- adaptor.getStorage().save(this);
- }
-
- /**
- * Returns true if this bundledata is dirty
- * @return true if this bundledata is dirty
- */
- public boolean isDirty() {
- return dirty;
- }
-
- /**
- * Sets the dirty flag for this BaseData
- * @param dirty the dirty flag
- */
- public void setDirty(boolean dirty) {
- this.dirty = dirty;
- }
-
- public final String getSymbolicName() {
- return symbolicName;
- }
-
- /**
- * Sets the symbolic name of this BaseData
- * @param symbolicName the symbolic name
- */
- public final void setSymbolicName(String symbolicName) {
- this.symbolicName = symbolicName;
- }
-
- public final Version getVersion() {
- return version;
- }
-
- /**
- * Sets the version of this BaseData
- * @param version the version
- */
- public final void setVersion(Version version) {
- this.version = version;
- }
-
- public final int getType() {
- return type;
- }
-
- /**
- * Sets the type of this BaseData
- * @param type the type
- */
- public final void setType(int type) {
- this.type = type;
- }
-
- public final String[] getClassPath() throws BundleException {
- ManifestElement[] classpathElements = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, classpath);
- return getClassPath(classpathElements);
- }
-
- // TODO make classpath a String[] instead of saving a comma separated string.
- public String getClassPathString() {
- return classpath;
- }
-
- //TODO make classpath a String[] instead of saving a comma separated string.
- public void setClassPathString(String classpath) {
- this.classpath = classpath;
- }
-
- public final String getActivator() {
- return activator;
- }
-
- /**
- * Sets the activator of this BaseData
- * @param activator the activator
- */
- public final void setActivator(String activator) {
- this.activator = activator;
- }
-
- public final String getExecutionEnvironment() {
- return executionEnvironment;
- }
-
- /**
- * Sets the execution environment of this BaseData
- * @param executionEnvironment the execution environment
- */
- public void setExecutionEnvironment(String executionEnvironment) {
- this.executionEnvironment = executionEnvironment;
- }
-
- public final String getDynamicImports() {
- return dynamicImports;
- }
-
- /**
- * Sets the dynamic imports of this BaseData
- * @param dynamicImports the dynamic imports
- */
- public void setDynamicImports(String dynamicImports) {
- this.dynamicImports = dynamicImports;
- }
-
- /**
- * Returns the adaptor for this BaseData
- * @return the adaptor
- */
- public final BaseAdaptor getAdaptor() {
- return adaptor;
- }
-
- /**
- * Returns the BundleFile for this BaseData. The first time this method is called the
- * configured storage {@link BaseAdaptor#createBundleFile(Object, BaseData)} method is called.
- * @return the BundleFile
- * @throws IllegalArgumentException
- */
- public synchronized BundleFile getBundleFile() throws IllegalArgumentException {
- if (bundleFile == null)
- try {
- bundleFile = adaptor.createBundleFile(null, this);
- } catch (IOException e) {
- throw (IllegalArgumentException) new IllegalArgumentException(e.getMessage()).initCause(e);
- }
- return bundleFile;
- }
-
- public synchronized BundleFile getBundleFile(Object content, boolean base) {
- return base ? bundleFile : (bundleFiles == null) ? null : bundleFiles.get(content);
- }
-
- public synchronized void setBundleFile(Object content, BundleFile bundleFile) {
- if (bundleFiles == null)
- bundleFiles = new ArrayMap<Object, BundleFile>(1);
- bundleFiles.put(content, bundleFile);
- }
-
- private static String[] getClassPath(ManifestElement[] classpath) {
- if (classpath == null) {
- if (Debug.DEBUG_LOADER)
- Debug.println(" no classpath"); //$NON-NLS-1$
- /* create default BundleClassPath */
- return new String[] {"."}; //$NON-NLS-1$
- }
-
- List<String> result = new ArrayList<String>(classpath.length);
- for (int i = 0; i < classpath.length; i++) {
- if (Debug.DEBUG_LOADER)
- Debug.println(" found classpath entry " + classpath[i].getValueComponents()); //$NON-NLS-1$
- String[] paths = classpath[i].getValueComponents();
- for (int j = 0; j < paths.length; j++) {
- result.add(paths[j]);
- }
- }
-
- return result.toArray(new String[result.size()]);
- }
-
- /**
- * Returns the storage hook which is keyed by the specified key
- * @param key the key of the storage hook to get
- * @return the storage hook which is keyed by the specified key
- */
- public StorageHook getStorageHook(String key) {
- if (storageHooks == null)
- return null;
- for (int i = 0; i < storageHooks.length; i++)
- if (storageHooks[i].getKey().equals(key))
- return storageHooks[i];
- return null;
- }
-
- /**
- * Sets the instance storage hooks for this base data. This is method
- * may only be called once for the lifetime of the base data. Once set,
- * the list of storage hooks remains constant.
- * @param storageHooks the storage hook to add
- */
- public void setStorageHooks(StorageHook[] storageHooks) {
- if (this.storageHooks != null)
- return; // only allow this to be set once.
- this.storageHooks = storageHooks;
- }
-
- /**
- * Returns all the storage hooks associated with this BaseData
- * @return all the storage hooks associated with this BaseData
- */
- public StorageHook[] getStorageHooks() {
- return storageHooks == null ? new StorageHook[0] : storageHooks;
- }
-
- /**
- * Gets called by BundleFile during {@link BundleFile#getFile(String, boolean)}. This method
- * will allocate a File object where content of the specified path may be
- * stored for the current generation of the base data. The returned File object may
- * not exist if the content has not previously be stored.
- * @param path the path to the content to extract from the base data
- * @return a file object where content of the specified path may be stored.
- */
- public File getExtractFile(String path) {
- return adaptor.getStorage().getExtractFile(this, path);
- }
-
- /**
- * This is only used to support PDE source lookup. The field named &quot;fileName&quot;
- * must be set for PDE to access the absolute path string.
- * @param fileName an absolute path string to the base bundle file.
- */
- // This is only done for PDE source lookup (bug 126517)
- public void setFileName(String fileName) {
- this.fileName = fileName;
- }
-
- /**
- * Return a string representation of the bundle that can be used in debug messages.
- *
- * @return String representation of the bundle
- */
- public String toString() {
- String name = getSymbolicName();
- if (name == null)
- return getLocation();
- Version ver = getVersion();
- if (ver == null)
- return name;
- return name + "_" + ver; //$NON-NLS-1$
- }
-
- public Enumeration<URL> findLocalResources(String path) {
- String[] cp;
- try {
- cp = getClassPath();
- } catch (BundleException e) {
- cp = new String[0];
- }
- if (cp == null)
- cp = new String[0];
- // this is not optimized; degenerate case of someone calling getResource on an unresolved bundle!
- ClasspathManager cm = new ClasspathManager(this, cp, null);
- cm.initialize();
- Enumeration<URL> result = cm.findLocalResources(path);
- // no need to close ClassPathManager because the BundleFile objects are stored in the BaseData and closed on shutdown or uninstall
- return result;
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/AdaptorHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/AdaptorHook.java
deleted file mode 100644
index 6c7bcdedc..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/AdaptorHook.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.hooks;
-
-import java.io.IOException;
-import java.net.URLConnection;
-import java.util.Properties;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-import org.eclipse.osgi.framework.adaptor.EventPublisher;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-
-/**
- * An AdaptorHook hooks into the <code>BaseAdaptor</code> class.
- * @see BaseAdaptor
- * @see HookRegistry#getAdaptorHooks()
- * @see HookRegistry#addAdaptorHook(AdaptorHook)
- * @since 3.2
- */
-public interface AdaptorHook {
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#initialize(EventPublisher)}.
- * This method allows an adaptor hook to save the adaptor object for later.
- * @param adaptor the adaptor object associated with this AdaptorHook.
- */
- public void initialize(BaseAdaptor adaptor);
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#frameworkStart(BundleContext)}.
- * This method allows an adaptor hook to execute code when the framework is starting
- * (e.g. to register services).
- * @param context the system bundle context
- * @throws BundleException if an error occurs
- */
- public void frameworkStart(BundleContext context) throws BundleException;
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#frameworkStop(BundleContext)}.
- * This method allows an adaptor hook to execute code when the framework is stopped
- * (e.g. to unregister services).
- * @param context the system bundle context
- * @throws BundleException if an error occurs.
- */
- public void frameworkStop(BundleContext context) throws BundleException;
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#frameworkStopping(BundleContext)}.
- * This method allows an adaptor hook to execute code when the framework is about to start
- * the shutdown process.
- * @param context the system bundle context
- */
- public void frameworkStopping(BundleContext context);
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#getProperties()}.
- * This method allows an adaptor hook to add property values to the adaptor
- * properties object.
- * @param properties the adaptor properties object.
- */
- public void addProperties(Properties properties);
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#mapLocationToURLConnection(String)}.
- * The adaptor will call this method for each configured adaptor hook until one
- * adaptor hook returns a non-null value. If no adaptor hook returns a non-null value
- * then the adaptor will perform the default behavior.
- * @param location a bundle location string to be converted to a URLConnection
- * @return the URLConnection converted from the bundle location or null.
- * @throws IOException if an error occured creating the URLConnection
- */
- public URLConnection mapLocationToURLConnection(String location) throws IOException;
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#handleRuntimeError(Throwable)}.
- * The adaptor will call this method for each configured adaptor hook.
- * @param error the unexpected error that occured.
- */
- public void handleRuntimeError(Throwable error);
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#getFrameworkLog()}.
- * The adaptor will call this method for each configured adaptor hook until one
- * adaptor hook returns a non-null value. If no adaptor hook returns a non-null value
- * then the adaptor will return null.
- * @return a FrameworkLog object or null.
- */
- public FrameworkLog createFrameworkLog();
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileFactoryHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileFactoryHook.java
deleted file mode 100644
index 0317f1483..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/BundleFileFactoryHook.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.hooks;
-
-import java.io.IOException;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-
-/**
- * A factory that creates bundle file objects.
- * @see BaseAdaptor#createBundleFile(Object, BaseData)
- * @since 3.2
- */
-public interface BundleFileFactoryHook {
- /**
- * Creates a bundle file for the given content and base data.
- * @param content The object which contains the content of a bundle file.
- * @param data The base data associated with the content
- * @param base true if the content is for the base bundle (not an inner jar, directory etc.)
- * @return a new bundle file for the specified content, or null if this factory cannot
- * create a bundle file for the specified content.
- * @throws IOException if an IO error occurs
- */
- BundleFile createBundleFile(Object content, BaseData data, boolean base) throws IOException;
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingHook.java
deleted file mode 100644
index 59e36eac4..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingHook.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.hooks;
-
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.*;
-
-/**
- * A ClassLoadingHook hooks into the <code>ClasspathManager</code> class.
- * @see ClasspathManager
- * @see HookRegistry#getClassLoadingHooks()
- * @see HookRegistry#addClassLoadingHook(ClassLoadingHook)
- * @since 3.2
- */
-public interface ClassLoadingHook {
- /**
- * Gets called by a classpath manager before defining a class. This method allows a class loading hook
- * to process the bytes of a class that is about to be defined.
- * @param name the name of the class being defined
- * @param classbytes the bytes of the class being defined
- * @param classpathEntry the ClasspathEntry where the class bytes have been read from.
- * @param entry the BundleEntry source of the class bytes
- * @param manager the class path manager used to define the requested class
- * @return a modified array of classbytes or null if the original bytes should be used.
- */
- byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager);
-
- /**
- * Gets called by a classpath manager when looking for ClasspathEntry objects. This method allows
- * a classloading hook to add additional ClasspathEntry objects
- * @param cpEntries the list of ClasspathEntry objects currently available for the requested classpath
- * @param cp the name of the requested classpath
- * @param hostmanager the classpath manager the requested ClasspathEntry is for
- * @param sourcedata the source bundle data of the requested ClasspathEntry
- * @param sourcedomain the source domain of the requested ClasspathEntry
- * @return true if a ClasspathEntry has been added to cpEntries
- */
- boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain);
-
- /**
- * Gets called by a base data during {@link BundleData#findLibrary(String)}.
- * A base data will call this method for each configured class loading hook until one
- * class loading hook returns a non-null value. If no class loading hook returns
- * a non-null value then the base data will return null.
- * @param data the base data to find a native library for.
- * @param libName the name of the native library.
- * @return The absolute path name of the native library or null.
- */
- String findLibrary(BaseData data, String libName);
-
- /**
- * Gets called by the adaptor during {@link FrameworkAdaptor#getBundleClassLoaderParent()}.
- * The adaptor will call this method for each configured class loading hook until one
- * class loading hook returns a non-null value. If no class loading hook returns
- * a non-null value then the adaptor will perform the default behavior.
- * @return the parent classloader to be used by all bundle classloaders or null.
- */
- public ClassLoader getBundleClassLoaderParent();
-
- /**
- * Gets called by a base data during
- * {@link BundleData#createClassLoader(ClassLoaderDelegate, BundleProtectionDomain, String[])}.
- * The BaseData will call this method for each configured class loading hook until one data
- * hook returns a non-null value. If no class loading hook returns a non-null value then a
- * default implemenation of BundleClassLoader will be created.
- * @param parent the parent classloader for the BundleClassLoader
- * @param delegate the delegate for the bundle classloader
- * @param domain the domian for the bundle classloader
- * @param data the BundleData for the BundleClassLoader
- * @param bundleclasspath the classpath for the bundle classloader
- * @return a newly created bundle classloader
- */
- BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath);
-
- /**
- * Gets called by a classpath manager at the end of
- * {@link ClasspathManager#initialize()}.
- * The classpath manager will call this method for each configured class loading hook after it
- * has been initialized.
- * @param baseClassLoader the newly created bundle classloader
- * @param data the BundleData associated with the bundle classloader
- */
- void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data);
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingStatsHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingStatsHook.java
deleted file mode 100644
index 726b923bc..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/ClassLoadingStatsHook.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.hooks;
-
-import java.net.URL;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
-
-/**
- * A ClassLoadingStatsHook hooks into the <code>ClasspathManager</code> class. This class allows
- * a hook to record statistics about classloading.
- * @see ClasspathManager
- * @see HookRegistry#getClassLoadingStatsHooks()
- * @see HookRegistry#addClassLoadingStatsHook(ClassLoadingStatsHook)
- * @since 3.2
- */
-public interface ClassLoadingStatsHook {
- /**
- * Gets called by a classpath manager during {@link ClasspathManager#findLocalClass(String)} before
- * searching the local classloader for a class. A classpath manager will call this method for
- * each configured class loading stat hook.
- * @param name the name of the requested class
- * @param manager the classpath manager used to find and load the requested class
- * @throws ClassNotFoundException to prevent the requested class from loading
- */
- void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException;
-
- /**
- * Gets called by a classpath manager during {@link ClasspathManager#findLocalClass(String)} after
- * searching the local classloader for a class. A classpath manager will call this method for
- * each configured class loading stat hook.
- * @param name the name of the requested class
- * @param clazz the loaded class or null if not found
- * @param manager the classpath manager used to find and load the requested class
- */
- void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) throws ClassNotFoundException;
-
- /**
- * Gets called by a classpath manager during {@link ClasspathManager#findLocalResource(String)} before
- * searching the local classloader for a resource. A classpath manager will call this method for
- * each configured class loading stat hook.
- * @param name the name of the requested resource
- * @param manager the classpath manager used to find the requested resource
- */
- void preFindLocalResource(String name, ClasspathManager manager);
-
- /**
- * Gets called by a classpath manager during {@link ClasspathManager#findLocalResource(String)} after
- * searching the local classloader for a resource. A classpath manager will call this method for
- * each configured class loading stat hook.
- * @param name the name of the requested resource
- * @param resource the URL to the requested resource or null if not found
- * @param manager the classpath manager used to find the requested resource
- */
- void postFindLocalResource(String name, URL resource, ClasspathManager manager);
-
- /**
- * Gets called by a classpath manager after an attempt is made to define a class. This method allows
- * a class loading stat hook to record data about a class definition.
- * @param name the name of the class that got defined
- * @param clazz the class object that got defined or null if an error occurred while defining a class
- * @param classbytes the class bytes used to define the class
- * @param classpathEntry the ClasspathEntry where the class bytes got read from
- * @param entry the BundleEntyr source of the class bytes
- * @param manager the classpath manager used to define the class
- */
- void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager);
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/StorageHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/StorageHook.java
deleted file mode 100644
index 160f2c128..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/hooks/StorageHook.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.hooks;
-
-import java.io.*;
-import java.util.Dictionary;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.util.KeyedElement;
-import org.osgi.framework.BundleException;
-
-/**
- * A StorageHook hooks into the persistent storage loading and saving. A StorageHook gets
- * associated with each BaseData object installed in the adaptor.<p>
- * A StorageHook extends {@link KeyedElement}, the key used for the element must be the
- * fully qualified string name of the StorageHook implementation class.
- * @see BaseData#getStorageHook(String)
- * @since 3.2
- */
-public interface StorageHook extends KeyedElement {
- /**
- * Returns the storage version of this storage hook. This version
- * is used by the storage to check the consistency of cached persistent
- * data. Any time a storage hook changes the format of its persistent
- * data the storage version should be incremented.
- * @return the storage version of this storage hook
- */
- int getStorageVersion();
-
- /**
- * Creates an uninitialized storage hook for the specified bundledata. This method
- * is called when a bundle is installed or updated. The returned storage hook will be
- * used for the new contents of the bundle. The returned hook will have its
- * {@link #initialize(Dictionary)} method called to initialize the storage hook.
- * @param bundledata a base data the created storage hook will be associated with
- * @return an uninitialized storage hook
- * @throws BundleException if any error occurs
- */
- StorageHook create(BaseData bundledata) throws BundleException;
-
- /**
- * Initializes this storage hook with the content of the specified bundle manifest.
- * This method is called when a bundle is installed or updated.
- * @see #create(BaseData)
- * @see #copy(StorageHook)
- * @param manifest the bundle manifest to load into this storage hook
- * @throws BundleException if any error occurs
- */
- void initialize(Dictionary<String, String> manifest) throws BundleException;
-
- /**
- * Creates a new storage hook and loads the data from the specified
- * input stream into the storage hook. This method is called during startup to
- * load all the persistently installed bundles. <p>
- * It is important that this method and the {@link #save(DataOutputStream)} method
- * stay in sync. This method must be able to successfully read the data saved by the
- * {@link #save(DataOutputStream)} method.
- * @param bundledata a base data the loaded storage hook will be associated with
- * @param is an input stream used to load the storage hook's data from.
- * @return a loaded storage hook
- * @see #save(DataOutputStream)
- * @throws IOException if any error occurs
- */
- StorageHook load(BaseData bundledata, DataInputStream is) throws IOException;
-
- /**
- * Saves the data from this storage hook into the specified output stream. This method
- * is called if some persistent data has changed for the bundle. <p>
- * It is important that this method and the {@link #load(BaseData, DataInputStream)}
- * method stay in sync. This method must be able to save data which the
- * {@link #load(BaseData, DataInputStream)} method can ready successfully.
- * @see #load(BaseData, DataInputStream)
- * @param os an output stream used to save the storage hook's data from.
- * @throws IOException if any error occurs
- */
- void save(DataOutputStream os) throws IOException;
-
- /**
- * Copies the data from the specified storage hook into this storage hook. This method
- * is called when a bundle is updated to copy the data from the original bundle to a
- * new storage hook. Then this storage will be initialized with the new bundle's
- * manifest using the {@link #initialize(Dictionary)} method.
- * @see #create(BaseData)
- * @see #initialize(Dictionary)
- * @param storageHook the original storage hook to copy data out of.
- */
- void copy(StorageHook storageHook);
-
- /**
- * Validates the data in this storage hook, if the data is invalid then an illegal state
- * exception is thrown
- * @throws IllegalArgumentException if the data is invalid
- */
- void validate() throws IllegalArgumentException;
-
- /**
- * Returns the manifest for the data in this storage hook, or null if this hook does
- * not provide the manifest. Most hooks should return null from this method. This
- * method may be used to provide special handling of manifest loading. For example,
- * to provide a cached manfest or to do automatic manifest generation.
- * @param firstLoad true if this is the very first time this manifest is being loaded.
- * @return the manifest for the data in this storage hook, or null if this hook does
- * not provide the manifest
- * @throws BundleException
- */
- Dictionary<String, String> getManifest(boolean firstLoad) throws BundleException;
-
- /**
- * Gets called by a base data during {@link BundleData#setStatus(int)}.
- * A base data will call this method for each configured storage hook it
- * is associated with until one storage hook returns true. If all configured storage
- * hooks return false then the BaseData will be marked dirty and will cause the
- * status to be persistently saved.
- * @param status the new status of the base data
- * @return false if the status is not to be persistently saved; otherwise true is returned
- */
- boolean forgetStatusChange(int status);
-
- /**
- * Gets called by a base data during {@link BundleData#setStartLevel(int)}.
- * A base data will call this method for each configured storage hook it
- * is associated with until one storage hook returns true. If all configured storage
- * hooks return false then the BaseData will be marked dirty and will cause the
- * start level to be persistently saved.
- * @param startlevel the new startlevel of the base data
- * @return false if the startlevel is not to be persistently saved; otherwise true is returned
- */
- boolean forgetStartLevelChange(int startlevel);
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/BaseClassLoader.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/BaseClassLoader.java
deleted file mode 100644
index 5f727076a..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/BaseClassLoader.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.loader;
-
-import java.net.URL;
-import java.security.ProtectionDomain;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
-
-/**
- * The actual class loader object used to define classes for a classpath manager.
- * This interface provides public versions of a few methods on class loader.
- * @see ClasspathManager
- * @since 3.2
- */
-public interface BaseClassLoader extends BundleClassLoader {
- /**
- * Returns the domain for the host bundle of this class loader
- * @return the domain for the host bundle of this class loader
- */
- ProtectionDomain getDomain();
-
- /**
- * Creates a classpath entry with the given bundle file and domain
- * @param bundlefile the source bundle file for a classpath entry
- * @param cpDomain the source domain for a classpath entry
- * @return a classpath entry with the given bundle file and domain
- */
- ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain cpDomain);
-
- /**
- * Defines a Class.
- * @param name the name of the class to define
- * @param classbytes the bytes of the class to define
- * @param classpathEntry the classpath entry used to load the class bytes
- * @param entry the bundle entry used to load the class bytes
- * @return a defined Class
- */
- Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry);
-
- /**
- * A public version of the ClassLoader.findLoadedClass(java.lang.String) method.
- * @param classname the class name to find.
- * @return a loaded class
- */
- Class<?> publicFindLoaded(String classname);
-
- /**
- * A public version of the ClassLoader#getPackage(java.lang.String) method.
- * @param pkgname the package name to get.
- * @return the package or null if it does not exist
- */
- Object publicGetPackage(String pkgname);
-
- /**
- * A public version of the ClassLoader#definePackage(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.net.URL) method.
- * @return a defined Package
- */
- Object publicDefinePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase);
-
- /**
- * Returns the ClasspathManager for this BaseClassLoader
- * @return the ClasspathManager
- */
- ClasspathManager getClasspathManager();
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ParallelClassLoader.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ParallelClassLoader.java
deleted file mode 100644
index f55c2a1c0..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ParallelClassLoader.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.baseadaptor.loader;
-
-/**
- * A parallel class loader. Parallel class loaders are thread safe class loaders
- * which can handle multiple threads loading classes and resources from them at
- * the same time. This is important for OSGi class loaders because the
- * class loader delegate in OSGi is not strictly hierarchical, instead the
- * delegation is grid based and may have cycles.
- * <p>
- * The {@link ClasspathManager} handles parallel capable class loaders
- * differently from other class loaders. For parallel capable
- * class loaders when {@link ClasspathManager#findLocalClass(String)} is
- * called a lock will be obtained for the class name being searched while
- * calling {@link BaseClassLoader#publicFindLoaded(String)} and
- * {@link BaseClassLoader#defineClass(String, byte[], ClasspathEntry, org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry)}.
- * This prevents other threads from trying to searching for the same class at the
- * same time. For other class loaders the class loader lock is obtained
- * instead. This prevents other threads from trying to search for any
- * class while the lock is held.
- * </p>
- * <p>
- * <b>Note:</b> This interface is part of an interim API that is still under
- * development. It is being made available at this early stage to solicit feedback
- * from pioneering adopters on the understanding that any code that uses this API will may
- * be broken (repeatedly) as the API evolves.
- * </p>
- * @since 3.5
- */
-public interface ParallelClassLoader extends BaseClassLoader {
- /**
- * Indicates if this class loader is parallel capable. Even
- * if a class loader is able to be parallel capable there are some
- * restrictions imposed by the VM which may prevent a class loader
- * from being parallel capable. For example, some VMs may lock
- * the class loader natively before delegating to a class loader.
- * This type of locking will prevent a class loader from being
- * parallel capable.
- * @return true if this class loader is parallel capable; false otherwise.
- */
- boolean isParallelCapable();
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleresource/Handler.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleresource/Handler.java
deleted file mode 100644
index 4dd5c7c2e..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/protocol/bundleresource/Handler.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.protocol.bundleresource;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URL;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
-import org.eclipse.osgi.framework.internal.core.AbstractBundle;
-import org.eclipse.osgi.framework.internal.core.BundleResourceHandler;
-
-/**
- * URLStreamHandler the bundleresource protocol.
- */
-
-public class Handler extends BundleResourceHandler {
-
- /**
- * Constructor for a bundle protocol resource URLStreamHandler.
- */
- public Handler() {
- super();
- }
-
- public Handler(BundleEntry bundleEntry, BaseAdaptor adaptor) {
- super(bundleEntry, adaptor);
- }
-
- protected BundleEntry findBundleEntry(URL url, AbstractBundle bundle) throws IOException {
- BaseClassLoader classloader = getBundleClassLoader(bundle);
- if (classloader == null)
- throw new FileNotFoundException(url.getPath());
- ClasspathManager cpManager = classloader.getClasspathManager();
- BundleEntry entry = cpManager.findLocalEntry(url.getPath(), url.getPort());
- if (entry == null)
- // this isn't strictly needed but is kept to maintain compatibility
- entry = cpManager.findLocalEntry(url.getPath());
- if (entry == null)
- throw new FileNotFoundException(url.getPath());
- return entry;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseClassLoadingHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseClassLoadingHook.java
deleted file mode 100644
index f5ffe0b8f..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseClassLoadingHook.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.File;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.Constants;
-
-public class BaseClassLoadingHook implements ClassLoadingHook {
- private static final String[] LIB_EXTENSIONS;
- private static final String[] EMPTY_STRINGS = new String[0];
- static {
- String[] libExtensions = ManifestElement.getArrayFromList(FrameworkProperties.getProperty("osgi.framework.library.extensions", FrameworkProperties.getProperty(Constants.FRAMEWORK_LIBRARY_EXTENSIONS, getOSLibraryExtDefaults())), ","); //$NON-NLS-1$ //$NON-NLS-2$
- for (int i = 0; i < libExtensions.length; i++)
- if (libExtensions[i].length() > 0 && libExtensions[i].charAt(0) != '.')
- libExtensions[i] = '.' + libExtensions[i];
- LIB_EXTENSIONS = libExtensions;
- }
-
- private static String getOSLibraryExtDefaults() {
- // Some OSes have multiple library extensions
- // We should provide defaults to the known ones
- // For example Mac OS X uses dylib and jnilib (bug 380350)
- String os = FrameworkProperties.getProperty("os.name"); //$NON-NLS-1$
- return os == null || !os.startsWith("Mac OS") ? null : "dylib,jnilib"; //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /*
- * Maps an already mapped library name to additional library file extensions.
- * This is needed on platforms like AIX where .a and .so can be used as library file
- * extensions, but System.mapLibraryName only returns a single string.
- */
- public static String[] mapLibraryNames(String mappedLibName) {
- int extIndex = mappedLibName.lastIndexOf('.');
- if (LIB_EXTENSIONS.length == 0 || extIndex < 0)
- return EMPTY_STRINGS;
- String libNameBase = mappedLibName.substring(0, extIndex);
- String[] results = new String[LIB_EXTENSIONS.length];
- for (int i = 0; i < results.length; i++)
- results[i] = libNameBase + LIB_EXTENSIONS[i];
- return results;
- }
-
- public String findLibrary(BaseData data, String libName) {
- String mappedName = System.mapLibraryName(libName);
- String path = null;
- if (Debug.DEBUG_LOADER)
- Debug.println(" mapped library name: " + mappedName); //$NON-NLS-1$
- path = findNativePath(data, mappedName);
- if (path == null) {
- String[] mappedNames = mapLibraryNames(mappedName);
- for (int i = 0; i < mappedNames.length && path == null; i++)
- path = findNativePath(data, mappedNames[i]);
- }
- if (path == null) {
- if (Debug.DEBUG_LOADER)
- Debug.println(" library does not exist: " + mappedName); //$NON-NLS-1$
- path = findNativePath(data, libName);
- }
- if (Debug.DEBUG_LOADER)
- Debug.println(" returning library: " + path); //$NON-NLS-1$
- return path;
- }
-
- private String findNativePath(BaseData bundledata, String libname) {
- int slash = libname.lastIndexOf('/');
- if (slash >= 0)
- libname = libname.substring(slash + 1);
- String[] nativepaths = getNativePaths(bundledata);
- if (nativepaths == null)
- return null;
- for (int i = 0; i < nativepaths.length; i++) {
- slash = nativepaths[i].lastIndexOf('/');
- String path = slash < 0 ? nativepaths[i] : nativepaths[i].substring(slash + 1);
- if (path.equals(libname)) {
- if (nativepaths[i].startsWith(BaseStorageHook.EXTERNAL_LIB_PREFIX)) {
- // references an external library; do variable substitution
- String externalPath = BaseStorageHook.substituteVars(nativepaths[i].substring(BaseStorageHook.EXTERNAL_LIB_PREFIX.length()));
- File nativeFile = new File(externalPath);
- return nativeFile.getAbsolutePath();
- }
- // this is a normal library contained within the bundle
- File nativeFile = bundledata.getBundleFile().getFile(nativepaths[i], true);
- if (nativeFile != null)
- return nativeFile.getAbsolutePath();
- }
- }
- return null;
- }
-
- private String[] getNativePaths(BaseData bundledata) {
- BaseStorageHook storageHook = (BaseStorageHook) bundledata.getStorageHook(BaseStorageHook.KEY);
- return storageHook != null ? storageHook.getNativePaths() : null;
- }
-
- public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) {
- // do nothing
- return false;
- }
-
- public ClassLoader getBundleClassLoaderParent() {
- // do nothing
- return null;
- }
-
- public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- // do nothing
- return null;
- }
-
- public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) {
- // do nothing
- return null;
- }
-
- public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
- // do nothing
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseHookConfigurator.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseHookConfigurator.java
deleted file mode 100644
index 9e25d1e09..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseHookConfigurator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import org.eclipse.osgi.baseadaptor.HookConfigurator;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-
-/**
- * Add the hooks necessary to support the OSGi Framework specification.
- */
-public class BaseHookConfigurator implements HookConfigurator {
-
- public void addHooks(HookRegistry registry) {
- // always add the BaseStorageHook and BaseClassLoadingHook; it is required for the storage implementation
- BaseStorageHook hook = new BaseStorageHook(new BaseStorage());
- registry.addStorageHook(hook);
- registry.addAdaptorHook(hook);
- registry.addClassLoadingHook(new BaseClassLoadingHook());
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BasePermissionStorage.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BasePermissionStorage.java
deleted file mode 100644
index 120861572..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BasePermissionStorage.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.IOException;
-import java.util.*;
-import org.eclipse.osgi.framework.adaptor.PermissionStorage;
-
-public class BasePermissionStorage implements PermissionStorage {
-
- private Map<String, String[]> locations = new HashMap<String, String[]>();
- private String[] defaultInfos;
- private String[] condPermInfos;
- private BaseStorage storage;
- private boolean dirty;
-
- BasePermissionStorage(BaseStorage storage) {
- this.storage = storage;
- }
-
- /**
- * @throws IOException
- */
- public String[] getLocations() throws IOException {
- synchronized (locations) {
- String[] result = new String[locations.size()];
- int i = 0;
- for (Iterator<String> iLocs = locations.keySet().iterator(); iLocs.hasNext(); i++)
- result[i] = iLocs.next();
- return result;
- }
- }
-
- /**
- * @throws IOException
- */
- public String[] getPermissionData(String location) throws IOException {
- if (location == null)
- return defaultInfos;
- synchronized (locations) {
- if (locations.size() == 0)
- return null;
- return locations.get(location);
- }
- }
-
- /**
- * @throws IOException
- */
- public void setPermissionData(String location, String[] data) throws IOException {
- if (location == null) {
- defaultInfos = data;
- return;
- }
- synchronized (locations) {
- if (data == null)
- locations.remove(location);
- else
- locations.put(location, data);
- }
- setDirty(true);
- storage.requestSave();
- }
-
- /**
- * @throws IOException
- */
- public void saveConditionalPermissionInfos(String[] infos) throws IOException {
- condPermInfos = infos;
- setDirty(true);
- storage.requestSave();
- }
-
- /**
- * @throws IOException
- */
- public String[] getConditionalPermissionInfos() throws IOException {
- return condPermInfos;
- }
-
- public boolean isDirty() {
- return dirty;
- }
-
- public void setDirty(boolean dirty) {
- this.dirty = dirty;
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorage.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorage.java
deleted file mode 100644
index 982b8162a..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorage.java
+++ /dev/null
@@ -1,1455 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Rob Harrop - SpringSource Inc. (bug 247520 and 253942)
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.*;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.*;
-import java.util.*;
-import org.eclipse.core.runtime.adaptor.EclipseStarter;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorMsg;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.*;
-import org.eclipse.osgi.baseadaptor.hooks.*;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.framework.util.KeyedHashSet;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
-import org.eclipse.osgi.service.datalocation.Location;
-import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.storagemanager.ManagedOutputStream;
-import org.eclipse.osgi.storagemanager.StorageManager;
-import org.eclipse.osgi.util.ManifestElement;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class BaseStorage implements SynchronousBundleListener {
- private static final String RUNTIME_ADAPTOR = FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + "/eclipseadaptor"; //$NON-NLS-1$
- private static final String OPTION_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/debug/platformadmin"; //$NON-NLS-1$
- private static final String OPTION_PLATFORM_ADMIN_RESOLVER = RUNTIME_ADAPTOR + "/debug/platformadmin/resolver"; //$NON-NLS-1$
- private static final String OPTION_MONITOR_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/resolver/timing"; //$NON-NLS-1$
- private static final String OPTION_RESOLVER_READER = RUNTIME_ADAPTOR + "/resolver/reader/timing"; //$NON-NLS-1$
- private static final String PROP_FRAMEWORK_EXTENSIONS = "osgi.framework.extensions"; //$NON-NLS-1$
- private static final String PROP_BUNDLE_STORE = "osgi.bundlestore"; //$NON-NLS-1$
- // The name of the bundle data directory
- static final String DATA_DIR_NAME = "data"; //$NON-NLS-1$
- static final String LIB_TEMP = "libtemp"; //$NON-NLS-1$
- // System property used to determine whether State saver needs to be enabled
- private static final String PROP_ENABLE_STATE_SAVER = "eclipse.enableStateSaver"; //$NON-NLS-1$
- static final String BUNDLEFILE_NAME = "bundlefile"; //$NON-NLS-1$
- // System property used to clean the osgi configuration area
- private static final String PROP_CLEAN = "osgi.clean"; //$NON-NLS-1$
-
- /** The current bundle data version */
- public static final byte BUNDLEDATA_VERSION = 18;
- /**
- * flag to indicate a framework extension is being intialized
- */
- public static final byte EXTENSION_INITIALIZE = 0x01;
- /**
- * flag to indicate a framework extension is being installed
- */
- public static final byte EXTENSION_INSTALLED = 0x02;
- /**
- * flag to indicate a framework extension is being uninstalled
- */
- public static final byte EXTENSION_UNINSTALLED = 0x04;
- /**
- * flag to indicate a framework extension is being updated
- */
- public static final byte EXTENSION_UPDATED = 0x08;
-
- /** The BundleData is for a bundle exploded in a directory */
- public static final int TYPE_DIRECTORYBUNDLE = 0x10000000;
- /** The BundleData is for a bundle contained in a file (typically jar) */
- public static final int TYPE_FILEBUNDLE = 0x20000000;
-
- /**
- * the file name for the delete flag. If this file exists in one a directory
- * under the bundle store area then it will be removed during the
- * compact operation.
- */
- public static final String DELETE_FLAG = ".delete"; //$NON-NLS-1$
- private static final String PERM_DATA_FILE = ".permdata"; //$NON-NLS-1$
- private static final byte PERMDATA_VERSION = 1;
-
- private final MRUBundleFileList mruList = new MRUBundleFileList();
-
- BaseAdaptor adaptor;
- // assume a file: installURL
- private String installPath;
- private StorageManager storageManager;
- private StateManager stateManager;
- // no need to synchronize on storageHooks because the elements are statically set in initialize
- private KeyedHashSet storageHooks = new KeyedHashSet(5, false);
- private BundleContext context;
- private SynchronousBundleListener extensionListener;
-
- /**
- * The add URL method used to support framework extensions
- */
- private final Method addFwkURLMethod;
- private final Method addExtURLMethod;
-
- /**
- * The list of configured framework extensions
- */
- private String[] configuredExtensions;
-
- private long timeStamp = 0;
- private int initialBundleStartLevel = 1;
-
- private final Object nextIdMonitor = new Object();
- private volatile long nextId = 1;
- /**
- * directory containing installed bundles
- */
- private File bundleStoreRoot;
-
- private BasePermissionStorage permissionStorage;
- private StateSaver stateSaver;
- private boolean invalidState;
- private boolean storageManagerClosed;
-
- BaseStorage() {
- // make constructor package private
- // initialize the addXYZURLMethods to support framework extensions
- addFwkURLMethod = findAddURLMethod(getFwkClassLoader(), "addURL"); //$NON-NLS-1$
- addExtURLMethod = findAddURLMethod(getExtClassLoader(), "addURL"); //$NON-NLS-1$
- }
-
- public void initialize(BaseAdaptor initAdaptor) throws IOException {
- this.adaptor = initAdaptor;
- setDebugOptions();
- if (Boolean.valueOf(FrameworkProperties.getProperty(BaseStorage.PROP_CLEAN)).booleanValue())
- cleanOSGiCache();
-
- // we need to set the install path as soon as possible so we can determine
- // the absolute location of install relative URLs
- Location installLoc = LocationManager.getInstallLocation();
- if (installLoc != null) {
- URL installURL = installLoc.getURL();
- // assume install URL is file: based
- installPath = installURL.getPath();
- }
- boolean readOnlyConfiguration = LocationManager.getConfigurationLocation().isReadOnly();
- storageManager = initFileManager(LocationManager.getOSGiConfigurationDir(), readOnlyConfiguration ? "none" : null, readOnlyConfiguration); //$NON-NLS-1$
- storageManagerClosed = false;
- // initialize the storageHooks
- StorageHook[] hooks = initAdaptor.getHookRegistry().getStorageHooks();
- for (int i = 0; i < hooks.length; i++)
- storageHooks.add(hooks[i]);
- }
-
- private static Method findAddURLMethod(ClassLoader cl, String name) {
- if (cl == null)
- return null;
- return findMethod(cl.getClass(), name, new Class[] {URL.class});
- }
-
- // recursively searches a class and it's superclasses for a (potentially inaccessable) method
- private static Method findMethod(Class<?> clazz, String name, Class<?>[] args) {
- if (clazz == null)
- return null; // ends the recursion when getSuperClass returns null
- try {
- Method result = clazz.getDeclaredMethod(name, args);
- result.setAccessible(true);
- return result;
- } catch (NoSuchMethodException e) {
- // do nothing look in super class below
- } catch (SecurityException e) {
- // if we do not have the permissions then we will not find the method
- }
- return findMethod(clazz.getSuperclass(), name, args);
- }
-
- private static void callAddURLMethod(ClassLoader cl, Method meth, URL arg) throws InvocationTargetException {
- try {
- meth.invoke(cl, new Object[] {arg});
- } catch (Throwable t) {
- throw new InvocationTargetException(t);
- }
- }
-
- private ClassLoader getFwkClassLoader() {
- return this.getClass().getClassLoader();
- }
-
- private ClassLoader getExtClassLoader() {
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- ClassLoader extcl = cl.getParent();
- while ((extcl != null) && (extcl.getParent() != null)) {
- extcl = extcl.getParent();
- }
- return extcl;
- }
-
- private static void setDebugOptions() {
- FrameworkDebugOptions options = FrameworkDebugOptions.getDefault();
- // may be null if debugging is not enabled
- if (options == null)
- return;
- StateManager.DEBUG = options != null;
- StateManager.DEBUG_READER = options.getBooleanOption(OPTION_RESOLVER_READER, false);
- StateManager.MONITOR_PLATFORM_ADMIN = options.getBooleanOption(OPTION_MONITOR_PLATFORM_ADMIN, false);
- StateManager.DEBUG_PLATFORM_ADMIN = options.getBooleanOption(OPTION_PLATFORM_ADMIN, false);
- StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER = options.getBooleanOption(OPTION_PLATFORM_ADMIN_RESOLVER, false);
- }
-
- protected StorageManager initFileManager(File baseDir, String lockMode, boolean readOnly) throws IOException {
- StorageManager sManager = new StorageManager(baseDir, lockMode, readOnly);
- try {
- sManager.open(!readOnly);
- } catch (IOException ex) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading framework metadata: " + ex.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(ex);
- }
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, ex.getMessage());
- FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, ex, null);
- adaptor.getFrameworkLog().log(logEntry);
- FrameworkProperties.setProperty(EclipseStarter.PROP_EXITCODE, "15"); //$NON-NLS-1$
- String errorDialog = "<title>" + AdaptorMsg.ADAPTOR_STORAGE_INIT_FAILED_TITLE + "</title>" + NLS.bind(AdaptorMsg.ADAPTOR_STORAGE_INIT_FAILED_MSG, baseDir) + "\n" + ex.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- FrameworkProperties.setProperty(EclipseStarter.PROP_EXITDATA, errorDialog);
- throw ex;
- }
- return sManager;
- }
-
- public boolean isReadOnly() {
- return storageManager.isReadOnly();
- }
-
- public void compact() {
- if (!isReadOnly())
- compact(getBundleStoreRoot());
- }
-
- private void compact(File directory) {
- if (Debug.DEBUG_GENERAL)
- Debug.println("compact(" + directory.getPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
- String list[] = directory.list();
- if (list == null)
- return;
-
- int len = list.length;
- for (int i = 0; i < len; i++) {
- if (BaseStorage.DATA_DIR_NAME.equals(list[i]))
- continue; /* do not examine the bundles data dir. */
- File target = new File(directory, list[i]);
- // if the file is a directory
- if (!target.isDirectory())
- continue;
- File delete = new File(target, BaseStorage.DELETE_FLAG);
- // and the directory is marked for delete
- if (delete.exists()) {
- // if rm fails to delete the directory and .delete was removed
- if (!AdaptorUtil.rm(target) && !delete.exists()) {
- try {
- // recreate .delete
- FileOutputStream out = new FileOutputStream(delete);
- out.close();
- } catch (IOException e) {
- if (Debug.DEBUG_GENERAL)
- Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- } else {
- compact(target); /* descend into directory */
- }
- }
- }
-
- /**
- * @throws IOException
- */
- public long getFreeSpace() throws IOException {
- // cannot implement this without native code!
- return -1;
- }
-
- public File getDataFile(BaseData data, String path) {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- if (storageHook == null)
- return null;
- return storageHook.getDataFile(path);
- }
-
- BaseAdaptor getAdaptor() {
- return adaptor;
- }
-
- public void installNativeCode(BaseData data, String[] nativepaths) throws BundleException {
- if (nativepaths.length > 0) {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- if (storageHook != null)
- storageHook.installNativePaths(nativepaths);
- }
- }
-
- public Dictionary<String, String> loadManifest(BaseData data) throws BundleException {
- return loadManifest(data, false);
- }
-
- public Dictionary<String, String> loadManifest(BaseData bundleData, boolean firstTime) throws BundleException {
- Dictionary<String, String> result = null;
- StorageHook[] dataStorageHooks = bundleData.getStorageHooks();
- for (int i = 0; i < dataStorageHooks.length && result == null; i++)
- result = dataStorageHooks[i].getManifest(firstTime);
- if (result == null)
- result = AdaptorUtil.loadManifestFrom(bundleData);
- if (result == null)
- throw new BundleException(NLS.bind(AdaptorMsg.MANIFEST_NOT_FOUND_EXCEPTION, Constants.OSGI_BUNDLE_MANIFEST, bundleData.getLocation()), BundleException.MANIFEST_ERROR);
- return result;
- }
-
- public File getExtractFile(BaseData data, String path) {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- if (storageHook == null)
- return null;
- // first check the child generation dir
- File childGenDir = storageHook.getGenerationDir();
- if (childGenDir != null) {
- File childPath = new File(childGenDir, path);
- if (childPath.exists())
- return childPath;
- }
- // now check the parent
- File parentGenDir = storageHook.getParentGenerationDir();
- if (parentGenDir != null) {
- // there is a parent generation check if the file exists
- File parentPath = new File(parentGenDir, path);
- if (parentPath.exists())
- // only use the parent generation file if it exists; do not extract there
- return parentPath;
- }
- // did not exist in both locations; create a file for extraction.
- File bundleGenerationDir = storageHook.createGenerationDir();
- /* if the generation dir exists, then we have place to cache */
- if (bundleGenerationDir != null && bundleGenerationDir.exists())
- return new File(bundleGenerationDir, path);
- return null;
- }
-
- public BaseData[] getInstalledBundles() {
- try {
- return readBundleDatas();
- } catch (Throwable t) {
- // be safe here and throw out the results and start over
- // otherwise this would result in a failed launch
- FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "Error loading bundle datas. Recalculating cache.", 0, t, null); //$NON-NLS-1$
- adaptor.getFrameworkLog().log(logEntry);
- return null;
- }
- }
-
- private BaseData[] readBundleDatas() {
- InputStream bundleDataStream = findStorageStream(LocationManager.BUNDLE_DATA_FILE);
- if (bundleDataStream == null)
- return null;
- try {
- DataInputStream in = new DataInputStream(new BufferedInputStream(bundleDataStream));
- try {
- byte version = in.readByte();
- if (version != BUNDLEDATA_VERSION)
- return null;
- timeStamp = in.readLong();
- initialBundleStartLevel = in.readInt();
- nextId = in.readLong();
-
- int numStorageHooks = in.readInt();
- StorageHook[] hooks = adaptor.getHookRegistry().getStorageHooks();
- if (numStorageHooks != hooks.length)
- return null; // must have the same number of storagehooks to properly read the data
- for (int i = 0; i < numStorageHooks; i++) {
- Object storageKey = hooks[i].getKey();
- int storageVersion = hooks[i].getStorageVersion();
- if (!storageKey.equals(in.readUTF()) || storageVersion != in.readInt())
- return null; // some storage hooks have changed must throw the data away.
- }
-
- int bundleCount = in.readInt();
- List<BaseData> result = new ArrayList<BaseData>(bundleCount);
- long id = -1;
- boolean bundleDiscarded = false;
- for (int i = 0; i < bundleCount; i++) {
- boolean error = false;
- BaseData data = null;
- try {
- id = in.readLong();
- if (id != 0) {
- data = loadBaseData(id, in);
- data.getBundleFile();
- StorageHook[] dataStorageHooks = data.getStorageHooks();
- for (int j = 0; j < dataStorageHooks.length; j++)
- dataStorageHooks[j].validate();
- if (Debug.DEBUG_GENERAL)
- Debug.println("BundleData created: " + data); //$NON-NLS-1$
- processExtension(data, EXTENSION_INITIALIZE);
- result.add(data);
- }
- } catch (IllegalArgumentException e) {
- // may be from data.getBundleFile()
- bundleDiscarded = true;
- error = true;
- } catch (BundleException e) {
- // should never happen
- bundleDiscarded = true;
- error = true;
- } catch (IOException e) {
- bundleDiscarded = true;
- error = true;
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(e);
- }
- }
- if (error && data != null) {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- storageHook.delete(true, BaseStorageHook.DEL_BUNDLE_STORE);
- }
- }
- if (bundleDiscarded)
- FrameworkProperties.setProperty(EclipseStarter.PROP_REFRESH_BUNDLES, "true"); //$NON-NLS-1$
- return result.toArray(new BaseData[result.size()]);
- } finally {
- in.close();
- }
- } catch (IOException e) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(e);
- }
- }
- return null;
- }
-
- private StorageManager getStorageManager() {
- if (storageManagerClosed)
- try {
- storageManager.open(!LocationManager.getConfigurationLocation().isReadOnly());
- storageManagerClosed = false;
- } catch (IOException e) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, e.getMessage());
- FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null);
- adaptor.getFrameworkLog().log(logEntry);
- }
- return storageManager;
- }
-
- void saveAllData(boolean shutdown) {
- if (Debug.DEBUG_GENERAL)
- Debug.println("Saving framework data ..."); //$NON-NLS-1$
- saveBundleDatas();
- saveStateData(shutdown);
- savePermissionStorage();
- if (shutdown)
- stateManager.stopDataManager();
- }
-
- private BasePermissionStorage readPermissionData() {
- BasePermissionStorage result = new BasePermissionStorage(this);
- InputStream permDataStream = findStorageStream(PERM_DATA_FILE);
- if (permDataStream == null)
- return result;
- try {
- DataInputStream in = new DataInputStream(new BufferedInputStream(permDataStream));
- try {
- if (PERMDATA_VERSION != in.readByte())
- return result;
- // read the default permissions first
- int numPerms = in.readInt();
- if (numPerms > 0) {
- String[] perms = new String[numPerms];
- for (int i = 0; i < numPerms; i++)
- perms[i] = in.readUTF();
- result.setPermissionData(null, perms);
- }
- int numLocs = in.readInt();
- if (numLocs > 0)
- for (int i = 0; i < numLocs; i++) {
- String loc = in.readUTF();
- numPerms = in.readInt();
- String[] perms = new String[numPerms];
- for (int j = 0; j < numPerms; j++)
- perms[j] = in.readUTF();
- result.setPermissionData(loc, perms);
- }
- int numCondPerms = in.readInt();
- if (numCondPerms > 0) {
- String[] condPerms = new String[numCondPerms];
- for (int i = 0; i < numCondPerms; i++)
- condPerms[i] = in.readUTF();
- result.saveConditionalPermissionInfos(condPerms);
- }
- result.setDirty(false);
- } finally {
- in.close();
- }
- } catch (IOException e) {
- adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
- }
- return result;
- }
-
- private void savePermissionStorage() {
- if (permissionStorage == null || isReadOnly() || !permissionStorage.isDirty())
- return;
- if (Debug.DEBUG_GENERAL)
- Debug.println("About to save permission data ..."); //$NON-NLS-1$
- try {
- ManagedOutputStream fmos = getStorageManager().getOutputStream(PERM_DATA_FILE);
- DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fmos));
- boolean error = true;
- try {
- out.writeByte(PERMDATA_VERSION);
- // always write the default permissions first
- String[] defaultPerms = permissionStorage.getPermissionData(null);
- out.writeInt(defaultPerms == null ? 0 : defaultPerms.length);
- if (defaultPerms != null)
- for (int i = 0; i < defaultPerms.length; i++)
- out.writeUTF(defaultPerms[i]);
- String[] locations = permissionStorage.getLocations();
- out.writeInt(locations == null ? 0 : locations.length);
- if (locations != null)
- for (int i = 0; i < locations.length; i++) {
- out.writeUTF(locations[i]);
- String[] perms = permissionStorage.getPermissionData(locations[i]);
- out.writeInt(perms == null ? 0 : perms.length);
- if (perms != null)
- for (int j = 0; j < perms.length; j++)
- out.writeUTF(perms[j]);
- }
- String[] condPerms = permissionStorage.getConditionalPermissionInfos();
- out.writeInt(condPerms == null ? 0 : condPerms.length);
- if (condPerms != null)
- for (int i = 0; i < condPerms.length; i++)
- out.writeUTF(condPerms[i]);
- out.close();
- permissionStorage.setDirty(false);
- error = false;
- } finally {
- // if something happens, don't close a corrupt file
- if (error) {
- fmos.abort();
- try {
- out.close();
- } catch (IOException e) {/*ignore*/
- }
- }
- }
- } catch (IOException e) {
- adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
- return;
- }
- }
-
- private void saveBundleDatas() {
- // the cache and the state match
- if (stateManager == null || isReadOnly() || (timeStamp == stateManager.getSystemState().getTimeStamp() && !stateManager.saveNeeded()))
- return;
- if (Debug.DEBUG_GENERAL)
- Debug.println("Saving bundle data ..."); //$NON-NLS-1$
- try {
- ManagedOutputStream fmos = getStorageManager().getOutputStream(LocationManager.BUNDLE_DATA_FILE);
- DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fmos));
- boolean error = true;
- try {
- out.writeByte(BUNDLEDATA_VERSION);
- out.writeLong(stateManager.getSystemState().getTimeStamp());
- out.writeInt(initialBundleStartLevel);
- out.writeLong(nextId);
-
- StorageHook[] hooks = adaptor.getHookRegistry().getStorageHooks();
- out.writeInt(hooks.length);
- for (int i = 0; i < hooks.length; i++) {
- out.writeUTF((String) hooks[i].getKey());
- out.writeInt(hooks[i].getStorageVersion());
- }
-
- Bundle[] bundles = context.getBundles();
- out.writeInt(bundles.length);
- for (int i = 0; i < bundles.length; i++) {
- long id = bundles[i].getBundleId();
- out.writeLong(id);
- if (id != 0) {
- BundleData data = ((org.eclipse.osgi.framework.internal.core.AbstractBundle) bundles[i]).getBundleData();
- saveBaseData((BaseData) data, out);
- }
- }
- out.close();
- // update the 'timeStamp' after the changed Meta data is saved.
- timeStamp = stateManager.getSystemState().getTimeStamp();
- error = false;
- } finally {
- // if something happens, don't close a corrupt file
- if (error) {
- fmos.abort();
- try {
- out.close();
- } catch (IOException e) {/*ignore*/
- }
- }
- }
- } catch (IOException e) {
- adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
- return;
- }
- }
-
- private void cleanRemovalPendings(State systemState, BundleDescription[] removalPendings) {
- if (removalPendings.length == 0)
- return;
- systemState.resolve(removalPendings);
- for (int i = 0; i < removalPendings.length; i++) {
- Object userObject = removalPendings[i].getUserObject();
- if (userObject instanceof BundleLoaderProxy) {
- BundleLoader.closeBundleLoader((BundleLoaderProxy) userObject);
- try {
- ((BundleLoaderProxy) userObject).getBundleData().close();
- } catch (IOException e) {
- // ignore
- }
- } else if (userObject instanceof BundleData) {
- try {
- ((BundleData) userObject).close();
- } catch (IOException e) {
- // ignore
- }
- }
- }
- }
-
- private void saveStateData(boolean shutdown) {
- State systemState = stateManager.getSystemState();
- if (shutdown && "true".equals(FrameworkProperties.getProperty("osgi.forcedRestart"))) //$NON-NLS-1$ //$NON-NLS-2$
- // increment the state timestamp if a forced restart happened.
- systemState.setTimeStamp(systemState.getTimeStamp() + 1);
- BundleDescription[] removalPendings = systemState.getRemovalPending();
- if (removalPendings.length > 0) {
- if (!shutdown)
- return; // never save if removal pending; unless we are shutting down
- cleanRemovalPendings(systemState, removalPendings);
- }
- if (stateManager == null || isReadOnly() || !stateManager.saveNeeded())
- return;
- if (Debug.DEBUG_GENERAL)
- Debug.println("Saving resolver state data ..."); //$NON-NLS-1$
- File stateTmpFile = null;
- File lazyTmpFile = null;
- try {
- stateTmpFile = File.createTempFile(LocationManager.STATE_FILE, ".new", LocationManager.getOSGiConfigurationDir()); //$NON-NLS-1$
- lazyTmpFile = File.createTempFile(LocationManager.LAZY_FILE, ".new", LocationManager.getOSGiConfigurationDir()); //$NON-NLS-1$
- if (shutdown)
- stateManager.shutdown(stateTmpFile, lazyTmpFile);
- else
- synchronized (stateManager) {
- stateManager.update(stateTmpFile, lazyTmpFile);
- }
- StorageManager curStorageManager = getStorageManager();
- curStorageManager.lookup(LocationManager.STATE_FILE, true);
- curStorageManager.lookup(LocationManager.LAZY_FILE, true);
- curStorageManager.update(new String[] {LocationManager.STATE_FILE, LocationManager.LAZY_FILE}, new String[] {stateTmpFile.getName(), lazyTmpFile.getName()});
- } catch (IOException e) {
- adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
- } finally {
- if (stateTmpFile != null && stateTmpFile.exists())
- stateTmpFile.delete();
- if (lazyTmpFile != null && lazyTmpFile.exists())
- lazyTmpFile.delete();
- }
- }
-
- public PermissionStorage getPermissionStorage() {
- if (permissionStorage == null)
- permissionStorage = readPermissionData();
- return permissionStorage;
- }
-
- public int getInitialBundleStartLevel() {
- return initialBundleStartLevel;
- }
-
- public void setInitialBundleStartLevel(int value) {
- this.initialBundleStartLevel = value;
- requestSave();
- }
-
- public void save(BaseData data) {
- if (data.isDirty()) {
- timeStamp--; // Change the value of the timeStamp, as a marker that something changed.
- requestSave();
- data.setDirty(false);
- }
- }
-
- public BundleOperation installBundle(String location, URLConnection source) {
- BaseData data = createBaseData(getNextBundleId(), location);
- return new BundleInstall(data, source, this);
- }
-
- public BundleOperation updateBundle(BaseData data, URLConnection source) {
- return new BundleUpdate(data, source, this);
- }
-
- public BundleOperation uninstallBundle(BaseData data) {
- return new BundleUninstall(data, this);
- }
-
- protected Object getBundleContent(BaseData bundledata) {
- BaseStorageHook storageHook = (BaseStorageHook) bundledata.getStorageHook(BaseStorageHook.KEY);
- if (storageHook == null)
- throw new IllegalStateException();
- return storageHook.isReference() ? new File(storageHook.getFileName()) : new File(storageHook.getGenerationDir(), storageHook.getFileName());
- }
-
- public BundleFile createBundleFile(Object content, BaseData data) throws IOException {
- boolean base = false;
- if (content == null) {
- // this must be a request for the base bundlefile
- base = true;
- // get the content of this bundle
- content = getBundleContent(data);
- }
- BundleFile result = data.getBundleFile(content, base);
- if (result != null)
- return result;
- // Ask factories before doing the default behavior
- BundleFileFactoryHook[] factories = adaptor.getHookRegistry().getBundleFileFactoryHooks();
- for (int i = 0; i < factories.length && result == null; i++)
- result = factories[i].createBundleFile(content, data, base);
-
- // No factories configured or they declined to create the bundle file; do default
- if (result == null && content instanceof File) {
- File file = (File) content;
- if (isDirectory(data, base, file))
- result = new DirBundleFile(file);
- else
- result = new ZipBundleFile(file, data, mruList);
- }
-
- if (result == null && content instanceof String) {
- // here we assume the content is a path offset into the base bundle file; create a NestedDirBundleFile
- result = new NestedDirBundleFile(data.getBundleFile(), (String) content);
- }
- if (result == null)
- // nothing we can do; must throw exception for the content
- throw new IOException("Cannot create bundle file for content of type: " + content.getClass().getName()); //$NON-NLS-1$
-
- // try creating a wrapper bundlefile out of it.
- BundleFileWrapperFactoryHook[] wrapperFactories = adaptor.getHookRegistry().getBundleFileWrapperFactoryHooks();
- BundleFileWrapperChain wrapped = wrapperFactories.length == 0 ? null : new BundleFileWrapperChain(result, null);
- for (int i = 0; i < wrapperFactories.length; i++) {
- BundleFile wrapperBundle = wrapperFactories[i].wrapBundleFile(result, content, data, base);
- if (wrapperBundle != null && wrapperBundle != result)
- result = wrapped = new BundleFileWrapperChain(wrapperBundle, wrapped);
- }
- if (!base)
- data.setBundleFile(content, result);
- return result;
- }
-
- private boolean isDirectory(BaseData data, boolean base, File file) {
- if (!base)
- // there is no other place to check this; just consult the file directly
- return file.isDirectory();
- boolean isDirectory = false;
- // first check if the type bits have been set
- int type = data.getType();
- if ((type & (TYPE_DIRECTORYBUNDLE | TYPE_FILEBUNDLE)) == 0) {
- // no type bits set; consult the file and save the result
- isDirectory = file.isDirectory();
- data.setType(type | (isDirectory ? TYPE_DIRECTORYBUNDLE : TYPE_FILEBUNDLE));
- } else {
- // type bits have been set check to see if this is a directory bundle.
- isDirectory = (type & TYPE_DIRECTORYBUNDLE) != 0;
- }
- return isDirectory;
- }
-
- public synchronized StateManager getStateManager() {
- if (stateManager != null)
- return stateManager;
- stateManager = readStateData();
- checkSystemState(stateManager.getSystemState());
- return stateManager;
- }
-
- private void checkSystemState(State state) {
- BundleDescription[] bundles = state.getBundles();
- if (bundles == null)
- return;
- boolean removedBundle = false;
- for (int i = 0; i < bundles.length; i++) {
- if (adaptor.getBundle(bundles[i].getBundleId()) == null) {
- state.removeBundle(bundles[i]);
- removedBundle = true;
- }
- }
- if (removedBundle)
- state.resolve(false); // do a full resolve
- BundleDescription systemBundle = state.getBundle(0);
- if (systemBundle == null || !systemBundle.isResolved()) {
- ResolverError[] errors = systemBundle == null ? new ResolverError[0] : state.getResolverErrors(systemBundle);
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < errors.length; i++) {
- sb.append(errors[i].toString());
- if (i < errors.length - 1)
- sb.append(", "); //$NON-NLS-1$
- }
- // this would be a bug in the framework
- throw new IllegalStateException(NLS.bind(AdaptorMsg.SYSTEMBUNDLE_NOTRESOLVED, sb.toString()));
- }
- }
-
- private StateManager readStateData() {
- File[] stateFiles = findStorageFiles(new String[] {LocationManager.STATE_FILE, LocationManager.LAZY_FILE});
- File stateFile = stateFiles[0];
- File lazyFile = stateFiles[1];
-
- stateManager = new StateManager(stateFile, lazyFile, context, timeStamp);
- State systemState = null;
- if (!invalidState) {
- systemState = stateManager.readSystemState();
- if (systemState != null)
- return stateManager;
- }
- systemState = stateManager.createSystemState();
- Bundle[] installedBundles = context.getBundles();
- if (installedBundles == null)
- return stateManager;
- StateObjectFactory factory = stateManager.getFactory();
- for (int i = 0; i < installedBundles.length; i++) {
- AbstractBundle toAdd = (AbstractBundle) installedBundles[i];
- try {
- // make sure we get the real manifest as if this is the first time.
- Dictionary<String, String> toAddManifest = loadManifest((BaseData) toAdd.getBundleData(), true);
- BundleDescription newDescription = factory.createBundleDescription(systemState, toAddManifest, toAdd.getLocation(), toAdd.getBundleId());
- systemState.addBundle(newDescription);
- } catch (BundleException be) {
- // just ignore bundle datas with invalid manifests
- }
- }
- // we do not set the cached timestamp here because we want a new one to be used from the new system state object (bug 132978)
- // we need the state resolved
- systemState.resolve();
- invalidState = false;
- return stateManager;
- }
-
- private File[] findStorageFiles(String[] fileNames) {
- StorageManager curStorageManager = getStorageManager();
- File[] storageFiles = new File[fileNames.length];
- try {
- for (int i = 0; i < storageFiles.length; i++)
- storageFiles[i] = curStorageManager.lookup(fileNames[i], false);
- } catch (IOException ex) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(ex);
- }
- }
- boolean success = true;
- for (int i = 0; i < storageFiles.length; i++)
- if (storageFiles[i] == null || !storageFiles[i].isFile()) {
- success = false;
- break;
- }
- if (success)
- return storageFiles;
- //if it does not exist, try to read it from the parent
- Location parentConfiguration = null;
- Location currentConfiguration = LocationManager.getConfigurationLocation();
- if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) {
- try {
- File stateLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME);
- StorageManager newFileManager = initFileManager(stateLocationDir, "none", true); //$NON-NLS-1$);
- for (int i = 0; i < storageFiles.length; i++)
- storageFiles[i] = newFileManager.lookup(fileNames[i], false);
- newFileManager.close();
- } catch (IOException ex) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(ex);
- }
- }
- } else {
- try {
- //it did not exist in either place, so create it in the original location
- if (!isReadOnly()) {
- for (int i = 0; i < storageFiles.length; i++)
- storageFiles[i] = curStorageManager.lookup(fileNames[i], true);
- }
- } catch (IOException ex) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(ex);
- }
- }
- }
- return storageFiles;
- }
-
- public void frameworkStart(BundleContext fwContext) {
- this.context = fwContext;
- // System property can be set to enable state saver or not.
- if (Boolean.valueOf(FrameworkProperties.getProperty(BaseStorage.PROP_ENABLE_STATE_SAVER, "true")).booleanValue()) //$NON-NLS-1$
- stateSaver = new StateSaver(adaptor.getState());
-
- }
-
- public void frameworkStop(BundleContext fwContext) {
- if (stateSaver != null)
- stateSaver.shutdown();
- saveAllData(true);
- storageManager.close();
- storageManagerClosed = true;
- if (extensionListener != null)
- context.removeBundleListener(extensionListener);
- mruList.shutdown();
- stateManager = null;
- }
-
- public void frameworkStopping(BundleContext fwContext) {
- // do nothing in storage
- }
-
- public void addProperties(Properties properties) {
- // set the extension support if we found the addURL method
- if (addFwkURLMethod != null)
- properties.put(Constants.SUPPORTS_FRAMEWORK_EXTENSION, "true"); //$NON-NLS-1$
- // store bundleStore back into adaptor properties for others to see
- properties.put(BaseStorage.PROP_BUNDLE_STORE, getBundleStoreRoot().getAbsolutePath());
- }
-
- private InputStream findStorageStream(String fileName) {
- InputStream storageStream = null;
- try {
- storageStream = getStorageManager().getInputStream(fileName);
- } catch (IOException ex) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error reading framework metadata: " + ex.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(ex);
- }
- }
- if (storageStream == null) {
- Location currentConfiguration = LocationManager.getConfigurationLocation();
- Location parentConfiguration = null;
- if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) {
- try {
- File bundledataLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME);
- StorageManager newStorageManager = initFileManager(bundledataLocationDir, "none", true); //$NON-NLS-1$
- storageStream = newStorageManager.getInputStream(fileName);
- newStorageManager.close();
- } catch (MalformedURLException e1) {
- // This will not happen since all the URLs are derived by us
- // and we are GODS!
- } catch (IOException e1) {
- // That's ok we will regenerate the .bundleData
- }
- }
- }
- return storageStream;
- }
-
- protected void saveBaseData(BaseData bundledata, DataOutputStream out) throws IOException {
- StorageHook[] hooks = bundledata.getStorageHooks();
- out.writeInt(hooks.length);
- for (int i = 0; i < hooks.length; i++) {
- out.writeUTF((String) hooks[i].getKey());
- hooks[i].save(out);
- }
- }
-
- protected BaseData loadBaseData(long id, DataInputStream in) throws IOException {
- BaseData result = new BaseData(id, adaptor);
- int numHooks = in.readInt();
- StorageHook[] hooks = new StorageHook[numHooks];
- for (int i = 0; i < numHooks; i++) {
- String hookKey = in.readUTF();
- StorageHook storageHook = (StorageHook) storageHooks.getByKey(hookKey);
- if (storageHook == null)
- throw new IOException();
- hooks[i] = storageHook.load(result, in);
- }
- result.setStorageHooks(hooks);
- return result;
- }
-
- protected BaseData createBaseData(long id, String location) {
- BaseData result = new BaseData(id, adaptor);
- result.setLocation(location);
- return result;
- }
-
- public String getInstallPath() {
- return installPath;
- }
-
- private void cleanOSGiCache() {
- File osgiConfig = LocationManager.getOSGiConfigurationDir();
- if (!AdaptorUtil.rm(osgiConfig))
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "The -clean (osgi.clean) option was not successful. Unable to clean the storage area: " + osgiConfig.getAbsolutePath(), 0, null, null)); //$NON-NLS-1$
-
- }
-
- /**
- * Processes an extension bundle
- * @param bundleData the extension bundle data
- * @param type the type of extension bundle
- * @throws BundleException on any errors or if the extension bundle type is not supported
- */
- protected void processExtension(BaseData bundleData, byte type) throws BundleException {
- if ((bundleData.getType() & BundleData.TYPE_FRAMEWORK_EXTENSION) != 0) {
- validateExtension(bundleData);
- processFrameworkExtension(bundleData, type);
- } else if ((bundleData.getType() & BundleData.TYPE_BOOTCLASSPATH_EXTENSION) != 0) {
- validateExtension(bundleData);
- processBootExtension(bundleData, type);
- } else if ((bundleData.getType() & BundleData.TYPE_EXTCLASSPATH_EXTENSION) != 0) {
- validateExtension(bundleData);
- processExtExtension(bundleData, type);
- }
- }
-
- /**
- * Validates the extension bundle metadata
- * @param bundleData the extension bundle data
- * @throws BundleException if the extension bundle metadata is invalid
- */
- private void validateExtension(BundleData bundleData) throws BundleException {
- Dictionary<String, String> extensionManifest = bundleData.getManifest();
- if (extensionManifest.get(Constants.IMPORT_PACKAGE) != null)
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_IMPORT_ERROR, bundleData.getLocation()), BundleException.MANIFEST_ERROR);
- if (extensionManifest.get(Constants.REQUIRE_BUNDLE) != null)
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_REQUIRE_ERROR, bundleData.getLocation()), BundleException.MANIFEST_ERROR);
- if (extensionManifest.get(Constants.BUNDLE_NATIVECODE) != null)
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_NATIVECODE_ERROR, bundleData.getLocation()), BundleException.MANIFEST_ERROR);
- }
-
- /**
- * Processes a framework extension bundle
- * @param bundleData the extension bundle data
- * @param type the type of extension bundle
- * @throws BundleException on errors or if framework extensions are not supported
- */
- protected void processFrameworkExtension(BaseData bundleData, byte type) throws BundleException {
- if (addFwkURLMethod == null)
- throw new BundleException("Framework extensions are not supported.", BundleException.UNSUPPORTED_OPERATION, new UnsupportedOperationException()); //$NON-NLS-1$
- addExtensionContent(bundleData, type, getFwkClassLoader(), addFwkURLMethod);
- }
-
- protected void processExtExtension(BaseData bundleData, byte type) throws BundleException {
- if (addExtURLMethod == null)
- throw new BundleException("Extension classpath extensions are not supported.", BundleException.UNSUPPORTED_OPERATION, new UnsupportedOperationException()); //$NON-NLS-1$
- addExtensionContent(bundleData, type, getExtClassLoader(), addExtURLMethod);
- }
-
- private void addExtensionContent(BaseData bundleData, byte type, ClassLoader addToLoader, Method addToMethod) {
- if ((type & (EXTENSION_UNINSTALLED | EXTENSION_UPDATED)) != 0)
- // if uninstalled or updated then do nothing framework must be restarted.
- return;
-
- // first make sure this BundleData is not on the pre-configured osgi.framework.extensions list
- String[] extensions = getConfiguredExtensions();
- for (int i = 0; i < extensions.length; i++)
- if (extensions[i].equals(bundleData.getSymbolicName()))
- return;
- if ((type & EXTENSION_INSTALLED) != 0) {
- if (extensionListener == null) {
- // add bundle listener to wait for extension to be resolved
- extensionListener = this;
- context.addBundleListener(extensionListener);
- }
- return;
- }
- File[] files = getExtensionFiles(bundleData);
- if (files == null)
- return;
-
- for (int i = 0; i < files.length; i++) {
- if (files[i] == null)
- continue;
- try {
- callAddURLMethod(addToLoader, addToMethod, AdaptorUtil.encodeFileURL(files[i]));
- } catch (InvocationTargetException e) {
- adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundleData.getBundle(), e);
- } catch (MalformedURLException e) {
- adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundleData.getBundle(), e);
- }
- }
-
- try {
- addToLoader.loadClass("thisIsNotAClass"); // initialize the new urls //$NON-NLS-1$
- } catch (ClassNotFoundException e) {
- // do nothing
- }
- }
-
- /**
- * Returns a list of configured extensions
- * @return a list of configured extensions
- */
- protected String[] getConfiguredExtensions() {
- if (configuredExtensions != null)
- return configuredExtensions;
- String prop = FrameworkProperties.getProperty(BaseStorage.PROP_FRAMEWORK_EXTENSIONS);
- if (prop == null || prop.trim().length() == 0)
- configuredExtensions = new String[0];
- else
- configuredExtensions = ManifestElement.getArrayFromList(prop);
- return configuredExtensions;
- }
-
- /**
- * Processes a boot extension bundle
- * @param bundleData the extension bundle data
- * @param type the type of extension bundle
- * @throws BundleException on errors or if boot extensions are not supported
- */
- protected void processBootExtension(BundleData bundleData, byte type) throws BundleException {
- throw new BundleException("Boot classpath extensions are not supported.", BundleException.UNSUPPORTED_OPERATION, new UnsupportedOperationException()); //$NON-NLS-1$
- }
-
- private void initBundleStoreRoot() {
- File configurationLocation = LocationManager.getOSGiConfigurationDir();
- if (configurationLocation != null)
- bundleStoreRoot = new File(configurationLocation, LocationManager.BUNDLES_DIR);
- else
- // last resort just default to "bundles"
- bundleStoreRoot = new File(LocationManager.BUNDLES_DIR);
- }
-
- public File getBundleStoreRoot() {
- if (bundleStoreRoot == null)
- initBundleStoreRoot();
- return bundleStoreRoot;
- }
-
- /**
- * Returns a list of classpath files for an extension bundle
- * @param bundleData the bundle data for an extension bundle
- * @return a list of classpath files for an extension bundle
- */
- protected File[] getExtensionFiles(BaseData bundleData) {
- File[] files = null;
- try {
- String[] paths = bundleData.getClassPath();
- if (DevClassPathHelper.inDevelopmentMode()) {
- String[] devPaths = DevClassPathHelper.getDevClassPath(bundleData.getSymbolicName());
- String[] origPaths = paths;
-
- paths = new String[origPaths.length + devPaths.length];
- System.arraycopy(origPaths, 0, paths, 0, origPaths.length);
- System.arraycopy(devPaths, 0, paths, origPaths.length, devPaths.length);
- }
- List<File> results = new ArrayList<File>(paths.length);
- for (int i = 0; i < paths.length; i++) {
- if (".".equals(paths[i])) //$NON-NLS-1$
- results.add(bundleData.getBundleFile().getBaseFile());
- else {
- File result = bundleData.getBundleFile().getFile(paths[i], false);
- if (result != null)
- results.add(result);
- }
- }
- return results.toArray(new File[results.size()]);
- } catch (BundleException e) {
- adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundleData.getBundle(), e);
- }
- return files;
- }
-
- void requestSave() {
- // Only when the State saver is enabled will the stateSaver be started.
- if (stateSaver == null)
- return;
- stateSaver.requestSave();
- }
-
- /**
- * Updates the state mananager with an updated/installed/uninstalled bundle
- * @param bundleData the modified bundle
- * @param type the type of modification
- * @throws BundleException
- */
- public void updateState(BaseData bundleData, int type) throws BundleException {
- if (stateManager == null) {
- invalidState = true;
- return;
- }
- State systemState = stateManager.getSystemState();
- BundleDescription oldDescription = null;
- BundleDescription newDescription = null;
- switch (type) {
- case BundleEvent.UPDATED :
- // fall through to INSTALLED
- case BundleEvent.INSTALLED :
- if (type == BundleEvent.UPDATED)
- oldDescription = systemState.getBundle(bundleData.getBundleID());
- newDescription = stateManager.getFactory().createBundleDescription(systemState, bundleData.getManifest(), bundleData.getLocation(), bundleData.getBundleID());
- // For the install case we need to set the bundle before adding to the state
- // because the bundle is not available in the context yet.
- // We go ahead and set it for the update case for simplicity;
- // but this is not strictly necessary
- newDescription.setUserObject(bundleData);
- if (oldDescription == null)
- systemState.addBundle(newDescription);
- else
- systemState.updateBundle(newDescription);
- break;
- case BundleEvent.UNINSTALLED :
- systemState.removeBundle(bundleData.getBundleID());
- break;
- }
-
- if (newDescription != null)
- validateNativeCodePaths(newDescription, bundleData);
- }
-
- private void validateNativeCodePaths(BundleDescription newDescription, BaseData data) {
- NativeCodeSpecification nativeCode = newDescription.getNativeCodeSpecification();
- if (nativeCode == null)
- return;
- NativeCodeDescription nativeCodeDescs[] = nativeCode.getPossibleSuppliers();
- for (int i = 0; i < nativeCodeDescs.length; i++) {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- if (storageHook != null)
- try {
- storageHook.validateNativePaths(nativeCodeDescs[i].getNativePaths());
- } catch (BundleException e) {
- stateManager.getSystemState().setNativePathsInvalid(nativeCodeDescs[i], true);
- }
- }
- }
-
- private class StateSaver implements Runnable {
- private final long delay_interval;
- private final long max_total_delay_interval;
- private boolean shutdown = false;
- private long lastSaveTime = 0;
- private Thread runningThread = null;
- private Thread shutdownHook = null;
-
- // Bug 383338. Pass the BaseAdaptor state as a constructor argument and
- // reuse rather than call adaptor.getState(), and risk an NPE from
- // Framework due to a null ServiceRegistry, each time a lock is desired.
- private final State lock;
-
- StateSaver(State lock) {
- this.lock = lock;
- String prop = FrameworkProperties.getProperty("eclipse.stateSaveDelayInterval"); //$NON-NLS-1$
- long delayValue = 30000; // 30 seconds.
- long maxDelayValue = 1800000; // 30 minutes.
- if (prop != null) {
- try {
- long val = Long.parseLong(prop);
- if (val >= 1000 && val <= 1800000) {
- delayValue = val;
- maxDelayValue = val * 60;
- } else if (val == 0) {
- delayValue = 0;
- maxDelayValue = 0;
- }
- } catch (NumberFormatException e) {
- // ignore
- }
- }
- delay_interval = delayValue;
- max_total_delay_interval = maxDelayValue;
- }
-
- public void run() {
- synchronized (lock) {
- long firstSaveTime = lastSaveTime;
- long curSaveTime = 0;
- long delayTime;
- do {
- do {
- if ((System.currentTimeMillis() - firstSaveTime) > max_total_delay_interval) {
- curSaveTime = lastSaveTime;
- // Waiting time has been too long, so break to start saving State data to file.
- break;
- }
- delayTime = Math.min(delay_interval, lastSaveTime - curSaveTime);
- curSaveTime = lastSaveTime;
- // wait for other save requests
- try {
- if (!shutdown)
- lock.wait(delayTime);
- } catch (InterruptedException ie) {
- // force break from do/while loops
- curSaveTime = lastSaveTime;
- break;
- }
- // Continue the loop if 'lastSaveTime' is increased again during waiting.
- } while (!shutdown && curSaveTime < lastSaveTime);
- // Save State and Meta data.
- saveAllData(false);
- // Continue the loop if Saver is asked again during saving State data to file.
- } while (!shutdown && curSaveTime < lastSaveTime);
- runningThread = null; // clear runningThread
- try {
- Runtime.getRuntime().removeShutdownHook(shutdownHook);
- } catch (IllegalStateException e) {
- // avoid exception if shutdown is in progress
- }
- shutdownHook = null;
- }
- }
-
- void shutdown() {
- Thread joinWith;
- synchronized (lock) {
- if (shutdown)
- return; // Don't shutdown more than once. Bug 383338.
- shutdown = true;
- joinWith = runningThread;
- lock.notifyAll(); // To wakeup sleeping thread.
- }
- try {
- if (joinWith != null) {
- if (Debug.DEBUG_GENERAL)
- Debug.println("About to join saving thread"); //$NON-NLS-1$
- // There should be no deadlock when 'shutdown' is true.
- joinWith.join();
- if (Debug.DEBUG_GENERAL)
- Debug.println("Joined with saving thread"); //$NON-NLS-1$
- }
- } catch (InterruptedException ie) {
- if (Debug.DEBUG_GENERAL) {
- Debug.println("Error shutdowning StateSaver: " + ie.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(ie);
- }
- }
- }
-
- void requestSave() {
- synchronized (lock) {
- if (shutdown)
- return; // do not start another thread if we have already shutdown
- if (delay_interval == 0) {
- // all saves are atomic; never start a background thread
- saveAllData(false);
- return;
- }
- lastSaveTime = System.currentTimeMillis();
- if (runningThread == null) {
- shutdownHook = new Thread(new Runnable() {
- public void run() {
- // Synchronize with JVM shutdown hook, because
- // saveAllData creates a temp file with delete on
- // exit is true. The temp file will be removed in the
- // shutdown hook. This prevents that the remove temp files
- // in the shutdown hook is earlier handled then adding new
- // temp file in saveAllData.
- shutdown();
- }
- });
- runningThread = new Thread(this, "State Saver"); //$NON-NLS-1$
- runningThread.start();
- try {
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- } catch (IllegalStateException e) {
- // bug 374300 - need to ignore this in case the VM is being shutdown
- }
- }
- }
- }
- }
-
- public long getNextBundleId() {
- synchronized (this.nextIdMonitor) {
- return nextId++;
- }
- }
-
- public void bundleChanged(BundleEvent event) {
- if (event.getType() != BundleEvent.RESOLVED)
- return;
- BaseData data = (BaseData) ((AbstractBundle) event.getBundle()).getBundleData();
- try {
- if ((data.getType() & BundleData.TYPE_FRAMEWORK_EXTENSION) != 0)
- processFrameworkExtension(data, EXTENSION_INITIALIZE);
- else if ((data.getType() & BundleData.TYPE_BOOTCLASSPATH_EXTENSION) != 0)
- processBootExtension(data, EXTENSION_INITIALIZE);
- else if ((data.getType() & BundleData.TYPE_EXTCLASSPATH_EXTENSION) != 0)
- processExtExtension(data, EXTENSION_INITIALIZE);
- } catch (BundleException e) {
- // do nothing;
- }
- }
-
- public String copyToTempLibrary(BaseData data, String absolutePath) throws IOException {
- File storageRoot = getBundleStoreRoot();
- File libTempDir = new File(storageRoot, LIB_TEMP);
- // we assume the absolutePath is a File path
- File realLib = new File(absolutePath);
- String libName = realLib.getName();
- // find a temp dir for the bundle data and the library;
- File bundleTempDir = null;
- File libTempFile = null;
- // We need a somewhat predictable temp dir for the libraries of a given bundle;
- // This is not strictly necessary but it does help scenarios where one native library loads another native library without using java.
- // On some OSes this causes issues because the second library is cannot be found.
- // This has been worked around by the bundles loading the libraries in a particular order (and setting some LIB_PATH env).
- // The one catch is that the libraries need to be in the same directory and they must use their original lib names.
- //
- // This bit of code attempts to do that by using the bundle ID as an ID for the temp dir along with an incrementing ID
- // in cases where the temp dir may already exist.
- Long bundleID = new Long(data.getBundleID());
- for (int i = 0; i < Integer.MAX_VALUE; i++) {
- bundleTempDir = new File(libTempDir, bundleID.toString() + "_" + new Integer(i).toString()); //$NON-NLS-1$
- libTempFile = new File(bundleTempDir, libName);
- if (bundleTempDir.exists()) {
- if (libTempFile.exists())
- continue; // to to next temp file
- break;
- }
- break;
- }
- if (!bundleTempDir.exists()) {
- bundleTempDir.mkdirs();
- bundleTempDir.deleteOnExit();
- // This is just a safeguard incase the VM is terminated unexpectantly, it also looks like deleteOnExit cannot really work because
- // the VM likely will still have a lock on the lib file at the time of VM exit.
- File deleteFlag = new File(libTempDir, BaseStorage.DELETE_FLAG);
- if (!deleteFlag.exists()) {
- // need to create a delete flag to force removal the temp libraries
- try {
- FileOutputStream out = new FileOutputStream(deleteFlag);
- out.close();
- } catch (IOException e) {
- // do nothing; that would mean we did not make the temp dir successfully
- }
- }
- }
- // copy the library file
- InputStream in = new FileInputStream(realLib);
- AdaptorUtil.readFile(in, libTempFile);
- // set permissions if needed
- BundleFile.setPermissions(libTempFile);
- libTempFile.deleteOnExit(); // this probably will not work because the VM will probably have the lib locked at exit
- // return the temporary path
- return libTempFile.getAbsolutePath();
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorageHook.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorageHook.java
deleted file mode 100644
index aa405123c..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BaseStorageHook.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Rob Harrop - SpringSource Inc. (bug 253942)
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.*;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.*;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.framework.util.KeyedElement;
-import org.eclipse.osgi.service.datalocation.Location;
-import org.eclipse.osgi.util.ManifestElement;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class BaseStorageHook implements StorageHook, AdaptorHook {
- public static final String KEY = BaseStorageHook.class.getName();
- public static final int HASHCODE = KEY.hashCode();
- public static final int DEL_BUNDLE_STORE = 0x01;
- public static final int DEL_GENERATION = 0x02;
- private static final int STORAGE_VERSION = 1;
- public static final String EXTERNAL_LIB_PREFIX = "external:"; //$NON-NLS-1$
- public static final String VARIABLE_DELIM_STRING = "$"; //$NON-NLS-1$
- public static final char VARIABLE_DELIM_CHAR = '$';
- public static String COMPOSITE_HEADER = "Equinox-CompositeBundle"; //$NON-NLS-1$
- public static String COMPOSITE_BUNDLE = "composite"; //$NON-NLS-1$
- public static String SURROGATE_BUNDLE = "surrogate"; //$NON-NLS-1$
-
- /** bundle's file name */
- private String fileName;
- /** native code paths for this BundleData */
- private String[] nativePaths;
- /** bundle generation */
- private int generation = 1;
- /** Is bundle a reference */
- private boolean reference;
-
- private BaseData bundleData;
- private BaseStorage storage;
- private File bundleStore;
- private File dataStore;
-
- public BaseStorageHook(BaseStorage storage) {
- this.storage = storage;
- }
-
- public int getStorageVersion() {
- return STORAGE_VERSION;
- }
-
- /**
- * @throws BundleException
- */
- public StorageHook create(BaseData bundledata) throws BundleException {
- BaseStorageHook storageHook = new BaseStorageHook(storage);
- storageHook.bundleData = bundledata;
- return storageHook;
- }
-
- public void initialize(Dictionary<String, String> manifest) throws BundleException {
- BaseStorageHook.loadManifest(bundleData, manifest);
- }
-
- @SuppressWarnings("deprecation")
- static void loadManifest(BaseData target, Dictionary<String, String> manifest) throws BundleException {
- try {
- target.setVersion(Version.parseVersion(manifest.get(Constants.BUNDLE_VERSION)));
- } catch (IllegalArgumentException e) {
- target.setVersion(new InvalidVersion(manifest.get(Constants.BUNDLE_VERSION)));
- }
- ManifestElement[] bsnHeader = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, manifest.get(Constants.BUNDLE_SYMBOLICNAME));
- int bundleType = 0;
- if (bsnHeader != null) {
- target.setSymbolicName(bsnHeader[0].getValue());
- String singleton = bsnHeader[0].getDirective(Constants.SINGLETON_DIRECTIVE);
- if (singleton == null)
- singleton = bsnHeader[0].getAttribute(Constants.SINGLETON_DIRECTIVE);
- if ("true".equals(singleton)) //$NON-NLS-1$
- bundleType |= BundleData.TYPE_SINGLETON;
- }
- // check that the classpath is valid
- String classpath = manifest.get(Constants.BUNDLE_CLASSPATH);
- ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, classpath);
- target.setClassPathString(classpath);
- target.setActivator(manifest.get(Constants.BUNDLE_ACTIVATOR));
- String host = manifest.get(Constants.FRAGMENT_HOST);
- if (host != null) {
- bundleType |= BundleData.TYPE_FRAGMENT;
- ManifestElement[] hostElement = ManifestElement.parseHeader(Constants.FRAGMENT_HOST, host);
- if (Constants.getInternalSymbolicName().equals(hostElement[0].getValue()) || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(hostElement[0].getValue())) {
- String extensionType = hostElement[0].getDirective("extension"); //$NON-NLS-1$
- if (extensionType == null || extensionType.equals("framework")) //$NON-NLS-1$
- bundleType |= BundleData.TYPE_FRAMEWORK_EXTENSION;
- else if (extensionType.equals("bootclasspath")) //$NON-NLS-1$
- bundleType |= BundleData.TYPE_BOOTCLASSPATH_EXTENSION;
- else if (extensionType.equals("extclasspath")) //$NON-NLS-1$
- bundleType |= BundleData.TYPE_EXTCLASSPATH_EXTENSION;
- }
- } else {
- String composite = manifest.get(COMPOSITE_HEADER);
- if (composite != null) {
- if (COMPOSITE_BUNDLE.equals(composite))
- bundleType |= BundleData.TYPE_COMPOSITEBUNDLE;
- else
- bundleType |= BundleData.TYPE_SURROGATEBUNDLE;
- }
- }
- target.setType(bundleType);
- target.setExecutionEnvironment(manifest.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT));
- target.setDynamicImports(manifest.get(Constants.DYNAMICIMPORT_PACKAGE));
- }
-
- public StorageHook load(BaseData target, DataInputStream in) throws IOException {
- target.setLocation(AdaptorUtil.readString(in, false));
- target.setSymbolicName(AdaptorUtil.readString(in, false));
- target.setVersion(AdaptorUtil.loadVersion(in));
- target.setActivator(AdaptorUtil.readString(in, false));
- target.setClassPathString(AdaptorUtil.readString(in, false));
- target.setExecutionEnvironment(AdaptorUtil.readString(in, false));
- target.setDynamicImports(AdaptorUtil.readString(in, false));
- target.setStartLevel(in.readInt());
- target.setStatus(in.readInt());
- target.setType(in.readInt());
- target.setLastModified(in.readLong());
- target.setDirty(false); // make sure to reset the dirty bit;
-
- BaseStorageHook storageHook = new BaseStorageHook(storage);
- storageHook.bundleData = target;
- storageHook.generation = in.readInt();
- storageHook.reference = in.readBoolean();
- storageHook.setFileName(getAbsolute(storageHook.reference, AdaptorUtil.readString(in, false)));
- int nativePathCount = in.readInt();
- storageHook.nativePaths = nativePathCount > 0 ? new String[nativePathCount] : null;
- for (int i = 0; i < nativePathCount; i++)
- storageHook.nativePaths[i] = in.readUTF();
- return storageHook;
- }
-
- private String getAbsolute(boolean isReference, String path) {
- if (!isReference)
- return path;
- // fileName for bundles installed with reference URLs is stored relative to the install location
- File storedPath = new File(path);
- if (!storedPath.isAbsolute())
- // make sure it has the absolute location instead
- return new FilePath(storage.getInstallPath() + path).toString();
- return path;
- }
-
- public void save(DataOutputStream out) throws IOException {
- if (bundleData == null)
- throw new IllegalStateException();
- AdaptorUtil.writeStringOrNull(out, bundleData.getLocation());
- AdaptorUtil.writeStringOrNull(out, bundleData.getSymbolicName());
- AdaptorUtil.writeStringOrNull(out, bundleData.getVersion().toString());
- AdaptorUtil.writeStringOrNull(out, bundleData.getActivator());
- AdaptorUtil.writeStringOrNull(out, bundleData.getClassPathString());
- AdaptorUtil.writeStringOrNull(out, bundleData.getExecutionEnvironment());
- AdaptorUtil.writeStringOrNull(out, bundleData.getDynamicImports());
- StorageHook[] hooks = bundleData.getStorageHooks();
- boolean forgetStartLevel = false;
- for (int i = 0; i < hooks.length && !forgetStartLevel; i++)
- forgetStartLevel = hooks[i].forgetStartLevelChange(bundleData.getStartLevel());
- out.writeInt(!forgetStartLevel ? bundleData.getStartLevel() : 1);
- boolean forgetStatus = false;
- // see if we should forget the persistently started flag
- for (int i = 0; i < hooks.length && !forgetStatus; i++)
- forgetStatus = hooks[i].forgetStatusChange(bundleData.getStatus());
- out.writeInt(!forgetStatus ? bundleData.getStatus() : (~Constants.BUNDLE_STARTED) & bundleData.getStatus());
- out.writeInt(bundleData.getType());
- out.writeLong(bundleData.getLastModified());
-
- out.writeInt(getGeneration());
- out.writeBoolean(isReference());
- String storedFileName = isReference() ? new FilePath(storage.getInstallPath()).makeRelative(new FilePath(getFileName())) : getFileName();
- AdaptorUtil.writeStringOrNull(out, storedFileName);
- if (nativePaths == null)
- out.writeInt(0);
- else {
- out.writeInt(nativePaths.length);
- for (int i = 0; i < nativePaths.length; i++)
- out.writeUTF(nativePaths[i]);
- }
-
- }
-
- public int getKeyHashCode() {
- return HASHCODE;
- }
-
- public boolean compare(KeyedElement other) {
- return other.getKey() == KEY;
- }
-
- public Object getKey() {
- return KEY;
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public int getGeneration() {
- return generation;
- }
-
- public String[] getNativePaths() {
- return nativePaths;
- }
-
- public void installNativePaths(String[] installPaths) throws BundleException {
- validateNativePaths(installPaths);
- this.nativePaths = installPaths;
- }
-
- public void validateNativePaths(String[] paths) throws BundleException {
- for (int i = 0; i < paths.length; i++) {
- if (paths[i].startsWith(EXTERNAL_LIB_PREFIX)) {
- String path = substituteVars(paths[i].substring(EXTERNAL_LIB_PREFIX.length()));
- File nativeFile = new File(path);
- if (!nativeFile.exists())
- throw new BundleException(NLS.bind(AdaptorMsg.BUNDLE_NATIVECODE_EXCEPTION, nativeFile.getAbsolutePath()), BundleException.NATIVECODE_ERROR);
- continue; // continue to next path
- }
- // ensure the file exists in the bundle; it will get extracted later on demand
- BundleEntry nativeEntry = bundleData.getBundleFile().getEntry(paths[i]);
- if (nativeEntry == null)
- throw new BundleException(NLS.bind(AdaptorMsg.BUNDLE_NATIVECODE_EXCEPTION, paths[i]), BundleException.NATIVECODE_ERROR);
- }
- }
-
- public boolean isReference() {
- return reference;
- }
-
- public File getBundleStore() {
- if (bundleStore == null)
- bundleStore = new File(storage.getBundleStoreRoot(), String.valueOf(bundleData.getBundleID()));
- return bundleStore;
- }
-
- public File getDataFile(String path) {
- // lazily initialize dirData to prevent early access to configuration location
- if (dataStore == null)
- dataStore = new File(getBundleStore(), BaseStorage.DATA_DIR_NAME);
- if (path != null && !dataStore.exists() && (storage.isReadOnly() || !dataStore.mkdirs()))
- if (Debug.DEBUG_GENERAL)
- Debug.println("Unable to create bundle data directory: " + dataStore.getPath()); //$NON-NLS-1$
- return path == null ? dataStore : new File(dataStore, path);
- }
-
- void delete(boolean postpone, int type) throws IOException {
- File delete = null;
- switch (type) {
- case DEL_GENERATION :
- delete = getGenerationDir();
- break;
- case DEL_BUNDLE_STORE :
- delete = getBundleStore();
- break;
- }
- if (delete != null && delete.exists() && (postpone || !AdaptorUtil.rm(delete))) {
- /* create .delete */
- FileOutputStream out = new FileOutputStream(new File(delete, BaseStorage.DELETE_FLAG));
- out.close();
- }
- }
-
- File getGenerationDir() {
- return new File(getBundleStore(), String.valueOf(getGeneration()));
- }
-
- File getParentGenerationDir() {
- Location parentConfiguration = null;
- Location currentConfiguration = LocationManager.getConfigurationLocation();
- if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null)
- return new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + '/' + LocationManager.BUNDLES_DIR + '/' + bundleData.getBundleID() + '/' + getGeneration());
- return null;
- }
-
- File createGenerationDir() {
- File generationDir = getGenerationDir();
- if (!generationDir.exists() && (storage.isReadOnly() || !generationDir.mkdirs()))
- if (Debug.DEBUG_GENERAL)
- Debug.println("Unable to create bundle generation directory: " + generationDir.getPath()); //$NON-NLS-1$
- return generationDir;
- }
-
- public void setReference(boolean reference) {
- this.reference = reference;
- }
-
- public void setFileName(String fileName) {
- this.fileName = fileName;
- // This is only done for PDE source lookup (bug 126517)
- this.bundleData.setFileName(fileName);
- }
-
- public void copy(StorageHook storageHook) {
- if (!(storageHook instanceof BaseStorageHook))
- throw new IllegalArgumentException();
- BaseStorageHook hook = (BaseStorageHook) storageHook;
- bundleStore = hook.bundleStore;
- dataStore = hook.dataStore;
- generation = hook.generation + 1;
- // fileName and reference will be set by update
- }
-
- public void validate() throws IllegalArgumentException {
- // do nothing
- }
-
- /**
- * @throws BundleException
- */
- public Dictionary<String, String> getManifest(boolean firstLoad) throws BundleException {
- // do nothing
- return null;
- }
-
- public boolean forgetStatusChange(int status) {
- // do nothing
- return false;
- }
-
- public boolean forgetStartLevelChange(int startlevel) {
- // do nothing
- return false;
- }
-
- public void initialize(BaseAdaptor adaptor) {
- // do nothing
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStart(BundleContext context) throws BundleException {
- // do nothing
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStop(BundleContext context) throws BundleException {
- // do nothing
- }
-
- public void frameworkStopping(BundleContext context) {
- // do nothing
- }
-
- public void addProperties(Properties properties) {
- // do nothing
- }
-
- public URLConnection mapLocationToURLConnection(String location) throws IOException {
- // take into account that initial@ is special (bug 268563)
- if (location.startsWith("initial@")) { //$NON-NLS-1$
- location = location.substring(8);
- return new URL(location).openConnection();
- }
- // see if this is an existing location
- Bundle[] bundles = storage.getAdaptor().getContext().getBundles();
- AbstractBundle bundle = null;
- for (int i = 0; i < bundles.length && bundle == null; i++)
- if (location.equals(bundles[i].getLocation()))
- bundle = (AbstractBundle) bundles[i];
- if (bundle == null)
- return null;
- BaseData data = (BaseData) bundle.getBundleData();
- BaseStorageHook hook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- return hook.isReference() ? new URL("reference:file:" + hook.getFileName()).openConnection() : null; //$NON-NLS-1$
- }
-
- public void handleRuntimeError(Throwable error) {
- // do nothing
- }
-
- public FrameworkLog createFrameworkLog() {
- // do nothing
- return null;
- }
-
- public BaseStorage getStorage() {
- return storage;
- }
-
- public static String substituteVars(String path) {
- StringBuffer buf = new StringBuffer(path.length());
- StringTokenizer st = new StringTokenizer(path, VARIABLE_DELIM_STRING, true);
- boolean varStarted = false; // indicates we are processing a var subtitute
- String var = null; // the current var key
- while (st.hasMoreElements()) {
- String tok = st.nextToken();
- if (VARIABLE_DELIM_STRING.equals(tok)) {
- if (!varStarted) {
- varStarted = true; // we found the start of a var
- var = ""; //$NON-NLS-1$
- } else {
- // we have found the end of a var
- String prop = null;
- // get the value of the var from system properties
- if (var != null && var.length() > 0)
- prop = FrameworkProperties.getProperty(var);
- if (prop == null) {
- try {
- // try using the System.getenv method if it exists (bug 126921)
- Method getenv = System.class.getMethod("getenv", new Class[] {String.class}); //$NON-NLS-1$
- prop = (String) getenv.invoke(null, new Object[] {var});
- } catch (Throwable t) {
- // do nothing;
- // on 1.4 VMs this throws an error
- // on J2ME this method does not exist
- }
- }
- if (prop != null)
- // found a value; use it
- buf.append(prop);
- else
- // could not find a value append the var name w/o delims
- buf.append(var == null ? "" : var); //$NON-NLS-1$
- varStarted = false;
- var = null;
- }
- } else {
- if (!varStarted)
- buf.append(tok); // the token is not part of a var
- else
- var = tok; // the token is the var key; save the key to process when we find the end token
- }
- }
- if (var != null)
- // found a case of $var at the end of the path with no trailing $; just append it as is.
- buf.append(VARIABLE_DELIM_CHAR).append(var);
- return buf.toString();
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleInstall.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleInstall.java
deleted file mode 100644
index 82a8d13ec..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleInstall.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Dictionary;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.BundleOperation;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.ReferenceInputStream;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class BundleInstall implements BundleOperation {
- private BaseData data;
- private URLConnection source;
- private BaseStorage storage;
-
- public BundleInstall(BaseData data, URLConnection source, BaseStorage storage) {
- this.data = data;
- this.source = source;
- this.storage = storage;
- }
-
- /**
- * Begin the operation on the bundle (install, update, uninstall).
- *
- * @return BundleData object for the target bundle.
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public BundleData begin() throws BundleException {
- try {
- InputStream in = null;
- try {
- data.setLastModified(System.currentTimeMillis());
- data.setStartLevel(storage.getInitialBundleStartLevel());
- StorageHook[] storageHooks = data.getAdaptor().getHookRegistry().getStorageHooks();
- StorageHook[] instanceHooks = new StorageHook[storageHooks.length];
- for (int i = 0; i < storageHooks.length; i++)
- instanceHooks[i] = storageHooks[i].create(data);
- data.setStorageHooks(instanceHooks);
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- in = source.getInputStream();
- URL sourceURL = source.getURL();
- String protocol = sourceURL == null ? null : sourceURL.getProtocol();
- if (in instanceof ReferenceInputStream) {
- URL reference = ((ReferenceInputStream) in).getReference();
- if (!"file".equals(reference.getProtocol())) //$NON-NLS-1$
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, reference));
- storageHook.setReference(true);
- storageHook.setFileName(reference.getPath());
- } else {
- File genDir = storageHook.createGenerationDir();
- if (!genDir.exists())
- throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, genDir.getPath()));
- storageHook.setReference(false);
- storageHook.setFileName(BaseStorage.BUNDLEFILE_NAME);
- File outFile = new File(genDir, storageHook.getFileName());
- if ("file".equals(protocol)) { //$NON-NLS-1$
- File inFile = new File(source.getURL().getPath());
- if (inFile.isDirectory())
- AdaptorUtil.copyDir(inFile, outFile);
- else
- AdaptorUtil.readFile(in, outFile);
- } else {
- AdaptorUtil.readFile(in, outFile);
- }
- }
- Dictionary<String, String> manifest = storage.loadManifest(data, true);
- for (int i = 0; i < instanceHooks.length; i++)
- instanceHooks[i].initialize(manifest);
- } finally {
- try {
- if (in != null)
- in.close();
- } catch (IOException e) {
- // do nothing
- }
- }
- } catch (IOException ioe) {
- throw new BundleException(AdaptorMsg.BUNDLE_READ_EXCEPTION, BundleException.READ_ERROR, ioe);
- }
-
- return (data);
- }
-
- public void undo() {
- if (data != null) {
- try {
- data.close();
- } catch (IOException e) {
- if (Debug.DEBUG_GENERAL)
- Debug.println("Unable to close " + data + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
- if (data != null) {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- try {
- if (storageHook != null)
- storageHook.delete(false, BaseStorageHook.DEL_BUNDLE_STORE);
- } catch (IOException e) {
- data.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
- }
- }
- }
-
- public void commit(boolean postpone) throws BundleException {
- storage.processExtension(data, BaseStorage.EXTENSION_INSTALLED);
- storage.updateState(data, BundleEvent.INSTALLED);
- try {
- data.save();
- } catch (IOException e) {
- throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
- }
-
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUninstall.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUninstall.java
deleted file mode 100644
index 83e1351aa..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUninstall.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.IOException;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.BundleOperation;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleException;
-
-public class BundleUninstall implements BundleOperation {
- private BaseData data;
- private BaseStorage storage;
-
- public BundleUninstall(BaseData data, BaseStorage storage) {
- this.data = data;
- this.storage = storage;
- }
-
- /**
- * Perform the change to persistent storage.
- *
- * @return Bundle object for the target bundle.
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public BundleData begin() throws BundleException {
- return data;
- }
-
- /**
- * Commit the change to persistent storage.
- *
- * @param postpone If true, the bundle's persistent
- * storage cannot be immediately reclaimed.
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public void commit(boolean postpone) throws BundleException {
- BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- try {
- storageHook.delete(postpone, BaseStorageHook.DEL_BUNDLE_STORE);
- } catch (IOException e) {
- // nothing we can do
- }
- storage.processExtension(data, BaseStorage.EXTENSION_UNINSTALLED);
- data.setLastModified(System.currentTimeMillis());
- storage.updateState(data, BundleEvent.UNINSTALLED);
- data.setDirty(true);
- try {
- data.save();
- } catch (IOException e) {
- throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
- }
- }
-
- /**
- * Undo the change to persistent storage.
- *
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public void undo() throws BundleException {
- // do nothing
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUpdate.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUpdate.java
deleted file mode 100644
index 732f25214..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/BundleUpdate.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Dictionary;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.BundleOperation;
-import org.eclipse.osgi.framework.internal.core.ReferenceInputStream;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class BundleUpdate implements BundleOperation {
- private BaseData data;
- private BaseData newData;
- private URLConnection source;
- private BaseStorage storage;
-
- public BundleUpdate(BaseData data, URLConnection source, BaseStorage storage) {
- this.data = data;
- this.source = source;
- this.storage = storage;
- }
-
- /**
- * Perform the change to persistent storage.
- *
- * @return Bundle object for the target bundle.
- * @throws BundleException if an error occurs
- */
- public BundleData begin() throws BundleException {
- try {
- newData = storage.createBaseData(data.getBundleID(), data.getLocation());
- newData.setLastModified(System.currentTimeMillis());
- newData.setStartLevel(data.getStartLevel());
- newData.setStatus(data.getStatus());
- // load the storage hooks into the new data
- StorageHook[] storageHooks = data.getAdaptor().getHookRegistry().getStorageHooks();
- StorageHook[] instanceHooks = new StorageHook[storageHooks.length];
- for (int i = 0; i < storageHooks.length; i++) {
- instanceHooks[i] = storageHooks[i].create(newData);
- instanceHooks[i].copy(data.getStorageHook((String) instanceHooks[i].getKey()));
- }
- newData.setStorageHooks(instanceHooks);
- // get the new eclipse storage hooks
- BaseStorageHook newStorageHook = (BaseStorageHook) newData.getStorageHook(BaseStorageHook.KEY);
- InputStream in = source.getInputStream();
- URL sourceURL = source.getURL();
- String protocol = sourceURL == null ? null : sourceURL.getProtocol();
- try {
- if (in instanceof ReferenceInputStream) {
- URL reference = ((ReferenceInputStream) in).getReference();
- if (!"file".equals(reference.getProtocol())) //$NON-NLS-1$
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, reference));
- // check to make sure we are not just trying to update to the same
- // directory reference. This would be a no-op.
- String path = reference.getPath();
- newStorageHook.setReference(true);
- newStorageHook.setFileName(path);
- } else {
- File genDir = newStorageHook.createGenerationDir();
- if (!genDir.exists())
- throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, genDir.getPath()));
- newStorageHook.setReference(false);
- newStorageHook.setFileName(BaseStorage.BUNDLEFILE_NAME);
- File outFile = new File(genDir, newStorageHook.getFileName());
- if ("file".equals(protocol)) { //$NON-NLS-1$
- File inFile = new File(source.getURL().getPath());
- if (inFile.isDirectory()) {
- AdaptorUtil.copyDir(inFile, outFile);
- } else {
- AdaptorUtil.readFile(in, outFile);
- }
- } else {
- AdaptorUtil.readFile(in, outFile);
- }
- }
- Dictionary<String, String> manifest = storage.loadManifest(newData, true);
- for (int i = 0; i < instanceHooks.length; i++)
- instanceHooks[i].initialize(manifest);
- } finally {
- try {
- if (in != null)
- in.close();
- } catch (IOException ee) {
- // nothing to do here
- }
- }
- } catch (IOException e) {
- throw new BundleException(AdaptorMsg.BUNDLE_READ_EXCEPTION, BundleException.READ_ERROR, e);
- }
-
- return (newData);
- }
-
- /**
- * Commit the change to persistent storage.
- *
- * @param postpone If true, the bundle's persistent
- * storage cannot be immediately reclaimed.
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
-
- public void commit(boolean postpone) throws BundleException {
- storage.processExtension(data, BaseStorage.EXTENSION_UNINSTALLED); // remove the old extension
- storage.processExtension(newData, BaseStorage.EXTENSION_UPDATED); // update to the new one
- newData.setLastModified(System.currentTimeMillis()); // save the last modified
- storage.updateState(newData, BundleEvent.UPDATED);
- try {
- newData.save();
- } catch (IOException e) {
- throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
- }
- BaseStorageHook oldStorageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
- try {
- oldStorageHook.delete(postpone, BaseStorageHook.DEL_GENERATION);
- } catch (IOException e) {
- data.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
- }
- }
-
- /**
- * Undo the change to persistent storage.
- *
- * @throws BundleException If a failure occured modifiying peristent storage.
- */
- public void undo() throws BundleException {
- if (newData != null) {
- BaseStorageHook newStorageHook = (BaseStorageHook) newData.getStorageHook(BaseStorageHook.KEY);
- try {
- if (newStorageHook != null)
- newStorageHook.delete(false, BaseStorageHook.DEL_GENERATION);
- } catch (IOException e) {
- data.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
- }
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassPathHelper.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassPathHelper.java
deleted file mode 100644
index 274c07666..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/DevClassPathHelper.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Dictionary;
-import java.util.Properties;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.util.ManifestElement;
-
-/**
- * This class provides helper methods to support developement classpaths.
- * @since 3.1
- */
-public final class DevClassPathHelper {
- static final private String FILE_PROTOCOL = "file"; //$NON-NLS-1$
- static final private boolean inDevelopmentMode;
- static final private File devLocation;
- static private String[] devDefaultClasspath;
- static private Dictionary<String, String> devProperties = null;
- // timestamp for the dev.properties file
- static private long lastModified = 0;
-
- static {
- String osgiDev = FrameworkProperties.getProperty("osgi.dev"); //$NON-NLS-1$
- File f = null;
- boolean devMode = false;
- if (osgiDev != null) {
- try {
- devMode = true;
- URL location = new URL(osgiDev);
-
- if (FILE_PROTOCOL.equals(location.getProtocol())) {
- f = new File(location.getFile());
- lastModified = f.lastModified();
- }
-
- // Check the osgi.dev property to see if dev classpath entries have been defined.
- try {
- load(location.openStream());
- devMode = true;
- } catch (IOException e) {
- // TODO consider logging
- }
-
- } catch (MalformedURLException e) {
- devDefaultClasspath = getArrayFromList(osgiDev);
- }
- }
- inDevelopmentMode = devMode;
- devLocation = f;
- }
-
- /*
- * Updates the dev classpath if the file containing the entries have changed
- */
- private static void updateDevProperties() {
- if (devLocation == null)
- return;
- if (devLocation.lastModified() == lastModified)
- return;
-
- try {
- load(new FileInputStream(devLocation));
- } catch (FileNotFoundException e) {
- return;
- }
- lastModified = devLocation.lastModified();
- }
-
- private static String[] getDevClassPath(String id, Dictionary<String, String> properties, String[] defaultClasspath) {
- String[] result = null;
- if (id != null && properties != null) {
- String entry = properties.get(id);
- if (entry != null)
- result = getArrayFromList(entry);
- }
- if (result == null)
- result = defaultClasspath;
- return result;
- }
-
- /**
- * Returns a list of classpath elements for the specified bundle symbolic name.
- * @param id a bundle symbolic name to get the development classpath for
- * @param properties a Dictionary of properties to use or <code>null</code> if
- * the default develoment classpath properties should be used
- * @return a list of development classpath elements
- */
- public static String[] getDevClassPath(String id, Dictionary<String, String> properties) {
- if (properties == null) {
- synchronized (DevClassPathHelper.class) {
- updateDevProperties();
- return getDevClassPath(id, devProperties, devDefaultClasspath);
- }
- }
- return getDevClassPath(id, properties, getArrayFromList(properties.get("*"))); //$NON-NLS-1$
- }
-
- /**
- * Returns a list of classpath elements for the specified bundle symbolic name.
- * @param id a bundle symbolic name to get the development classpath for
- * @return a list of development classpath elements
- */
- public static String[] getDevClassPath(String id) {
- return getDevClassPath(id, null);
- }
-
- /**
- * Returns the result of converting a list of comma-separated tokens into an array
- *
- * @return the array of string tokens
- * @param prop the initial comma-separated string
- */
- public static String[] getArrayFromList(String prop) {
- return ManifestElement.getArrayFromList(prop, ","); //$NON-NLS-1$
- }
-
- /**
- * Indicates the development mode.
- * @return true if in development mode; false otherwise
- */
- public static boolean inDevelopmentMode() {
- return inDevelopmentMode;
- }
-
- /*
- * Load the given input stream into a dictionary
- */
- private static void load(InputStream input) {
- Properties props = new Properties();
- try {
- props.load(input);
- } catch (IOException e) {
- // TODO consider logging here
- } finally {
- if (input != null)
- try {
- input.close();
- } catch (IOException e) {
- // tried our best
- }
- }
- @SuppressWarnings({"unchecked", "rawtypes"})
- Dictionary<String, String> result = (Dictionary) props;
- devProperties = result;
- if (devProperties != null)
- devDefaultClasspath = getArrayFromList(devProperties.get("*")); //$NON-NLS-1$
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/InvalidVersion.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/InvalidVersion.java
deleted file mode 100644
index 1dea537a7..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/InvalidVersion.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import org.osgi.framework.Version;
-
-/**
- * This class is used to hold invalid version strings. This is used to support
- * OSGi R3 bundles which could have an invalid Bundle-Version header. An
- * InvalidVersion always has a value of 0.0.0.
- */
-public class InvalidVersion extends Version {
- private String invalidVersion;
-
- /**
- * Constructs a BadVersion using the specified invalid version string.
- * @param badVersion an invalid version string.
- */
- public InvalidVersion(String badVersion) {
- super(0, 0, 0, null);
- this.invalidVersion = badVersion;
- }
-
- /**
- * Returns the invalid version string.
- * @return the invalid version string.
- */
- public String getInvalidVersion() {
- return invalidVersion;
- }
-
- public String toString() {
- return invalidVersion;
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/StateManager.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/StateManager.java
deleted file mode 100644
index 167385a95..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/StateManager.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Rob Harrop - SpringSource Inc. (bug 247522)
- *******************************************************************************/
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.File;
-import java.io.IOException;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.internal.resolver.*;
-import org.eclipse.osgi.service.resolver.*;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-
-/**
- * The StateManager manages the system state for the framework. It also provides the implementation
- * to the PlatformAdmin service.
- * <p>
- * Clients may extend this class.
- * </p>
- * @since 3.1
- */
-public class StateManager implements PlatformAdmin, Runnable {
- /**
- * General debug flag
- */
- public static boolean DEBUG = false;
- /**
- * Reader debug flag
- */
- public static boolean DEBUG_READER = false;
- /**
- * PlatformAdmin debug flag
- */
- public static boolean DEBUG_PLATFORM_ADMIN = false;
- /**
- * PlatformAdmin resolver debug flag
- */
- public static boolean DEBUG_PLATFORM_ADMIN_RESOLVER = false;
- /**
- * Monitor PlatformAdmin debug flag
- */
- public static boolean MONITOR_PLATFORM_ADMIN = false;
- /**
- * System property used to disable lazy state loading
- */
- public static String PROP_NO_LAZY_LOADING = "osgi.noLazyStateLoading"; //$NON-NLS-1$
- /**
- * System property used to specify to amount time before lazy data can be flushed from memory
- */
- public static String PROP_LAZY_UNLOADING_TIME = "osgi.lazyStateUnloadingTime"; //$NON-NLS-1$
- private long expireTime = 300000; // default to five minutes
- private long readStartupTime;
- private StateImpl systemState;
- private final StateObjectFactoryImpl factory;
- private long lastTimeStamp;
- private boolean cachedState = false;
- private final File stateFile;
- private final File lazyFile;
- private final long expectedTimeStamp;
- private final BundleContext context;
- private Thread dataManagerThread;
-
- /**
- * Constructs a StateManager using the specified files and context
- * @param stateFile a file with the data required to persist in memory
- * @param lazyFile a file with the data that may be lazy loaded and can be flushed from memory
- * @param context the bundle context of the system bundle
- */
- public StateManager(File stateFile, File lazyFile, BundleContext context) {
- // a negative timestamp means no timestamp checking
- this(stateFile, lazyFile, context, -1);
- }
-
- /**
- * Constructs a StateManager using the specified files and context
- * @param stateFile a file with the data required to persist in memory
- * @param lazyFile a file with the data that may be lazy loaded and can be flushed from memory
- * @param context the bundle context of the system bundle
- * @param expectedTimeStamp the expected timestamp of the persisted system state. A negative
- * value indicates that no timestamp checking is done
- */
- public StateManager(File stateFile, File lazyFile, BundleContext context, long expectedTimeStamp) {
- this.stateFile = stateFile;
- this.lazyFile = lazyFile;
- this.context = context;
- this.expectedTimeStamp = expectedTimeStamp;
- factory = new StateObjectFactoryImpl();
- }
-
- /**
- * Shutsdown the state manager. If the timestamp of the system state has changed
- * @param saveStateFile
- * @param saveLazyFile
- * @throws IOException
- */
- public void shutdown(File saveStateFile, File saveLazyFile) throws IOException {
- writeState(systemState, saveStateFile, saveLazyFile);
- stopDataManager();
- }
-
- /**
- * Update the given target files with the state data in memory.
- * @param updateStateFile
- * @param updateLazyFile
- * @throws IOException
- */
- public void update(File updateStateFile, File updateLazyFile) throws IOException {
- writeState(systemState, updateStateFile, updateLazyFile);
- // Need to use the timestamp of the original state here
- lastTimeStamp = systemState.getTimeStamp();
- // TODO consider updating the state files for lazy loading
- }
-
- private void internalReadSystemState() {
- if (stateFile == null || !stateFile.isFile())
- return;
- if (DEBUG_READER)
- readStartupTime = System.currentTimeMillis();
- try {
- boolean lazyLoad = !Boolean.valueOf(FrameworkProperties.getProperty(PROP_NO_LAZY_LOADING)).booleanValue();
- systemState = factory.readSystemState(context, stateFile, lazyFile, lazyLoad, expectedTimeStamp);
- // problems in the cache (corrupted/stale), don't create a state object
- if (systemState == null || !initializeSystemState()) {
- systemState = null;
- return;
- }
- cachedState = true;
- try {
- expireTime = Long.parseLong(FrameworkProperties.getProperty(PROP_LAZY_UNLOADING_TIME, Long.toString(expireTime)));
- } catch (NumberFormatException nfe) {
- // default to not expire
- expireTime = 0;
- }
- if (lazyLoad && expireTime > 0)
- startDataManager();
- } catch (IOException ioe) {
- // TODO: how do we log this?
- ioe.printStackTrace();
- } finally {
- if (DEBUG_READER)
- System.out.println("Time to read state: " + (System.currentTimeMillis() - readStartupTime)); //$NON-NLS-1$
- }
- }
-
- private synchronized void startDataManager() {
- if (dataManagerThread != null)
- return;
- dataManagerThread = new Thread(this, "State Data Manager"); //$NON-NLS-1$
- dataManagerThread.setDaemon(true);
- dataManagerThread.start();
- }
-
- /**
- * Stops the active data manager thread which is used to unload unused
- * state objects from memory.
- */
- public synchronized void stopDataManager() {
- if (dataManagerThread == null)
- return;
- dataManagerThread.interrupt();
- dataManagerThread = null;
- }
-
- private void writeState(StateImpl state, File saveStateFile, File saveLazyFile) throws IOException {
- if (state == null)
- return;
- if (cachedState && !saveNeeded())
- return;
- state.fullyLoad(); // make sure we are fully loaded before saving
- factory.writeState(state, saveStateFile, saveLazyFile);
- }
-
- private boolean initializeSystemState() {
- systemState.setResolver(createResolver(System.getSecurityManager() != null));
- lastTimeStamp = systemState.getTimeStamp();
- return !systemState.setPlatformProperties(FrameworkProperties.getProperties());
- }
-
- /**
- * Creates a new State used by the system. If the system State already
- * exists then a new system State is not created.
- * @return the State used by the system.
- */
- public synchronized State createSystemState() {
- if (systemState == null) {
- systemState = factory.createSystemState(context);
- initializeSystemState();
- }
- return systemState;
- }
-
- /**
- * Reads the State used by the system. If the system State already
- * exists then the system State is not read from a cache. If the State could
- * not be read from a cache then <code>null</code> is returned.
- * @return the State used by the system or <code>null</code> if the State
- * could not be read from a cache.
- */
- public synchronized State readSystemState() {
- if (systemState == null)
- internalReadSystemState();
- return systemState;
- }
-
- /**
- * Returns the State used by the system. If the system State does
- * not exist then <code>null</code> is returned.
- * @return the State used by the system or <code>null</code> if one
- * does not exist.
- */
- public State getSystemState() {
- return systemState;
- }
-
- /**
- * Returns the cached time stamp of the system State. This value is the
- * original time stamp of the system state when it was created or read from
- * a cache.
- * @see State#getTimeStamp()
- * @return the cached time stamp of the system State
- */
- public long getCachedTimeStamp() {
- return lastTimeStamp;
- }
-
- public boolean saveNeeded() {
- return systemState.getTimeStamp() != lastTimeStamp || systemState.dynamicCacheChanged();
- }
-
- /**
- * @see PlatformAdmin#getState(boolean)
- */
- public State getState(boolean mutable) {
- return mutable ? factory.createState(systemState) : new ReadOnlyState(systemState);
- }
-
- /**
- * @see PlatformAdmin#getState()
- */
- public State getState() {
- return getState(true);
- }
-
- /**
- * @see PlatformAdmin#getFactory()
- */
- public StateObjectFactory getFactory() {
- return factory;
- }
-
- /**
- * @throws BundleException
- * @see PlatformAdmin#commit(State)
- */
- public synchronized void commit(State state) throws BundleException {
- throw new IllegalArgumentException("PlatformAdmin.commit() not supported"); //$NON-NLS-1$
- }
-
- /**
- * @see PlatformAdmin#getResolver()
- * @deprecated
- */
- public Resolver getResolver() {
- return createResolver(false);
- }
-
- /**
- * @see PlatformAdmin#createResolver()
- */
- public Resolver createResolver() {
- return createResolver(false);
- }
-
- private Resolver createResolver(boolean checkPermissions) {
- return new org.eclipse.osgi.internal.module.ResolverImpl(checkPermissions);
- }
-
- /**
- * @see PlatformAdmin#getStateHelper()
- */
- public StateHelper getStateHelper() {
- return StateHelperImpl.getInstance();
- }
-
- public void run() {
- long timeStamp = lastTimeStamp; // cache the original timestamp incase of updates
- while (true) {
- try {
- Thread.sleep(expireTime);
- } catch (InterruptedException e) {
- return;
- }
- if (systemState != null)
- synchronized (systemState) {
- if (!systemState.unloadLazyData(timeStamp))
- return;
- }
- }
- }
-
- public void addDisabledInfo(DisabledInfo disabledInfo) {
- if (systemState == null)
- throw new IllegalStateException(); // should never happen
- systemState.addDisabledInfo(disabledInfo);
- }
-
- public void removeDisabledInfo(DisabledInfo disabledInfo) {
- if (systemState == null)
- throw new IllegalStateException(); // should never happen
- systemState.removeDisabledInfo(disabledInfo);
- }
-}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/SystemBundleData.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/SystemBundleData.java
deleted file mode 100644
index 9604b59ed..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/SystemBundleData.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.internal.baseadaptor;
-
-import java.io.*;
-import java.net.URL;
-import java.util.Enumeration;
-import org.eclipse.osgi.baseadaptor.BaseAdaptor;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.framework.adaptor.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.util.Headers;
-import org.osgi.framework.BundleException;
-
-public class SystemBundleData extends BaseData {
- private static final String OSGI_FRAMEWORK = "osgi.framework"; //$NON-NLS-1$
-
- public SystemBundleData(BaseAdaptor adaptor) throws BundleException {
- super(0, adaptor);
- File osgiBase = getOsgiBase();
- createBundleFile(osgiBase);
- manifest = createManifest(osgiBase);
- setMetaData();
- setLastModified(System.currentTimeMillis()); // just set the lastModified to the current time
- StorageHook[] hooks = adaptor.getHookRegistry().getStorageHooks();
- StorageHook[] instanceHooks = new StorageHook[hooks.length];
- for (int i = 0; i < hooks.length; i++)
- instanceHooks[i] = hooks[i].create(this);
- setStorageHooks(instanceHooks);
- }
-
- private File getOsgiBase() {
- String frameworkLocation = FrameworkProperties.getProperty(SystemBundleData.OSGI_FRAMEWORK);
- if (frameworkLocation != null && frameworkLocation.startsWith("file:")) //$NON-NLS-1$
- // TODO assumes the location is a file URL
- return new File(frameworkLocation.substring(5));
- try {
- URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
- // assumes file URL
- if ("file".equals(url.getProtocol())) //$NON-NLS-1$
- return new File(url.getPath());
- } catch (Throwable e) {
- // do nothing
- }
- return null;
- }
-
- private Headers<String, String> createManifest(File osgiBase) throws BundleException {
- InputStream in = null;
-
- if (osgiBase != null && osgiBase.exists())
- try {
- BundleEntry entry = getBundleFile().getEntry(Constants.OSGI_BUNDLE_MANIFEST);
- if (entry != null)
- in = entry.getInputStream();
- } catch (IOException e) {
- // do nothing here. in == null
- }
-
- // If we cannot find the Manifest file from the baseBundleFile then
- // search for the manifest as a classloader resource
- // This allows an adaptor to package the SYSTEMBUNDLE.MF file in a jar.
- if (in == null)
- in = getManifestAsResource();
- if (Debug.DEBUG_GENERAL)
- if (in == null)
- Debug.println("Unable to find system bundle manifest " + Constants.OSGI_BUNDLE_MANIFEST); //$NON-NLS-1$
-
- if (in == null)
- throw new BundleException(AdaptorMsg.SYSTEMBUNDLE_MISSING_MANIFEST, BundleException.MANIFEST_ERROR);
- return Headers.parseManifest(in);
- }
-
- private InputStream getManifestAsResource() {
- URL url = getManifestURL();
- try {
- return url == null ? null : url.openStream();
- } catch (IOException e) {
- return null;
- }
- }
-
- private URL getManifestURL() {
- ClassLoader cl = getClass().getClassLoader();
- try {
- // get all manifests in your classloader delegation
- Enumeration<URL> manifests = cl != null ? cl.getResources(Constants.OSGI_BUNDLE_MANIFEST) : ClassLoader.getSystemResources(Constants.OSGI_BUNDLE_MANIFEST);
- while (manifests.hasMoreElements()) {
- URL url = manifests.nextElement();
- try {
- // check each manifest until we find one with the Eclipse-SystemBundle: true header
- Headers<String, String> headers = Headers.parseManifest(url.openStream());
- if ("true".equals(headers.get(Constants.ECLIPSE_SYSTEMBUNDLE))) //$NON-NLS-1$
- return url;
- } catch (BundleException e) {
- // ignore and continue to next URL
- }
- }
- } catch (IOException e) {
- // ignore and return null
- }
- return null;
- }
-
- private void createBundleFile(File osgiBase) {
- if (osgiBase != null)
- try {
- bundleFile = getAdaptor().createBundleFile(osgiBase, this);
- } catch (IOException e) {
- // should not happen
- }
- else
- bundleFile = new BundleFile(osgiBase) {
- public File getFile(String path, boolean nativeCode) {
- return null;
- }
-
- public BundleEntry getEntry(String path) {
- if (Constants.OSGI_BUNDLE_MANIFEST.equals(path)) {
- System.err.println("Getting system bundle manifest: " + path);
- return new BundleEntry() {
-
- public InputStream getInputStream() throws IOException {
- return getManifestURL().openStream();
- }
-
- public long getSize() {
- return 0;
- }
-
- public String getName() {
- return Constants.OSGI_BUNDLE_MANIFEST;
- }
-
- public long getTime() {
- return 0;
- }
-
- public URL getLocalURL() {
- return getManifestURL();
- }
-
- public URL getFileURL() {
- return null;
- }
- };
- }
- return null;
- }
-
- public Enumeration<String> getEntryPaths(String path) {
- return null;
- }
-
- public void close() {
- // do nothing
- }
-
- public void open() {
- // do nothing
- }
-
- public boolean containsDir(String dir) {
- return false;
- }
- };
- }
-
- private void setMetaData() throws BundleException {
- setLocation(Constants.SYSTEM_BUNDLE_LOCATION);
- BaseStorageHook.loadManifest(this, manifest);
- }
-
- public BundleClassLoader createClassLoader(ClassLoaderDelegate delegate, BundleProtectionDomain domain, String[] bundleclasspath) {
- return null;
- }
-
- public File createGenerationDir() {
- return null;
- }
-
- public String findLibrary(String libname) {
- return null;
- }
-
- /**
- * @throws BundleException
- */
- public void installNativeCode(String[] nativepaths) throws BundleException {
- // do nothing
- }
-
- public int getStartLevel() {
- return 0;
- }
-
- public int getStatus() {
- return Constants.BUNDLE_STARTED;
- }
-
- public void save() {
- // do nothing
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/CachedManifest.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/CachedManifest.java
deleted file mode 100644
index 550c2e24b..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/CachedManifest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.framework.util.Headers;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-
-/**
- * Internal class.
- */
-public class CachedManifest extends Dictionary<String, String> {
- static final String SERVICE_COMPONENT = "Service-Component"; //$NON-NLS-1$
- static boolean DEBUG = false;
- private Dictionary<String, String> manifest = null;
- private EclipseStorageHook storageHook;
-
- public CachedManifest(EclipseStorageHook storageHook) {
- this.storageHook = storageHook;
- }
-
- public Dictionary<String, String> getManifest() {
- if (manifest == null)
- try {
- if (DEBUG)
- System.out.println("Reading manifest for: " + storageHook.getBaseData()); //$NON-NLS-1$
- manifest = storageHook.createCachedManifest(true);
- } catch (BundleException e) {
- final String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CACHEDMANIFEST_UNEXPECTED_EXCEPTION, storageHook.getBaseData().getLocation());
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null);
- storageHook.getAdaptor().getFrameworkLog().log(entry);
- }
- if (manifest == null) {
- Headers<String, String> empty = new Headers<String, String>(0);
- empty.setReadOnly();
- manifest = empty;
- return empty;
- }
- return manifest;
- }
-
- public int size() {
- return getManifest().size();
- }
-
- public boolean isEmpty() {
- return size() == 0;
- }
-
- public Enumeration<String> elements() {
- return getManifest().elements();
- }
-
- public Enumeration<String> keys() {
- return getManifest().keys();
- }
-
- @SuppressWarnings("deprecation")
- public String get(Object key) {
- if (manifest != null)
- return manifest.get(key);
- String keyString = (String) key;
- if (Constants.BUNDLE_VERSION.equalsIgnoreCase(keyString)) {
- Version result = storageHook.getBaseData().getVersion();
- return result == null ? null : result.toString();
- }
- if (Constants.PLUGIN_CLASS.equalsIgnoreCase(keyString))
- return storageHook.getPluginClass();
- if (Constants.BUNDLE_SYMBOLICNAME.equalsIgnoreCase(keyString)) {
- if ((storageHook.getBaseData().getType() & BundleData.TYPE_SINGLETON) == 0)
- return storageHook.getBaseData().getSymbolicName();
- return storageHook.getBaseData().getSymbolicName() + ';' + Constants.SINGLETON_DIRECTIVE + ":=true"; //$NON-NLS-1$
- }
- if (Constants.BUDDY_LOADER.equalsIgnoreCase(keyString))
- return storageHook.getBuddyList();
- if (Constants.REGISTERED_POLICY.equalsIgnoreCase(keyString))
- return storageHook.getRegisteredBuddyList();
- if (Constants.BUNDLE_ACTIVATOR.equalsIgnoreCase(keyString))
- return storageHook.getBaseData().getActivator();
- if (Constants.BUNDLE_ACTIVATIONPOLICY.equals(keyString)) {
- if (!storageHook.isAutoStartable())
- return null;
- String[] excludes = storageHook.getLazyStartExcludes();
- String[] includes = storageHook.getLazyStartIncludes();
- if (excludes == null && includes == null)
- return Constants.ACTIVATION_LAZY;
- StringBuffer result = new StringBuffer(Constants.ACTIVATION_LAZY);
- if (excludes != null) {
- result.append(';').append(Constants.EXCLUDE_DIRECTIVE).append(":=\""); //$NON-NLS-1$
- for (int i = 0; i < excludes.length; i++) {
- if (i > 0)
- result.append(',');
- result.append(excludes[i]);
- }
- result.append("\""); //$NON-NLS-1$
- }
- if (includes != null) {
- result.append(';').append(Constants.INCLUDE_DIRECTIVE).append(":=\""); //$NON-NLS-1$
- for (int i = 0; i < includes.length; i++) {
- if (i > 0)
- result.append(',');
- result.append(includes[i]);
- }
- result.append("\""); //$NON-NLS-1$
- }
- }
- if (Constants.ECLIPSE_LAZYSTART.equals(keyString) || Constants.ECLIPSE_AUTOSTART.equals(keyString)) {
- if (!storageHook.isAutoStartable())
- return null;
- if (storageHook.getLazyStartExcludes() == null)
- return Boolean.TRUE.toString();
- StringBuffer result = new StringBuffer(storageHook.isLazyStart() ? Boolean.TRUE.toString() : Boolean.FALSE.toString());
- result.append(";").append(Constants.ECLIPSE_LAZYSTART_EXCEPTIONS).append("=\""); //$NON-NLS-1$ //$NON-NLS-2$
- String[] exceptions = storageHook.getLazyStartExcludes();
- for (int i = 0; i < exceptions.length; i++) {
- if (i > 0)
- result.append(","); //$NON-NLS-1$
- result.append(exceptions[i]);
- }
- result.append("\""); //$NON-NLS-1$
- return result.toString();
- }
- if (Constants.BUNDLE_MANIFESTVERSION.equals(keyString))
- return storageHook.getBundleManifestVersion() == 0 ? null : Integer.toString(storageHook.getBundleManifestVersion());
- if (SERVICE_COMPONENT.equals(keyString))
- return storageHook.getServiceComponent();
- Dictionary<String, String> result = getManifest();
- if (DEBUG)
- System.out.println("Manifest read because of header: " + key); //$NON-NLS-1$
- return result == null ? null : result.get(key);
- }
-
- public String remove(Object key) {
- return getManifest().remove(key);
- }
-
- public String put(String key, String value) {
- return getManifest().put(key, value);
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ClasspathManifest.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ClasspathManifest.java
deleted file mode 100644
index 80e3c28cd..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/ClasspathManifest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.jar.Manifest;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.util.KeyedElement;
-
-public class ClasspathManifest implements KeyedElement {
- public static final Object KEY = new Object();
- public static final int HASHCODE = KEY.hashCode();
-
- private Manifest manifest;
- private boolean initialized = false;
-
- public int getKeyHashCode() {
- return HASHCODE;
- }
-
- public boolean compare(KeyedElement other) {
- return other.getKey() == KEY;
- }
-
- public Object getKey() {
- return KEY;
- }
-
- public synchronized Manifest getManifest(ClasspathEntry cpEntry, ClasspathManager loader) {
- if (initialized)
- return manifest;
- if (!hasPackageInfo(cpEntry, loader)) {
- initialized = true;
- manifest = null;
- return manifest;
- }
- BundleEntry mfEntry = cpEntry.getBundleFile().getEntry(org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST);
- if (mfEntry != null) {
- InputStream manIn = null;
- try {
- try {
- manIn = mfEntry.getInputStream();
- manifest = new Manifest(manIn);
- } finally {
- if (manIn != null)
- manIn.close();
- }
- } catch (IOException e) {
- // do nothing
- }
- }
- initialized = true;
- return manifest;
- }
-
- private boolean hasPackageInfo(ClasspathEntry cpEntry, ClasspathManager loader) {
- BaseData bundledata = null;
- if (cpEntry.getBundleFile() == loader.getBaseData().getBundleFile())
- bundledata = loader.getBaseData();
- if (bundledata == null) {
- FragmentClasspath[] fragCPs = loader.getFragmentClasspaths();
- if (fragCPs != null)
- for (int i = 0; i < fragCPs.length; i++)
- if (cpEntry.getBundleFile() == fragCPs[i].getBundleData().getBundleFile()) {
- bundledata = fragCPs[i].getBundleData();
- break;
- }
- }
- if (bundledata == null)
- return true;
- EclipseStorageHook storageHook = (EclipseStorageHook) bundledata.getStorageHook(EclipseStorageHook.KEY);
- return storageHook == null ? true : storageHook.hasPackageInfo();
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorHook.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorHook.java
deleted file mode 100644
index d8c88d684..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorHook.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.IOException;
-import java.net.URLConnection;
-import java.util.*;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.SAXParserFactory;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.console.CommandProvider;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
-import org.eclipse.osgi.service.datalocation.Location;
-import org.eclipse.osgi.service.pluginconversion.PluginConverter;
-import org.eclipse.osgi.service.resolver.PlatformAdmin;
-import org.eclipse.osgi.service.urlconversion.URLConverter;
-import org.osgi.framework.*;
-
-public class EclipseAdaptorHook implements AdaptorHook, HookConfigurator {
- /** The SAX factory name */
- public static final String SAXFACTORYNAME = "javax.xml.parsers.SAXParserFactory"; //$NON-NLS-1$
- /** The DOM factory name */
- public static final String DOMFACTORYNAME = "javax.xml.parsers.DocumentBuilderFactory"; //$NON-NLS-1$
- private static final String RUNTIME_ADAPTOR = FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + "/eclipseadaptor"; //$NON-NLS-1$
- private static final String OPTION_CONVERTER = RUNTIME_ADAPTOR + "/converter/debug"; //$NON-NLS-1$
- private static final String OPTION_LOCATION = RUNTIME_ADAPTOR + "/debug/location"; //$NON-NLS-1$
- private static final String OPTION_CACHEDMANIFEST = RUNTIME_ADAPTOR + "/debug/cachedmanifest"; //$NON-NLS-1$
- static final boolean SET_TCCL_XMLFACTORY = "true".equals(FrameworkProperties.getProperty("eclipse.parsers.setTCCL", "true"));//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- private BaseAdaptor adaptor;
- private boolean noXML = false;
- private List<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>(10);
-
- /**
- * @throws BundleException
- */
- public void frameworkStart(BundleContext context) throws BundleException {
- registrations.clear();
- registerEndorsedXMLParser(context);
- Dictionary<String, Object> locationProperties = new Hashtable<String, Object>(1);
- Location location = LocationManager.getUserLocation();
- if (location != null) {
- locationProperties.put("type", LocationManager.PROP_USER_AREA); //$NON-NLS-1$
- registrations.add(context.registerService(Location.class.getName(), location, locationProperties));
- }
- location = LocationManager.getInstanceLocation();
- if (location != null) {
- locationProperties.put("type", LocationManager.PROP_INSTANCE_AREA); //$NON-NLS-1$
- registrations.add(context.registerService(Location.class.getName(), location, locationProperties));
- }
- location = LocationManager.getConfigurationLocation();
- if (location != null) {
- locationProperties.put("type", LocationManager.PROP_CONFIG_AREA); //$NON-NLS-1$
- registrations.add(context.registerService(Location.class.getName(), location, locationProperties));
- }
- location = LocationManager.getInstallLocation();
- if (location != null) {
- locationProperties.put("type", LocationManager.PROP_INSTALL_AREA); //$NON-NLS-1$
- registrations.add(context.registerService(Location.class.getName(), location, locationProperties));
- }
-
- location = LocationManager.getEclipseHomeLocation();
- if (location != null) {
- locationProperties.put("type", LocationManager.PROP_HOME_LOCATION_AREA); //$NON-NLS-1$
- registrations.add(context.registerService(Location.class.getName(), location, locationProperties));
- }
-
- Dictionary<String, Object> urlProperties = new Hashtable<String, Object>();
- urlProperties.put("protocol", new String[] {"bundleentry", "bundleresource"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- registrations.add(context.registerService(URLConverter.class.getName(), new URLConverterImpl(), urlProperties));
-
- registrations.add(AdaptorUtil.register(org.eclipse.osgi.service.environment.EnvironmentInfo.class.getName(), EclipseEnvironmentInfo.getDefault(), context));
- registrations.add(AdaptorUtil.register(PlatformAdmin.class.getName(), adaptor.getPlatformAdmin(), context));
- PluginConverter converter = PluginConverterImpl.getDefault();
- if (converter == null)
- converter = new PluginConverterImpl(adaptor, context);
- registrations.add(AdaptorUtil.register(PluginConverter.class.getName(), converter, context));
- String builtinEnabled = FrameworkProperties.getProperty(ConsoleManager.PROP_CONSOLE_ENABLED, ConsoleManager.CONSOLE_BUNDLE);
- if ("true".equals(builtinEnabled)) { //$NON-NLS-1$
- registrations.add(AdaptorUtil.register(CommandProvider.class.getName(), new EclipseCommandProvider(context), context));
- }
- registrations.add(AdaptorUtil.register(org.eclipse.osgi.service.localization.BundleLocalization.class.getName(), new BundleLocalizationImpl(), context));
- }
-
- private void registerEndorsedXMLParser(BundleContext bc) {
- try {
- Class.forName(SAXFACTORYNAME);
- registrations.add(bc.registerService(SAXFACTORYNAME, new ParsingService(true), null));
- Class.forName(DOMFACTORYNAME);
- registrations.add(bc.registerService(DOMFACTORYNAME, new ParsingService(false), null));
- } catch (ClassNotFoundException e) {
- noXML = true;
- if (Debug.DEBUG_ENABLED) {
- String message = EclipseAdaptorMsg.ECLIPSE_ADAPTOR_ERROR_XML_SERVICE;
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
- }
- }
- }
-
- private static class ParsingService implements ServiceFactory<Object> {
- private final boolean isSax;
-
- public ParsingService(boolean isSax) {
- this.isSax = isSax;
- }
-
- public Object getService(Bundle bundle, ServiceRegistration<Object> registration) {
- BundleHost host = (bundle instanceof BundleHost) ? (BundleHost) bundle : null;
- if (!SET_TCCL_XMLFACTORY || bundle == null)
- return createService();
- /*
- * Set the TCCL while creating jaxp factory instances to the
- * requesting bundles class loader. This is needed to
- * work around bug 285505. There are issues if multiple
- * xerces implementations are available on the bundles class path
- *
- * The real issue is that the ContextFinder will only delegate
- * to the framework class loader in this case. This class
- * loader forces the requesting bundle to be delegated to for
- * TCCL loads.
- */
- final ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- ClassLoader cl = host.getClassLoader();
- if (cl != null)
- Thread.currentThread().setContextClassLoader(cl);
- return createService();
- } finally {
- Thread.currentThread().setContextClassLoader(savedClassLoader);
- }
- }
-
- private Object createService() {
- if (isSax)
- return SAXParserFactory.newInstance();
- return DocumentBuilderFactory.newInstance();
- }
-
- public void ungetService(Bundle bundle, ServiceRegistration<Object> registration, Object service) {
- // Do nothing.
- }
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStop(BundleContext context) throws BundleException {
- printStats();
- if (!noXML)
- PluginParser.releaseXMLParsing();
- // unregister services
- for (ServiceRegistration<?> registration : registrations)
- registration.unregister();
- registrations.clear();
- }
-
- private void printStats() {
- FrameworkDebugOptions debugOptions = FrameworkDebugOptions.getDefault();
- if (debugOptions == null)
- return;
- String registryParsing = debugOptions.getOption("org.eclipse.core.runtime/registry/parsing/timing/value"); //$NON-NLS-1$
- if (registryParsing != null)
- MessageHelper.debug("Time spent in registry parsing: " + registryParsing); //$NON-NLS-1$
- String packageAdminResolution = debugOptions.getOption("debug.packageadmin/timing/value"); //$NON-NLS-1$
- if (packageAdminResolution != null)
- System.out.println("Time spent in package admin resolve: " + packageAdminResolution); //$NON-NLS-1$
- String constraintResolution = debugOptions.getOption("org.eclipse.core.runtime.adaptor/resolver/timing/value"); //$NON-NLS-1$
- if (constraintResolution != null)
- System.out.println("Time spent resolving the dependency system: " + constraintResolution); //$NON-NLS-1$
- }
-
- public void frameworkStopping(BundleContext context) {
- // do nothing
- }
-
- public void addProperties(Properties properties) {
- // do nothing
- }
-
- /**
- * @throws IOException
- */
- public URLConnection mapLocationToURLConnection(String location) throws IOException {
- // do nothing
- return null;
- }
-
- public void handleRuntimeError(Throwable error) {
- // do nothing
- }
-
- public FrameworkLog createFrameworkLog() {
- // do nothing
- return null;
- }
-
- public void initialize(BaseAdaptor initAdaptor) {
- this.adaptor = initAdaptor;
- // EnvironmentInfo has to be initialized first to compute defaults for system context (see bug 88925)
- EclipseEnvironmentInfo.getDefault();
- setDebugOptions();
- }
-
- private void setDebugOptions() {
- FrameworkDebugOptions options = FrameworkDebugOptions.getDefault();
- // may be null if debugging is not enabled
- if (options == null)
- return;
- PluginConverterImpl.DEBUG = options.getBooleanOption(OPTION_CONVERTER, false);
- BasicLocation.DEBUG = options.getBooleanOption(OPTION_LOCATION, false);
- CachedManifest.DEBUG = options.getBooleanOption(OPTION_CACHEDMANIFEST, false);
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addAdaptorHook(this);
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseClassLoadingHook.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseClassLoadingHook.java
deleted file mode 100644
index c24307844..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseClassLoadingHook.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.File;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
-import org.eclipse.osgi.baseadaptor.loader.*;
-import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.internal.baseadaptor.BaseClassLoadingHook;
-import org.eclipse.osgi.internal.baseadaptor.BaseStorageHook;
-
-public class EclipseClassLoadingHook implements ClassLoadingHook, HookConfigurator {
- private static String[] NL_JAR_VARIANTS = buildNLJarVariants(EclipseEnvironmentInfo.getDefault().getNL());
- private static boolean DEFINE_PACKAGES;
- private final static boolean DEFINE_PACKAGE_ATTRIBUTES = !"noattributes".equals(FrameworkProperties.getProperty("osgi.classloader.define.packages")); //$NON-NLS-1$ //$NON-NLS-2$
- private static String[] LIB_VARIANTS = buildLibraryVariants();
- private Object pkgLock = new Object();
-
- static {
- try {
- Class.forName("java.lang.Package"); //$NON-NLS-1$
- DEFINE_PACKAGES = true;
- } catch (ClassNotFoundException e) {
- DEFINE_PACKAGES = false;
- }
- }
-
- private static String[] buildLibraryVariants() {
- List<String> result = new ArrayList<String>();
- EclipseEnvironmentInfo info = EclipseEnvironmentInfo.getDefault();
- result.add("ws/" + info.getWS() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
- result.add("os/" + info.getOS() + "/" + info.getOSArch() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- result.add("os/" + info.getOS() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
- String nl = info.getNL();
- nl = nl.replace('_', '/');
- while (nl.length() > 0) {
- result.add("nl/" + nl + "/"); //$NON-NLS-1$ //$NON-NLS-2$
- int i = nl.lastIndexOf('/');
- nl = (i < 0) ? "" : nl.substring(0, i); //$NON-NLS-1$
- }
- result.add(""); //$NON-NLS-1$
- return result.toArray(new String[result.size()]);
- }
-
- public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- if (!DEFINE_PACKAGES)
- return null;
- // Define the package if it is not the default package.
- int lastIndex = name.lastIndexOf('.');
- if (lastIndex < 0)
- return null;
- String packageName = name.substring(0, lastIndex);
- Object pkg;
- synchronized (pkgLock) {
- pkg = manager.getBaseClassLoader().publicGetPackage(packageName);
- if (pkg != null)
- return null;
- }
-
- // get info about the package from the classpath entry's manifest.
- String specTitle = null, specVersion = null, specVendor = null, implTitle = null, implVersion = null, implVendor = null;
-
- if (DEFINE_PACKAGE_ATTRIBUTES) {
- ClasspathManifest cpm = (ClasspathManifest) classpathEntry.getUserObject(ClasspathManifest.KEY);
- if (cpm == null) {
- cpm = new ClasspathManifest();
- classpathEntry.addUserObject(cpm);
- }
- Manifest mf = cpm.getManifest(classpathEntry, manager);
- if (mf != null) {
- Attributes mainAttributes = mf.getMainAttributes();
- String dirName = packageName.replace('.', '/') + '/';
- Attributes packageAttributes = mf.getAttributes(dirName);
- boolean noEntry = false;
- if (packageAttributes == null) {
- noEntry = true;
- packageAttributes = mainAttributes;
- }
- specTitle = packageAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
- if (specTitle == null && !noEntry)
- specTitle = mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
- specVersion = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
- if (specVersion == null && !noEntry)
- specVersion = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
- specVendor = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
- if (specVendor == null && !noEntry)
- specVendor = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
- implTitle = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
- if (implTitle == null && !noEntry)
- implTitle = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
- implVersion = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
- if (implVersion == null && !noEntry)
- implVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
- implVendor = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
- if (implVendor == null && !noEntry)
- implVendor = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
- }
- }
-
- // The package is not defined yet define it before we define the class.
- // TODO still need to seal packages.
- synchronized (pkgLock) {
- pkg = manager.getBaseClassLoader().publicGetPackage(packageName);
- if (pkg != null)
- return null;
- manager.getBaseClassLoader().publicDefinePackage(packageName, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, null);
- }
- // not doing any byte processing
- return null;
- }
-
- public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) {
- String var = hasPrefix(cp);
- if (var != null)
- // find internal library using eclipse predefined vars
- return addInternalClassPath(var, cpEntries, cp, hostmanager, sourcedata, sourcedomain);
- if (cp.startsWith(BaseStorageHook.EXTERNAL_LIB_PREFIX)) {
- cp = cp.substring(BaseStorageHook.EXTERNAL_LIB_PREFIX.length());
- // find external library using system property substitution
- ClasspathEntry cpEntry = hostmanager.getExternalClassPath(BaseStorageHook.substituteVars(cp), sourcedata, sourcedomain);
- if (cpEntry != null) {
- cpEntries.add(cpEntry);
- return true;
- }
- }
- return false;
- }
-
- private boolean addInternalClassPath(String var, ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
- if (var.equals("ws")) //$NON-NLS-1$
- return ClasspathManager.addClassPathEntry(cpEntries, "ws/" + EclipseEnvironmentInfo.getDefault().getWS() + cp.substring(4), hostloader, sourcedata, sourcedomain); //$NON-NLS-1$
- if (var.equals("os")) //$NON-NLS-1$
- return ClasspathManager.addClassPathEntry(cpEntries, "os/" + EclipseEnvironmentInfo.getDefault().getOS() + cp.substring(4), hostloader, sourcedata, sourcedomain); //$NON-NLS-1$
- if (var.equals("nl")) { //$NON-NLS-1$
- cp = cp.substring(4);
- for (int i = 0; i < NL_JAR_VARIANTS.length; i++)
- if (ClasspathManager.addClassPathEntry(cpEntries, "nl/" + NL_JAR_VARIANTS[i] + cp, hostloader, sourcedata, sourcedomain)) //$NON-NLS-1$
- return true;
- }
- return false;
- }
-
- //return a String representing the string found between the $s
- private static String hasPrefix(String libPath) {
- if (libPath.startsWith("$ws$")) //$NON-NLS-1$
- return "ws"; //$NON-NLS-1$
- if (libPath.startsWith("$os$")) //$NON-NLS-1$
- return "os"; //$NON-NLS-1$
- if (libPath.startsWith("$nl$")) //$NON-NLS-1$
- return "nl"; //$NON-NLS-1$
- return null;
- }
-
- private static String[] buildNLJarVariants(String nl) {
- List<String> result = new ArrayList<String>();
- nl = nl.replace('_', '/');
- while (nl.length() > 0) {
- result.add("nl/" + nl + "/"); //$NON-NLS-1$ //$NON-NLS-2$
- int i = nl.lastIndexOf('/');
- nl = (i < 0) ? "" : nl.substring(0, i); //$NON-NLS-1$
- }
- result.add(""); //$NON-NLS-1$
- return result.toArray(new String[result.size()]);
- }
-
- public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- // do nothing
- }
-
- public String findLibrary(BaseData data, String libName) {
- if (libName.length() == 0)
- return null;
- if (libName.charAt(0) == '/' || libName.charAt(0) == '\\')
- libName = libName.substring(1);
- String mappedLibName = System.mapLibraryName(libName);
- String result = searchVariants(data, mappedLibName);
- if (result != null)
- return result;
- String[] mappedLibNames = BaseClassLoadingHook.mapLibraryNames(mappedLibName);
- for (int i = 0; i < mappedLibNames.length && result == null; i++)
- result = searchVariants(data, mappedLibNames[i]);
- return result;
- }
-
- private String searchVariants(BaseData bundledata, String path) {
- for (int i = 0; i < LIB_VARIANTS.length; i++) {
- BundleFile baseBundleFile = bundledata.getBundleFile();
- BundleEntry libEntry = baseBundleFile.getEntry(LIB_VARIANTS[i] + path);
- if (libEntry != null) {
- File libFile = baseBundleFile.getFile(LIB_VARIANTS[i] + path, true);
- if (libFile == null)
- return null;
- // see bug 88697 - HP requires libraries to have executable permissions
- if (org.eclipse.osgi.service.environment.Constants.OS_HPUX.equals(EclipseEnvironmentInfo.getDefault().getOS())) {
- try {
- // use the string array method in case there is a space in the path
- Runtime.getRuntime().exec(new String[] {"chmod", "755", libFile.getAbsolutePath()}).waitFor(); //$NON-NLS-1$ //$NON-NLS-2$
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return libFile.getAbsolutePath();
- }
- }
- return null;
- }
-
- public ClassLoader getBundleClassLoaderParent() {
- return null; // do nothing
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addClassLoadingHook(this);
- }
-
- public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) {
- // do nothing
- return null;
- }
-
- public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
- // do nothing
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseCommandProvider.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseCommandProvider.java
deleted file mode 100644
index 9647edfa7..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseCommandProvider.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.util.*;
-import java.util.Map.Entry;
-import org.eclipse.osgi.framework.console.CommandInterpreter;
-import org.eclipse.osgi.framework.console.CommandProvider;
-import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Internal class.
- */
-public class EclipseCommandProvider implements CommandProvider {
- public static final String NEW_LINE = "\r\n"; //$NON-NLS-1$
- public static final String TAB = "\t"; //$NON-NLS-1$
- private static final String POLICY_CONSOLE = "org.eclipse.osgi.framework.console"; //$NON-NLS-1$
- private PlatformAdmin platformAdmin;
- private BundleContext context;
-
- // holds the mapping between command name and command description
- private Map<String, String> commandsHelp = null;
-
- public EclipseCommandProvider(BundleContext context) {
- this.context = context;
- }
-
- public String getHelp() {
- return getHelp(null);
- }
-
- /* Returns either the help message for a particular command,
- * or the help messages for all commands (if commandName is not specified)*/
- private String getHelp(String commandName) {
- StringBuffer help = new StringBuffer(512);
-
- if (commandsHelp == null) {
- initializeCommandsHelp();
- }
-
- if (commandName != null) {
- if (commandsHelp.containsKey(commandName)) {
- addCommand(commandName, commandsHelp.get(commandName), help);
- }
- return help.toString();
- }
-
- addHeader(EclipseAdaptorMsg.ECLIPSE_CONSOLE_COMMANDS_HEADER, help);
- for (Entry<String, String> entry : commandsHelp.entrySet()) {
- addCommand(entry.getKey(), entry.getValue(), help);
- }
-
- return help.toString();
- }
-
- private void initializeCommandsHelp() {
- commandsHelp = new LinkedHashMap<String, String>();
- commandsHelp.put("diag", EclipseAdaptorMsg.ECLIPSE_CONSOLE_HELP_DIAG_COMMAND_DESCRIPTION); //$NON-NLS-1$
- commandsHelp.put("enableBundle", EclipseAdaptorMsg.ECLIPSE_CONSOLE_HELP_ENABLE_COMMAND_DESCRIPTION); //$NON-NLS-1$
- commandsHelp.put("disableBundle", EclipseAdaptorMsg.ECLIPSE_CONSOLE_HELP_DISABLE_COMMAND_DESCRIPTION); //$NON-NLS-1$
- commandsHelp.put("disabledBundles", EclipseAdaptorMsg.ECLIPSE_CONSOLE_HELP_LD_COMMAND_DESCRIPTION); //$NON-NLS-1$
- }
-
- /** Private helper method for getHelp. Formats the help headers. */
- private void addHeader(String header, StringBuffer help) {
- help.append("---"); //$NON-NLS-1$
- help.append(header);
- help.append("---"); //$NON-NLS-1$
- help.append(NEW_LINE);
- }
-
- /** Private helper method for getHelp. Formats the command descriptions. */
- private void addCommand(String command, String description, StringBuffer help) {
- help.append(TAB);
- help.append(command);
- help.append(" - "); //$NON-NLS-1$
- help.append(description);
- help.append(NEW_LINE);
- }
-
- private BundleDescription getBundleDescriptionFromToken(State state, String token) {
- try {
- long id = Long.parseLong(token);
- return state.getBundle(id);
- } catch (NumberFormatException nfe) {
- BundleDescription[] allBundles = state.getBundles(token);
- if (allBundles.length > 0)
- return allBundles[0];
- }
- return null;
- }
-
- private PlatformAdmin getPlatformAdmin(CommandInterpreter ci) {
- if (platformAdmin == null) {
- ServiceReference<?> platformAdminRef = context.getServiceReference(PlatformAdmin.class.getName());
- if (platformAdminRef == null) {
- ci.print(" "); //$NON-NLS-1$
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_NO_CONSTRAINTS_NO_PLATFORM_ADMIN_MESSAGE);
- return null;
- }
- platformAdmin = (PlatformAdmin) context.getService(platformAdminRef);
- }
- return platformAdmin;
- }
-
- private void ungetPlatformAdmin() {
- ServiceReference<?> platformAdminRef = context.getServiceReference(PlatformAdmin.class.getName());
- context.ungetService(platformAdminRef);
- }
-
- public void _diag(CommandInterpreter ci) throws Exception {
- String nextArg = ci.nextArgument();
- if (nextArg == null) {
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- return;
- }
- try {
- State systemState = getPlatformAdmin(ci).getState(false);
- while (nextArg != null) {
- BundleDescription bundle = getBundleDescriptionFromToken(systemState, nextArg);
- if (bundle == null) {
- ci.println(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_CANNOT_FIND_BUNDLE_ERROR, nextArg));
- nextArg = ci.nextArgument();
- continue;
- }
- ci.println(bundle.getLocation() + " [" + bundle.getBundleId() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
- VersionConstraint[] unsatisfied = platformAdmin.getStateHelper().getUnsatisfiedConstraints(bundle);
- ResolverError[] resolverErrors = platformAdmin.getState(false).getResolverErrors(bundle);
- for (int i = 0; i < resolverErrors.length; i++) {
- if ((resolverErrors[i].getType() & (ResolverError.MISSING_FRAGMENT_HOST | ResolverError.MISSING_GENERIC_CAPABILITY | ResolverError.MISSING_IMPORT_PACKAGE | ResolverError.MISSING_REQUIRE_BUNDLE)) != 0)
- continue;
- ci.print(" "); //$NON-NLS-1$
- ci.println(resolverErrors[i].toString());
- }
-
- if (unsatisfied.length == 0 && resolverErrors.length == 0) {
- ci.print(" "); //$NON-NLS-1$
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_NO_CONSTRAINTS);
- }
- if (unsatisfied.length > 0) {
- ci.print(" "); //$NON-NLS-1$
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_DIRECT_CONSTRAINTS);
- }
- for (int i = 0; i < unsatisfied.length; i++) {
- ci.print(" "); //$NON-NLS-1$
- ci.println(MessageHelper.getResolutionFailureMessage(unsatisfied[i]));
- }
- VersionConstraint[] unsatisfiedLeaves = platformAdmin.getStateHelper().getUnsatisfiedLeaves(new BundleDescription[] {bundle});
- boolean foundLeaf = false;
- for (int i = 0; i < unsatisfiedLeaves.length; i++) {
- if (unsatisfiedLeaves[i].getBundle() == bundle)
- continue;
- if (!foundLeaf) {
- foundLeaf = true;
- ci.print(" "); //$NON-NLS-1$
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_LEAF_CONSTRAINTS);
- }
- ci.print(" "); //$NON-NLS-1$
- ci.println(unsatisfiedLeaves[i].getBundle().getLocation() + " [" + unsatisfiedLeaves[i].getBundle().getBundleId() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
- ci.print(" "); //$NON-NLS-1$
- ci.println(MessageHelper.getResolutionFailureMessage(unsatisfiedLeaves[i]));
- }
- nextArg = ci.nextArgument();
- }
- } finally {
- ungetPlatformAdmin();
- }
- }
-
- public void _enableBundle(CommandInterpreter ci) throws Exception {
- String nextArg = ci.nextArgument();
- if (nextArg == null) {
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- return;
- }
- try {
- State systemState = getPlatformAdmin(ci).getState(false);
- while (nextArg != null) {
- BundleDescription bundleDesc = getBundleDescriptionFromToken(systemState, nextArg);
- if (bundleDesc == null) {
- ci.println(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_CANNOT_FIND_BUNDLE_ERROR, nextArg));
- nextArg = ci.nextArgument();
- continue;
- }
- DisabledInfo[] infos = systemState.getDisabledInfos(bundleDesc);
- for (int i = 0; i < infos.length; i++) {
- getPlatformAdmin(ci).removeDisabledInfo(infos[i]);
- }
- nextArg = ci.nextArgument();
- }
- } finally {
- ungetPlatformAdmin();
- }
- }
-
- public void _disableBundle(CommandInterpreter ci) throws Exception {
- String nextArg = ci.nextArgument();
- if (nextArg == null) {
- ci.println(EclipseAdaptorMsg.ECLIPSE_CONSOLE_NO_BUNDLE_SPECIFIED_ERROR);
- return;
- }
- try {
- State systemState = getPlatformAdmin(ci).getState(false);
- while (nextArg != null) {
- BundleDescription bundleDesc = getBundleDescriptionFromToken(systemState, nextArg);
- if (bundleDesc == null) {
- ci.println(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_CANNOT_FIND_BUNDLE_ERROR, nextArg));
- nextArg = ci.nextArgument();
- continue;
- }
- DisabledInfo info = new DisabledInfo(POLICY_CONSOLE, EclipseAdaptorMsg.ECLIPSE_CONSOLE_BUNDLE_DISABLED_MESSAGE, bundleDesc);
- getPlatformAdmin(ci).addDisabledInfo(info);
- nextArg = ci.nextArgument();
- }
- } finally {
- ungetPlatformAdmin();
- }
- }
-
- public void _disabledBundles(CommandInterpreter ci) throws Exception {
-
- try {
- State systemState = getPlatformAdmin(ci).getState(false);
- BundleDescription[] disabledBundles = systemState.getDisabledBundles();
-
- ci.println(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_DISABLED_COUNT_MESSAGE, String.valueOf(disabledBundles.length)));
-
- if (disabledBundles.length > 0) {
- ci.println();
- }
- for (int i = 0; i < disabledBundles.length; i++) {
- DisabledInfo[] disabledInfos = systemState.getDisabledInfos(disabledBundles[i]);
-
- ci.println(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_DISABLED_BUNDLE_HEADER, formatBundleName(disabledBundles[i]), String.valueOf(disabledBundles[i].getBundleId())));
- ci.print(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_DISABLED_BUNDLE_REASON1, disabledInfos[0].getMessage(), disabledInfos[0].getPolicyName()));
-
- for (int j = 1; j < disabledInfos.length; j++) {
- ci.print(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONSOLE_DISABLED_BUNDLE_REASON1, disabledInfos[j].getMessage(), String.valueOf(disabledInfos[j].getPolicyName())));
- }
-
- ci.println();
- }
- } finally {
- ungetPlatformAdmin();
- }
- }
-
- /**
- * Handles the help command
- *
- * @param intp
- * @return description for a particular command or false if there is no command with the specified name
- */
- public Object _help(CommandInterpreter intp) {
- String commandName = intp.nextArgument();
- if (commandName == null) {
- return false;
- }
- String help = getHelp(commandName);
- return help.length() > 0 ? help : false;
- }
-
- private String formatBundleName(BundleDescription b) {
- String label = b.getSymbolicName();
- if (label == null || label.length() == 0)
- label = b.toString();
- else
- label = label + "_" + b.getVersion(); //$NON-NLS-1$
-
- return label;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseEnvironmentInfo.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseEnvironmentInfo.java
deleted file mode 100644
index 0d091d7f4..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseEnvironmentInfo.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.util.*;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.service.environment.Constants;
-import org.eclipse.osgi.service.environment.EnvironmentInfo;
-import org.eclipse.osgi.util.NLS;
-
-/**
- * Internal class.
- */
-public class EclipseEnvironmentInfo implements EnvironmentInfo {
- private static EclipseEnvironmentInfo singleton;
- private static String nl;
- private static String os;
- private static String ws;
- private static String arch;
- private volatile static String[] allArgs;
- private volatile static String[] frameworkArgs;
- private volatile static String[] appArgs;
-
- // While we recognize the SunOS operating system, we change
- // this internally to be Solaris.
- private static final String INTERNAL_OS_SUNOS = "SunOS"; //$NON-NLS-1$
- private static final String INTERNAL_OS_LINUX = "Linux"; //$NON-NLS-1$
- private static final String INTERNAL_OS_MACOSX = "Mac OS"; //$NON-NLS-1$
- private static final String INTERNAL_OS_AIX = "AIX"; //$NON-NLS-1$
- private static final String INTERNAL_OS_HPUX = "HP-UX"; //$NON-NLS-1$
- private static final String INTERNAL_OS_QNX = "QNX"; //$NON-NLS-1$
- private static final String INTERNAL_OS_OS400 = "OS/400"; //$NON-NLS-1$
- private static final String INTERNAL_OS_OS390 = "OS/390"; //$NON-NLS-1$
- private static final String INTERNAL_OS_ZOS = "z/OS"; //$NON-NLS-1$
-
- // While we recognize the i386 architecture, we change
- // this internally to be x86.
- private static final String INTERNAL_ARCH_I386 = "i386"; //$NON-NLS-1$
- // While we recognize the amd64 architecture, we change
- // this internally to be x86_64.
- private static final String INTERNAL_AMD64 = "amd64"; //$NON-NLS-1$
-
- private EclipseEnvironmentInfo() {
- super();
- setupSystemContext();
- }
-
- public static EclipseEnvironmentInfo getDefault() {
- if (singleton == null)
- singleton = new EclipseEnvironmentInfo();
- return singleton;
- }
-
- public boolean inDevelopmentMode() {
- return FrameworkProperties.getProperty("osgi.dev") != null; //$NON-NLS-1$
- }
-
- public boolean inDebugMode() {
- return FrameworkProperties.getProperty("osgi.debug") != null; //$NON-NLS-1$
- }
-
- public String[] getCommandLineArgs() {
- return allArgs;
- }
-
- public String[] getFrameworkArgs() {
- return frameworkArgs;
- }
-
- public String[] getNonFrameworkArgs() {
- return appArgs;
- }
-
- public String getOSArch() {
- return arch;
- }
-
- public String getNL() {
- return nl;
- }
-
- public String getOS() {
- return os;
- }
-
- public String getWS() {
- return ws;
- }
-
- /**
- * Initializes the execution context for this run of the platform. The context
- * includes information about the locale, operating system and window system.
- *
- * NOTE: The OS, WS, and ARCH values should never be null. The executable should
- * be setting these values and therefore this code path is obsolete for Eclipse
- * when run from the executable.
- */
- private static void setupSystemContext() {
- // if the user didn't set the locale with a command line argument then use the default.
- nl = FrameworkProperties.getProperty("osgi.nl"); //$NON-NLS-1$
- if (nl != null) {
- StringTokenizer tokenizer = new StringTokenizer(nl, "_"); //$NON-NLS-1$
- int segments = tokenizer.countTokens();
- try {
- Locale userLocale = null;
- switch (segments) {
- case 1 :
- // use the 2 arg constructor to maintain compatibility with 1.3.1
- userLocale = new Locale(tokenizer.nextToken(), ""); //$NON-NLS-1$
- break;
- case 2 :
- userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken());
- break;
- case 3 :
- userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken(), tokenizer.nextToken());
- break;
- default :
- // if the user passed us in a bogus value then log a message and use the default
- System.err.println(NLS.bind(EclipseAdaptorMsg.error_badNL, nl));
- userLocale = Locale.getDefault();
- break;
- }
- Locale.setDefault(userLocale);
- // TODO what the heck is this for?? why not just use osgi.nl
- FrameworkProperties.setProperty("osgi.nl.user", nl); //$NON-NLS-1$
- } catch (NoSuchElementException e) {
- // fall through and use the default
- }
- }
- nl = Locale.getDefault().toString();
- FrameworkProperties.setProperty("osgi.nl", nl); //$NON-NLS-1$
-
- // if the user didn't set the operating system with a command line
- // argument then use the default.
- os = FrameworkProperties.getProperty("osgi.os"); //$NON-NLS-1$
- if (os == null) {
- os = guessOS(FrameworkProperties.getProperty("os.name"));//$NON-NLS-1$);
- FrameworkProperties.setProperty("osgi.os", os); //$NON-NLS-1$
- }
-
- // if the user didn't set the window system with a command line
- // argument then use the default.
- ws = FrameworkProperties.getProperty("osgi.ws"); //$NON-NLS-1$
- if (ws == null) {
- ws = guessWS(os);
- FrameworkProperties.setProperty("osgi.ws", ws); //$NON-NLS-1$
- }
-
- // if the user didn't set the system architecture with a command line
- // argument then use the default.
- arch = FrameworkProperties.getProperty("osgi.arch"); //$NON-NLS-1$
- if (arch == null) {
- String name = FrameworkProperties.getProperty("os.arch");//$NON-NLS-1$
- // Map i386 architecture to x86
- if (name.equalsIgnoreCase(INTERNAL_ARCH_I386))
- arch = Constants.ARCH_X86;
- // Map amd64 architecture to x86_64
- else if (name.equalsIgnoreCase(INTERNAL_AMD64))
- arch = Constants.ARCH_X86_64;
- else
- arch = name;
- FrameworkProperties.setProperty("osgi.arch", arch); //$NON-NLS-1$
- }
- }
-
- public static void setAllArgs(String[] allArgs) {
- // do not check if this is set already to allow arguments to change when multiple applications are launched
- EclipseEnvironmentInfo.allArgs = allArgs;
- }
-
- public static void setAppArgs(String[] appArgs) {
- // do not check if this is set already to allow arguments to change when multiple applications are launched
- EclipseEnvironmentInfo.appArgs = appArgs;
- }
-
- public static void setFrameworkArgs(String[] frameworkArgs) {
- // do not check if this is set already to allow arguments to change when multiple applications are launched
- EclipseEnvironmentInfo.frameworkArgs = frameworkArgs;
- }
-
- public static String guessWS(String osName) {
- // setup default values for known OSes if nothing was specified
- if (osName.equals(Constants.OS_WIN32))
- return Constants.WS_WIN32;
- if (osName.equals(Constants.OS_LINUX))
- return Constants.WS_GTK;
- if (osName.equals(Constants.OS_MACOSX))
- return Constants.WS_COCOA;
- if (osName.equals(Constants.OS_HPUX))
- return Constants.WS_MOTIF;
- if (osName.equals(Constants.OS_AIX))
- return Constants.WS_MOTIF;
- if (osName.equals(Constants.OS_SOLARIS))
- return Constants.WS_GTK;
- if (osName.equals(Constants.OS_QNX))
- return Constants.WS_PHOTON;
- return Constants.WS_UNKNOWN;
- }
-
- public static String guessOS(String osName) {
- // check to see if the OS name is "Windows 98" or some other
- // flavour which should be converted to win32.
- if (osName.regionMatches(true, 0, Constants.OS_WIN32, 0, 3))
- return Constants.OS_WIN32;
- // EXCEPTION: All mappings of SunOS convert to Solaris
- if (osName.equalsIgnoreCase(INTERNAL_OS_SUNOS))
- return Constants.OS_SOLARIS;
- if (osName.equalsIgnoreCase(INTERNAL_OS_LINUX))
- return Constants.OS_LINUX;
- if (osName.equalsIgnoreCase(INTERNAL_OS_QNX))
- return Constants.OS_QNX;
- if (osName.equalsIgnoreCase(INTERNAL_OS_AIX))
- return Constants.OS_AIX;
- if (osName.equalsIgnoreCase(INTERNAL_OS_HPUX))
- return Constants.OS_HPUX;
- if (osName.equalsIgnoreCase(INTERNAL_OS_OS400))
- return Constants.OS_OS400;
- if (osName.equalsIgnoreCase(INTERNAL_OS_OS390))
- return Constants.OS_OS390;
- if (osName.equalsIgnoreCase(INTERNAL_OS_ZOS))
- return Constants.OS_ZOS;
- // os.name on Mac OS can be either Mac OS or Mac OS X
- if (osName.regionMatches(true, 0, INTERNAL_OS_MACOSX, 0, INTERNAL_OS_MACOSX.length()))
- return Constants.OS_MACOSX;
- return Constants.OS_UNKNOWN;
- }
-
- public String getProperty(String key) {
- return FrameworkProperties.getProperty(key);
- }
-
- public String setProperty(String key, String value) {
- return FrameworkProperties.setProperty(key, value);
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseErrorHandler.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseErrorHandler.java
deleted file mode 100644
index afad88113..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseErrorHandler.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.IOException;
-import java.net.URLConnection;
-import java.util.Properties;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-
-public class EclipseErrorHandler implements AdaptorHook, HookConfigurator {
- // System property used to prevent VM exit when unexpected errors occur
- private static final String PROP_EXITONERROR = "eclipse.exitOnError"; //$NON-NLS-1$
- private BaseAdaptor adaptor;
-
- /**
- * @throws BundleException
- */
- public void frameworkStart(BundleContext context) throws BundleException {
- // do nothing
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStop(BundleContext context) throws BundleException {
- // do nothing
- }
-
- public void frameworkStopping(BundleContext context) {
- // do nothing
- }
-
- public void addProperties(Properties properties) {
- // do nothing
- }
-
- /**
- * @throws IOException
- */
- public URLConnection mapLocationToURLConnection(String location) throws IOException {
- // do nothing
- return null;
- }
-
- private boolean isFatalException(Throwable error) {
- if (error instanceof VirtualMachineError) {
- return true;
- }
- if (error instanceof ThreadDeath) {
- return true;
- }
- return false;
- }
-
- public void handleRuntimeError(Throwable error) {
- // this is the important method to handle errors
- boolean exitOnError = false;
- try {
- // check the prop each time this happens (should NEVER happen!)
- exitOnError = Boolean.valueOf(FrameworkProperties.getProperty(EclipseErrorHandler.PROP_EXITONERROR, "true")).booleanValue(); //$NON-NLS-1$
- String message = EclipseAdaptorMsg.ECLIPSE_ADAPTOR_RUNTIME_ERROR;
- if (exitOnError && isFatalException(error))
- message += ' ' + EclipseAdaptorMsg.ECLIPSE_ADAPTOR_EXITING;
- FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, error, null);
- adaptor.getFrameworkLog().log(logEntry);
- } catch (Throwable t) {
- // we may be in a currupted state and must be able to handle any
- // errors (ie OutOfMemoryError)
- // that may occur when handling the first error; this is REALLY the
- // last resort.
- try {
- error.printStackTrace();
- t.printStackTrace();
- } catch (Throwable t1) {
- // if we fail that then we are beyond help.
- }
- } finally {
- // do the exit outside the try block just incase another runtime
- // error was thrown while logging
- if (exitOnError && isFatalException(error))
- System.exit(13);
- }
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addAdaptorHook(this);
- }
-
- public FrameworkLog createFrameworkLog() {
- // do nothing
- return null;
- }
-
- public void initialize(BaseAdaptor initAdaptor) {
- this.adaptor = initAdaptor;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java
deleted file mode 100644
index e1c34d4df..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseLazyStarter.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.adaptor.StatusException;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.StateHelper;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, HookConfigurator {
- private static final boolean throwErrorOnFailedStart = "true".equals(FrameworkProperties.getProperty("osgi.compatibility.errorOnFailedStart", "true")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
- private BaseAdaptor adaptor;
- // holds the current activation trigger class and the ClasspathManagers that need to be activated
- private ThreadLocal<List<Object>> activationStack = new ThreadLocal<List<Object>>();
- // used to store exceptions that occurred while activating a bundle
- // keyed by ClasspathManager->Exception
- // WeakHashMap is used to prevent pinning the ClasspathManager objects.
- private final Map<ClasspathManager, TerminatingClassNotFoundException> errors = Collections.synchronizedMap(new WeakHashMap<ClasspathManager, TerminatingClassNotFoundException>());
-
- public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
- AbstractBundle bundle = (AbstractBundle) manager.getBaseData().getBundle();
- // If the bundle is active, uninstalled or stopping then the bundle has already
- // been initialized (though it may have been destroyed) so just return the class.
- if ((bundle.getState() & (Bundle.ACTIVE | Bundle.UNINSTALLED | Bundle.STOPPING)) != 0)
- return;
- EclipseStorageHook storageHook = (EclipseStorageHook) manager.getBaseData().getStorageHook(EclipseStorageHook.KEY);
- // The bundle is not active and does not require activation, just return the class
- if (!shouldActivateFor(name, manager.getBaseData(), storageHook, manager))
- return;
- List<Object> stack = activationStack.get();
- if (stack == null) {
- stack = new ArrayList<Object>(6);
- activationStack.set(stack);
- }
- // the first element in the stack is the name of the trigger class,
- // each element after the trigger class is a classpath manager
- // that must be activated after the trigger class has been defined (see postFindLocalClass)
- int size = stack.size();
- if (size > 1) {
- for (int i = size - 1; i >= 1; i--)
- if (manager == stack.get(i))
- // the manager is already on the stack in which case we are already in the process of loading the trigger class
- return;
- }
- Thread threadChangingState = bundle.getStateChanging();
- if (bundle.getState() == Bundle.STARTING && threadChangingState == Thread.currentThread())
- return; // this thread is starting the bundle already
- if (size == 0)
- stack.add(name);
- stack.add(manager);
- }
-
- public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) throws ClassNotFoundException {
- List<Object> stack = activationStack.get();
- if (stack == null)
- return;
- int size = stack.size();
- if (size <= 1 || stack.get(0) != name)
- return;
- // if we have a stack we must clear it even if (clazz == null)
- ClasspathManager[] managers = null;
- managers = new ClasspathManager[size - 1];
- for (int i = 1; i < size; i++)
- managers[i - 1] = (ClasspathManager) stack.get(i);
- stack.clear();
- if (clazz == null)
- return;
- for (int i = managers.length - 1; i >= 0; i--) {
- if (errors.get(managers[i]) != null) {
- if (throwErrorOnFailedStart)
- throw errors.get(managers[i]);
- continue;
- }
-
- // The bundle must be started.
- // Note that another thread may already be starting this bundle;
- // In this case we will timeout after a default of 5 seconds and record the BundleException
- long startTime = System.currentTimeMillis();
- try {
- // do not persist the start of this bundle
- managers[i].getBaseClassLoader().getDelegate().setLazyTrigger();
- } catch (BundleException e) {
- Bundle bundle = managers[i].getBaseData().getBundle();
- Throwable cause = e.getCause();
- if (cause != null && cause instanceof StatusException) {
- StatusException status = (StatusException) cause;
- if ((status.getStatusCode() & StatusException.CODE_ERROR) == 0) {
- if (status.getStatus() instanceof Thread) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object[] {Thread.currentThread(), name, status.getStatus(), bundle, new Long(System.currentTimeMillis() - startTime)});
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, e, null));
- }
- continue;
- }
- }
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_ACTIVATION, bundle.getSymbolicName(), Long.toString(bundle.getBundleId()));
- TerminatingClassNotFoundException error = new TerminatingClassNotFoundException(message, e);
- errors.put(managers[i], error);
- if (throwErrorOnFailedStart) {
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
- throw error;
- }
- adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, new BundleException(message, e));
- }
- }
- }
-
- public void preFindLocalResource(String name, ClasspathManager manager) {
- // do nothing
- }
-
- public void postFindLocalResource(String name, URL resource, ClasspathManager manager) {
- // do nothing
- }
-
- public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- // do nothing
- }
-
- private boolean shouldActivateFor(String className, BaseData bundledata, EclipseStorageHook storageHook, ClasspathManager manager) throws ClassNotFoundException {
- if (!isLazyStartable(className, bundledata, storageHook))
- return false;
- //if (manager.getBaseClassLoader().getDelegate().isLazyTriggerSet())
- // return false;
- // Don't activate non-starting bundles
- if (bundledata.getBundle().getState() == Bundle.RESOLVED) {
- if (throwErrorOnFailedStart) {
- TerminatingClassNotFoundException error = errors.get(manager);
- if (error != null)
- throw error;
- }
- return (bundledata.getStatus() & Constants.BUNDLE_STARTED) != 0;
- }
- return true;
- }
-
- private boolean isLazyStartable(String className, BaseData bundledata, EclipseStorageHook storageHook) {
- if (storageHook == null)
- return false;
- boolean lazyStart = storageHook.isLazyStart();
- String[] excludes = storageHook.getLazyStartExcludes();
- String[] includes = storageHook.getLazyStartIncludes();
- // no exceptions, it is easy to figure it out
- if (excludes == null && includes == null)
- return lazyStart;
- // otherwise, we need to check if the package is in the exceptions list
- int dotPosition = className.lastIndexOf('.');
- // the class has no package name... no exceptions apply
- if (dotPosition == -1)
- return lazyStart;
- String packageName = className.substring(0, dotPosition);
- if (lazyStart)
- return ((includes == null || contains(includes, packageName)) && (excludes == null || !contains(excludes, packageName)));
- return (excludes != null && contains(excludes, packageName));
- }
-
- private boolean contains(String[] array, String element) {
- for (int i = 0; i < array.length; i++)
- if (array[i].equals(element))
- return true;
- return false;
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addClassLoadingStatsHook(this);
- hookRegistry.addAdaptorHook(this);
- }
-
- public void addProperties(Properties properties) {
- // do nothing
- }
-
- public FrameworkLog createFrameworkLog() {
- // do nothing
- return null;
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStart(BundleContext context) throws BundleException {
- // nothing
- }
-
- /**
- * @throws BundleException
- */
- public void frameworkStop(BundleContext context) throws BundleException {
- // nothing
- }
-
- public void frameworkStopping(BundleContext context) {
- if (!Debug.DEBUG_ENABLED)
- return;
-
- BundleDescription[] allBundles = adaptor.getState().getResolvedBundles();
- StateHelper stateHelper = adaptor.getPlatformAdmin().getStateHelper();
- Object[][] cycles = stateHelper.sortBundles(allBundles);
- logCycles(cycles);
- }
-
- public void handleRuntimeError(Throwable error) {
- // do nothing
-
- }
-
- public void initialize(BaseAdaptor baseAdaptor) {
- this.adaptor = baseAdaptor;
- }
-
- /**
- * @throws IOException
- */
- public URLConnection mapLocationToURLConnection(String location) throws IOException {
- // do nothing
- return null;
- }
-
- private void logCycles(Object[][] cycles) {
- // log cycles
- if (cycles.length > 0) {
- StringBuffer cycleText = new StringBuffer("["); //$NON-NLS-1$
- for (int i = 0; i < cycles.length; i++) {
- cycleText.append('[');
- for (int j = 0; j < cycles[i].length; j++) {
- cycleText.append(((BundleDescription) cycles[i][j]).getSymbolicName());
- cycleText.append(',');
- }
- cycleText.insert(cycleText.length() - 1, ']');
- }
- cycleText.setCharAt(cycleText.length() - 1, ']');
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_BUNDLESTOPPER_CYCLES_FOUND, cycleText);
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, null, null);
- adaptor.getFrameworkLog().log(entry);
- }
- }
-
- private static class TerminatingClassNotFoundException extends ClassNotFoundException implements StatusException {
- private static final long serialVersionUID = -6730732895632169173L;
- private Throwable cause;
-
- public TerminatingClassNotFoundException(String message, Throwable cause) {
- super(message, cause);
- this.cause = cause;
- }
-
- public Object getStatus() {
- return cause;
- }
-
- public int getStatusCode() {
- return StatusException.CODE_ERROR;
- }
-
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseStorageHook.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseStorageHook.java
deleted file mode 100644
index 78aa333aa..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/EclipseStorageHook.java
+++ /dev/null
@@ -1,522 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.*;
-import java.net.URL;
-import java.security.*;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.osgi.baseadaptor.*;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.framework.util.Headers;
-import org.eclipse.osgi.framework.util.KeyedElement;
-import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
-import org.eclipse.osgi.service.datalocation.Location;
-import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
-import org.eclipse.osgi.util.ManifestElement;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-
-public final class EclipseStorageHook implements StorageHook, HookConfigurator {
- // System property used to check timestamps of the bundles in the configuration
- private static final String PROP_CHECK_CONFIG = "osgi.checkConfiguration"; //$NON-NLS-1$
- private static final String PROP_COMPATIBILITY_LAZYSTART = "osgi.compatibility.eagerStart.LazyActivation"; //$NON-NLS-1$
- private static final boolean COMPATIBILITY_LAZYSTART = Boolean.valueOf(FrameworkProperties.getProperty(PROP_COMPATIBILITY_LAZYSTART, "true")).booleanValue(); //$NON-NLS-1$
- private static final int STORAGE_VERION = 4;
-
- public static final String KEY = EclipseStorageHook.class.getName();
- public static final int HASHCODE = KEY.hashCode();
-
- private static final byte FLAG_LAZY_START = 0x01;
- private static final byte FLAG_HAS_PACKAGE_INFO = 0x02;
- // Note that the 0x04 was used in previous versions, if a new flag is needed then do not reuse this one
- //private static final byte FLAG_ACTIVATE_ON_CLASSLOAD = 0x04;
- // Flag to indicate that an include directive is present on the lazy activation policy
- private static final byte FLAG_HAS_LAZY_INCLUDE = 0x08;
-
- /** data to detect modification made in the manifest */
- private long manifestTimeStamp = 0;
- private byte manifestType = PluginConverterImpl.MANIFEST_TYPE_UNKNOWN;
-
- private BaseData bundledata;
-
- /** the Plugin-Class header */
- private String pluginClass = null;
- /** Eclipse-LazyStart header */
- private String[] lazyStartExcludes;
- private String[] lazyStartIncludes;
- private int bundleManfestVersion;
- /** shortcut to know if a bundle has a buddy */
- private String buddyList;
- /** shortcut to know if a bundle is a registrant to a registered policy */
- private String registeredBuddyList;
- /** DS Service Component header */
- private String serviceComponent;
- private byte flags = 0;
-
- public int getStorageVersion() {
- return STORAGE_VERION;
- }
-
- /**
- * @throws BundleException
- */
- public StorageHook create(BaseData data) throws BundleException {
- EclipseStorageHook storageHook = new EclipseStorageHook();
- storageHook.bundledata = data;
- return storageHook;
- }
-
- @SuppressWarnings("deprecation")
- public void initialize(Dictionary<String, String> manifest) throws BundleException {
- String activationPolicy = manifest.get(Constants.BUNDLE_ACTIVATIONPOLICY);
- if (activationPolicy != null) {
- parseActivationPolicy(this, activationPolicy);
- } else {
- String lazyStart = manifest.get(Constants.ECLIPSE_LAZYSTART);
- if (lazyStart == null)
- lazyStart = manifest.get(Constants.ECLIPSE_AUTOSTART);
- parseLazyStart(this, lazyStart);
- }
- try {
- String versionString = manifest.get(Constants.BUNDLE_MANIFESTVERSION);
- bundleManfestVersion = versionString == null ? 0 : Integer.parseInt(versionString);
- } catch (NumberFormatException nfe) {
- bundleManfestVersion = 0;
- }
- pluginClass = manifest.get(Constants.PLUGIN_CLASS);
- buddyList = manifest.get(Constants.BUDDY_LOADER);
- registeredBuddyList = manifest.get(Constants.REGISTERED_POLICY);
- if (hasPackageInfo(bundledata.getEntry(Constants.OSGI_BUNDLE_MANIFEST)))
- flags |= FLAG_HAS_PACKAGE_INFO;
- String genFrom = manifest.get(PluginConverterImpl.GENERATED_FROM);
- if (genFrom != null) {
- ManifestElement generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, genFrom)[0];
- if (generatedFrom != null) {
- manifestTimeStamp = Long.parseLong(generatedFrom.getValue());
- manifestType = Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE));
- }
- }
- if (isAutoStartable()) {
- bundledata.setStatus(bundledata.getStatus() | Constants.BUNDLE_LAZY_START);
- if (COMPATIBILITY_LAZYSTART)
- bundledata.setStatus(bundledata.getStatus() | Constants.BUNDLE_STARTED | Constants.BUNDLE_ACTIVATION_POLICY);
- }
- serviceComponent = manifest.get(CachedManifest.SERVICE_COMPONENT);
- }
-
- public StorageHook load(BaseData target, DataInputStream in) throws IOException {
- EclipseStorageHook storageHook = new EclipseStorageHook();
- storageHook.bundledata = target;
- storageHook.flags = in.readByte();
- int pkgCount = in.readInt();
- String[] packageList = pkgCount > 0 ? new String[pkgCount] : null;
- for (int i = 0; i < pkgCount; i++)
- packageList[i] = in.readUTF();
- storageHook.lazyStartExcludes = packageList;
- if ((storageHook.flags & FLAG_HAS_LAZY_INCLUDE) != 0) {
- pkgCount = in.readInt();
- packageList = pkgCount > 0 ? new String[pkgCount] : null;
- for (int i = 0; i < pkgCount; i++)
- packageList[i] = in.readUTF();
- storageHook.lazyStartIncludes = packageList;
- }
- storageHook.buddyList = AdaptorUtil.readString(in, false);
- storageHook.registeredBuddyList = AdaptorUtil.readString(in, false);
- storageHook.pluginClass = AdaptorUtil.readString(in, false);
- storageHook.manifestTimeStamp = in.readLong();
- storageHook.manifestType = in.readByte();
- storageHook.bundleManfestVersion = in.readInt();
- if (storageHook.isAutoStartable()) {
- if ((target.getStatus() & Constants.BUNDLE_LAZY_START) == 0)
- target.setStatus(target.getStatus() | Constants.BUNDLE_LAZY_START);
- // if the compatibility flag is set then we must make sure the persistent start bit is set and the activation policy bit;
- // if the persistent start bit was already set then we should not set the activation policy bit because this is an "eager" started bundle.
- if (COMPATIBILITY_LAZYSTART && (target.getStatus() & Constants.BUNDLE_STARTED) == 0)
- target.setStatus(target.getStatus() | Constants.BUNDLE_STARTED | Constants.BUNDLE_ACTIVATION_POLICY);
- }
- storageHook.serviceComponent = AdaptorUtil.readString(in, false);
- return storageHook;
- }
-
- public void save(DataOutputStream out) throws IOException {
- if (bundledata == null)
- throw new IllegalStateException();
- // when this is stored back we always use the has include/exclude flag
- out.writeByte(flags);
- String[] excludes = getLazyStartExcludes();
- if (excludes == null)
- out.writeInt(0);
- else {
- out.writeInt(excludes.length);
- for (int i = 0; i < excludes.length; i++)
- out.writeUTF(excludes[i]);
- }
- if ((flags & FLAG_HAS_LAZY_INCLUDE) != 0) {
- String[] includes = getLazyStartIncludes();
- if (includes == null)
- out.writeInt(0);
- else {
- out.writeInt(includes.length);
- for (int i = 0; i < includes.length; i++)
- out.writeUTF(includes[i]);
- }
- }
- AdaptorUtil.writeStringOrNull(out, getBuddyList());
- AdaptorUtil.writeStringOrNull(out, getRegisteredBuddyList());
- AdaptorUtil.writeStringOrNull(out, getPluginClass());
- out.writeLong(getManifestTimeStamp());
- out.writeByte(getManifestType());
- out.writeInt(getBundleManifestVersion());
- AdaptorUtil.writeStringOrNull(out, serviceComponent);
- }
-
- public int getKeyHashCode() {
- return HASHCODE;
- }
-
- public boolean compare(KeyedElement other) {
- return other.getKey() == KEY;
- }
-
- public Object getKey() {
- return KEY;
- }
-
- public boolean isLazyStart() {
- return (flags & FLAG_LAZY_START) == FLAG_LAZY_START;
- }
-
- public String[] getLazyStartExcludes() {
- return lazyStartExcludes;
- }
-
- public String[] getLazyStartIncludes() {
- return lazyStartIncludes;
- }
-
- public String getBuddyList() {
- return buddyList;
- }
-
- public boolean hasPackageInfo() {
- return (flags & FLAG_HAS_PACKAGE_INFO) == FLAG_HAS_PACKAGE_INFO;
- }
-
- public String getPluginClass() {
- return pluginClass;
- }
-
- public String getRegisteredBuddyList() {
- return registeredBuddyList;
- }
-
- public long getManifestTimeStamp() {
- return manifestTimeStamp;
- }
-
- public byte getManifestType() {
- return manifestType;
- }
-
- public int getBundleManifestVersion() {
- return bundleManfestVersion;
- }
-
- public String getServiceComponent() {
- return serviceComponent;
- }
-
- /**
- * Checks whether this bundle is auto started for all resource/class loads or only for a
- * subset of resource/classloads
- * @return true if the bundle is auto started; false otherwise
- */
- public boolean isAutoStartable() {
- return isLazyStart() || (lazyStartExcludes != null && lazyStartExcludes.length > 0);
- }
-
- private void parseLazyStart(EclipseStorageHook storageHook, String headerValue) {
- storageHook.lazyStartExcludes = null;
- ManifestElement[] allElements = null;
- try {
- allElements = ManifestElement.parseHeader(Constants.ECLIPSE_LAZYSTART, headerValue);
- } catch (BundleException e) {
- // just use the default settings (no auto activation)
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS, storageHook.bundledata.getLocation());
- bundledata.getAdaptor().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
- }
- //Eclipse-AutoStart not found...
- if (allElements == null)
- return;
- // the single value for this element should be true|false
- if ("true".equalsIgnoreCase(allElements[0].getValue())) //$NON-NLS-1$
- storageHook.flags |= FLAG_LAZY_START;
- // look for any exceptions (the attribute) to the autoActivate setting
- String[] exceptions = ManifestElement.getArrayFromList(allElements[0].getAttribute(Constants.ECLIPSE_LAZYSTART_EXCEPTIONS));
- storageHook.lazyStartExcludes = exceptions;
- }
-
- private void parseActivationPolicy(EclipseStorageHook storageHook, String headerValue) {
- storageHook.lazyStartExcludes = null;
- ManifestElement[] allElements = null;
- try {
- allElements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, headerValue);
- } catch (BundleException e) {
- // just use the default settings (no auto activation)
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS, storageHook.bundledata.getLocation());
- bundledata.getAdaptor().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
- }
- //Bundle-ActivationPolicy not found.
- if (allElements == null)
- return;
- // the single value for this type is lazy
- if (!Constants.ACTIVATION_LAZY.equalsIgnoreCase(allElements[0].getValue()))
- return;
- storageHook.flags |= FLAG_LAZY_START;
- // look for any include or exclude attrs
- storageHook.lazyStartExcludes = ManifestElement.getArrayFromList(allElements[0].getDirective(Constants.EXCLUDE_DIRECTIVE));
- storageHook.lazyStartIncludes = ManifestElement.getArrayFromList(allElements[0].getDirective(Constants.INCLUDE_DIRECTIVE));
- if (storageHook.lazyStartIncludes != null)
- storageHook.flags |= FLAG_HAS_LAZY_INCLUDE;
- }
-
- // Used to check the bundle manifest file for any package information.
- // This is used when '.' is on the Bundle-ClassPath to prevent reading
- // the bundle manifest for pacakge information when loading classes.
- private static boolean hasPackageInfo(URL url) {
- if (url == null)
- return false;
- BufferedReader br = null;
- try {
- br = new BufferedReader(new InputStreamReader(url.openStream()));
- String line;
- while ((line = br.readLine()) != null) {
- if (line.length() < 20)
- continue;
- switch (line.charAt(0)) {
- case 'S' :
- if (line.charAt(1) == 'p')
- if (line.startsWith("Specification-Title: ") || line.startsWith("Specification-Version: ") || line.startsWith("Specification-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
- return true;
- break;
- case 'I' :
- if (line.startsWith("Implementation-Title: ") || line.startsWith("Implementation-Version: ") || line.startsWith("Implementation-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
- return true;
- break;
- }
- }
- } catch (IOException ioe) {
- // do nothing
- } finally {
- if (br != null)
- try {
- br.close();
- } catch (IOException e) {
- // do nothing
- }
- }
- return false;
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- hookRegistry.addStorageHook(this);
- }
-
- private void checkTimeStamp() throws IllegalArgumentException {
- if (!checkManifestTimeStamp())
- throw new IllegalArgumentException();
- }
-
- private boolean checkManifestTimeStamp() {
- if (!"true".equalsIgnoreCase(FrameworkProperties.getProperty(EclipseStorageHook.PROP_CHECK_CONFIG))) //$NON-NLS-1$
- return true;
- if (PluginConverterImpl.getTimeStamp(bundledata.getBundleFile().getBaseFile(), getManifestType()) == getManifestTimeStamp()) {
- if ((getManifestType() & (PluginConverterImpl.MANIFEST_TYPE_JAR | PluginConverterImpl.MANIFEST_TYPE_BUNDLE)) != 0)
- return true;
- String cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE);
- Location parentConfiguration = LocationManager.getConfigurationLocation().getParentLocation();
- if (parentConfiguration != null) {
- try {
- return checkManifestAndParent(cacheLocation, bundledata.getSymbolicName(), bundledata.getVersion().toString(), getManifestType()) != null;
- } catch (BundleException e) {
- return false;
- }
- }
- File cacheFile = new File(cacheLocation, bundledata.getSymbolicName() + '_' + bundledata.getVersion() + ".MF"); //$NON-NLS-1$
- if (cacheFile.isFile())
- return true;
- }
- return false;
- }
-
- private Headers<String, String> checkManifestAndParent(String cacheLocation, String symbolicName, String version, byte inputType) throws BundleException {
- Headers<String, String> result = basicCheckManifest(cacheLocation, symbolicName, version, inputType);
- if (result != null)
- return result;
- Location parentConfiguration = null;
- if ((parentConfiguration = LocationManager.getConfigurationLocation().getParentLocation()) != null)
- result = basicCheckManifest(new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + '/' + LocationManager.MANIFESTS_DIR).toString(), symbolicName, version, inputType);
- return result;
- }
-
- private Headers<String, String> basicCheckManifest(String cacheLocation, String symbolicName, String version, byte inputType) throws BundleException {
- File currentFile = new File(cacheLocation, symbolicName + '_' + version + ".MF"); //$NON-NLS-1$
- if (PluginConverterImpl.upToDate(currentFile, bundledata.getBundleFile().getBaseFile(), inputType)) {
- try {
- return Headers.parseManifest(new FileInputStream(currentFile));
- } catch (FileNotFoundException e) {
- // do nothing.
- }
- }
- return null;
- }
-
- Dictionary<String, String> createCachedManifest(boolean firstTime) throws BundleException {
- return firstTime ? getGeneratedManifest() : new CachedManifest(this);
- }
-
- public Dictionary<String, String> getGeneratedManifest() throws BundleException {
- if (System.getSecurityManager() == null)
- return getGeneratedManifest0();
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Dictionary<String, String>>() {
- public Dictionary<String, String> run() throws BundleException {
- return getGeneratedManifest0();
- }
- });
- } catch (PrivilegedActionException e) {
- throw (BundleException) e.getException();
- }
- }
-
- final Dictionary<String, String> getGeneratedManifest0() throws BundleException {
- Dictionary<String, String> builtIn = AdaptorUtil.loadManifestFrom(bundledata);
- if (builtIn != null) {
- // the bundle has a built-in manifest - we may not have to generate one
- if (!isComplete(builtIn)) {
- Dictionary<String, String> generatedManifest = generateManifest(builtIn);
- if (generatedManifest != null)
- return generatedManifest;
- }
- // the manifest is complete or we could not complete it - take it as it is
- manifestType = PluginConverterImpl.MANIFEST_TYPE_BUNDLE;
- File baseFile = bundledata.getBundleFile().getBaseFile();
- if (baseFile != null && bundledata.getBundleFile().getBaseFile().isFile()) {
- manifestTimeStamp = bundledata.getBundleFile().getBaseFile().lastModified();
- manifestType |= PluginConverterImpl.MANIFEST_TYPE_JAR;
- } else
- manifestTimeStamp = bundledata.getBundleFile().getEntry(Constants.OSGI_BUNDLE_MANIFEST).getTime();
- return builtIn;
- }
- Dictionary<String, String> result = generateManifest(null);
- if (result == null)
- throw new BundleException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_DATA_MANIFEST_NOT_FOUND, bundledata.getLocation()));
- return result;
- }
-
- private Dictionary<String, String> generateManifest(Dictionary<String, String> builtIn) throws BundleException {
- String cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE);
- if (bundledata.getSymbolicName() != null) {
- Headers<String, String> existingHeaders = checkManifestAndParent(cacheLocation, bundledata.getSymbolicName(), bundledata.getVersion().toString(), manifestType);
- if (existingHeaders != null)
- return existingHeaders;
- }
-
- PluginConverterImpl converter = PluginConverterImpl.getDefault();
- if (converter == null)
- converter = new PluginConverterImpl(bundledata.getAdaptor(), bundledata.getAdaptor().getContext());
-
- Dictionary<String, String> generatedManifest;
- try {
- generatedManifest = converter.convertManifest(bundledata.getBundleFile().getBaseFile(), true, null, true, null);
- } catch (PluginConversionException pce) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_CONVERTING, bundledata.getBundleFile().getBaseFile());
- throw new BundleException(message, BundleException.MANIFEST_ERROR, pce);
- }
-
- //Now we know the symbolicId and the version of the bundle, we check to see if don't have a manifest for it already
- Version version = Version.parseVersion(generatedManifest.get(Constants.BUNDLE_VERSION));
- String symbolicName = ManifestElement.parseHeader(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME, generatedManifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME))[0].getValue();
- ManifestElement generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, generatedManifest.get(PluginConverterImpl.GENERATED_FROM))[0];
- Headers<String, String> existingHeaders = checkManifestAndParent(cacheLocation, symbolicName, version.toString(), Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE)));
- //We don't have a manifest.
- manifestTimeStamp = Long.parseLong(generatedFrom.getValue());
- manifestType = Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE));
- if (bundledata.getAdaptor().isReadOnly() || existingHeaders != null)
- return existingHeaders;
-
- //merge the original manifest with the generated one
- if (builtIn != null) {
- Enumeration<String> keysEnum = builtIn.keys();
- while (keysEnum.hasMoreElements()) {
- String key = keysEnum.nextElement();
- generatedManifest.put(key, builtIn.get(key));
- }
- }
-
- //write the generated manifest
- File bundleManifestLocation = new File(cacheLocation, symbolicName + '_' + version.toString() + ".MF"); //$NON-NLS-1$
- try {
- converter.writeManifest(bundleManifestLocation, generatedManifest, true);
- } catch (Exception e) {
- //TODO Need to log
- }
- return generatedManifest;
-
- }
-
- private boolean isComplete(Dictionary<String, String> manifest) {
- // a manifest is complete if it has a Bundle-SymbolicName entry...
- if (manifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME) != null)
- return true;
- // ...or it does not have a plugin/fragment manifest where to get the other entries from
- return bundledata.getEntry(PluginConverterImpl.PLUGIN_MANIFEST) == null && bundledata.getEntry(PluginConverterImpl.FRAGMENT_MANIFEST) == null;
- }
-
- public BaseData getBaseData() {
- return bundledata;
- }
-
- public void copy(StorageHook storageHook) {
- // copy nothing all must be re-read from a manifest
- }
-
- public void validate() throws IllegalArgumentException {
- checkTimeStamp();
- }
-
- public FrameworkAdaptor getAdaptor() {
- if (bundledata != null)
- return bundledata.getAdaptor();
- return null;
- }
-
- public Dictionary<String, String> getManifest(boolean firstLoad) throws BundleException {
- return createCachedManifest(firstLoad);
- }
-
- public boolean forgetStatusChange(int status) {
- return false;
- }
-
- public boolean forgetStartLevelChange(int startlevel) {
- return false;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IModel.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IModel.java
deleted file mode 100644
index 1a870c822..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IModel.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.core.runtime.internal.adaptor;
-
-/**
- * Internal class.
- */
-public interface IModel {
- public static final int INDENT = 2;
- public static final int RADIX = 36;
-
- public static final String TRUE = "true"; //$NON-NLS-1$
- public static final String FALSE = "false"; //$NON-NLS-1$
-
- public static final String REGISTRY = "plugin-registry"; //$NON-NLS-1$
- public static final String REGISTRY_PATH = "path"; //$NON-NLS-1$
-
- public static final String FRAGMENT = "fragment"; //$NON-NLS-1$
- public static final String FRAGMENT_ID = "id"; //$NON-NLS-1$
- public static final String FRAGMENT_NAME = "name"; //$NON-NLS-1$
- public static final String FRAGMENT_PROVIDER = "provider-name"; //$NON-NLS-1$
- public static final String FRAGMENT_VERSION = "version"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_ID = "plugin-id"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_VERSION = "plugin-version"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_MATCH = "match"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_MATCH_PERFECT = "perfect"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_MATCH_EQUIVALENT = "equivalent"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_MATCH_COMPATIBLE = "compatible"; //$NON-NLS-1$
- public static final String FRAGMENT_PLUGIN_MATCH_GREATER_OR_EQUAL = "greaterOrEqual"; //$NON-NLS-1$
-
- public static final String PLUGIN = "plugin"; //$NON-NLS-1$
- public static final String PLUGIN_ID = "id"; //$NON-NLS-1$
- public static final String PLUGIN_NAME = "name"; //$NON-NLS-1$
- public static final String PLUGIN_VENDOR = "vendor-name"; //$NON-NLS-1$
- public static final String PLUGIN_PROVIDER = "provider-name"; //$NON-NLS-1$
- public static final String PLUGIN_VERSION = "version"; //$NON-NLS-1$
- public static final String PLUGIN_CLASS = "class"; //$NON-NLS-1$
-
- public static final String PLUGIN_REQUIRES = "requires"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_PLATFORM = "platform-version"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_PLUGIN = "plugin"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_PLUGIN_VERSION = "version"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_OPTIONAL = "optional"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_IMPORT = "import"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_EXPORT = "export"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_MATCH = "match"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_MATCH_EXACT = "exact"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_MATCH_PERFECT = "perfect"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_MATCH_EQUIVALENT = "equivalent"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_MATCH_COMPATIBLE = "compatible"; //$NON-NLS-1$
- public static final String PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL = "greaterOrEqual"; //$NON-NLS-1$
-
- public static final String PLUGIN_KEY_VERSION_SEPARATOR = "_"; //$NON-NLS-1$
-
- public static final String RUNTIME = "runtime"; //$NON-NLS-1$
-
- public static final String LIBRARY = "library"; //$NON-NLS-1$
- public static final String LIBRARY_NAME = "name"; //$NON-NLS-1$
- public static final String LIBRARY_SOURCE = "source"; //$NON-NLS-1$
- public static final String LIBRARY_TYPE = "type"; //$NON-NLS-1$
- public static final String LIBRARY_EXPORT = "export"; //$NON-NLS-1$
- public static final String LIBRARY_EXPORT_MASK = "name"; //$NON-NLS-1$
- public static final String LIBRARY_PACKAGES = "packages"; //$NON-NLS-1$
- public static final String LIBRARY_PACKAGES_PREFIXES = "prefixes"; //$NON-NLS-1$
-
- public static final String EXTENSION_POINT = "extension-point"; //$NON-NLS-1$
- public static final String EXTENSION_POINT_NAME = "name"; //$NON-NLS-1$
- public static final String EXTENSION_POINT_ID = "id"; //$NON-NLS-1$
- public static final String EXTENSION_POINT_SCHEMA = "schema"; //$NON-NLS-1$
-
- public static final String EXTENSION = "extension"; //$NON-NLS-1$
- public static final String EXTENSION_NAME = "name"; //$NON-NLS-1$
- public static final String EXTENSION_ID = "id"; //$NON-NLS-1$
- public static final String EXTENSION_TARGET = "point"; //$NON-NLS-1$
-
- public static final String ELEMENT = "element"; //$NON-NLS-1$
- public static final String ELEMENT_NAME = "name"; //$NON-NLS-1$
- public static final String ELEMENT_VALUE = "value"; //$NON-NLS-1$
-
- public static final String PROPERTY = "property"; //$NON-NLS-1$
- public static final String PROPERTY_NAME = "name"; //$NON-NLS-1$
- public static final String PROPERTY_VALUE = "value"; //$NON-NLS-1$
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IPluginInfo.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IPluginInfo.java
deleted file mode 100644
index 9520f88eb..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/IPluginInfo.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.util.*;
-
-/**
- * Interface used as an entry to the IPluginConverter
- *
- * <p>Internal class.</p>
- */
-public interface IPluginInfo {
- public Map<String, List<String>> getLibraries();
-
- public String[] getLibrariesName();
-
- public ArrayList<PluginParser.Prerequisite> getRequires();
-
- public String getMasterId();
-
- public String getMasterVersion();
-
- public String getMasterMatch();
-
- public String getPluginClass();
-
- public String getUniqueId();
-
- public String getVersion();
-
- public boolean isFragment();
-
- public Set<String> getPackageFilters();
-
- public String getPluginName();
-
- public String getProviderName();
-
- public boolean isSingleton();
-
- public boolean hasExtensionExtensionPoints();
-
- String validateForm();
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/MessageHelper.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/MessageHelper.java
deleted file mode 100644
index e1cf601b1..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/MessageHelper.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.util.Date;
-import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.Constants;
-
-/**
- * @since 3.3
- */
-public class MessageHelper {
- public static String getResolutionFailureMessage(VersionConstraint unsatisfied) {
- if (unsatisfied.isResolved())
- throw new IllegalArgumentException();
- if (unsatisfied instanceof ImportPackageSpecification) {
- if (ImportPackageSpecification.RESOLUTION_OPTIONAL.equals(((ImportPackageSpecification) unsatisfied).getDirective(Constants.RESOLUTION_DIRECTIVE)))
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_OPTIONAL_IMPORTED_PACKAGE, toString(unsatisfied));
- if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(((ImportPackageSpecification) unsatisfied).getDirective(Constants.RESOLUTION_DIRECTIVE)))
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_DYNAMIC_IMPORTED_PACKAGE, toString(unsatisfied));
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_IMPORTED_PACKAGE, toString(unsatisfied));
- } else if (unsatisfied instanceof BundleSpecification) {
- if (((BundleSpecification) unsatisfied).isOptional())
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_OPTIONAL_REQUIRED_BUNDLE, toString(unsatisfied));
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_REQUIRED_BUNDLE, toString(unsatisfied));
- } else if (unsatisfied instanceof HostSpecification) {
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_HOST, toString(unsatisfied));
- } else if (unsatisfied instanceof NativeCodeSpecification) {
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_NATIVECODE, unsatisfied.toString());
- } else if (unsatisfied instanceof GenericSpecification) {
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_REQUIRED_CAPABILITY, unsatisfied.toString());
- }
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_MISSING_REQUIREMENT, unsatisfied.toString());
- }
-
- /**
- * Print a debug message to the console.
- * Pre-pend the message with the current date and the name of the current thread.
- */
- public static void debug(String message) {
- StringBuffer buffer = new StringBuffer();
- buffer.append(new Date(System.currentTimeMillis()));
- buffer.append(" - ["); //$NON-NLS-1$
- buffer.append(Thread.currentThread().getName());
- buffer.append("] "); //$NON-NLS-1$
- buffer.append(message);
- System.out.println(buffer.toString());
- }
-
- private static String toString(VersionConstraint constraint) {
- org.eclipse.osgi.service.resolver.VersionRange versionRange = constraint.getVersionRange();
- if (versionRange == null)
- return constraint.getName();
- return constraint.getName() + '_' + versionRange;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginConverterImpl.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginConverterImpl.java
deleted file mode 100644
index fe1447f2e..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginConverterImpl.java
+++ /dev/null
@@ -1,761 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.*;
-import java.util.*;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.baseadaptor.DevClassPathHelper;
-import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
-import org.eclipse.osgi.service.pluginconversion.PluginConverter;
-import org.eclipse.osgi.service.resolver.VersionRange;
-import org.eclipse.osgi.util.ManifestElement;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.*;
-
-/**
- * Internal class.
- */
-public class PluginConverterImpl implements PluginConverter {
- public static boolean DEBUG = false;
- /** bundle manifest type unknown */
- static public final byte MANIFEST_TYPE_UNKNOWN = 0x00;
- /** bundle manifest type bundle (META-INF/MANIFEST.MF) */
- static public final byte MANIFEST_TYPE_BUNDLE = 0x01;
- /** bundle manifest type plugin (plugin.xml) */
- static public final byte MANIFEST_TYPE_PLUGIN = 0x02;
- /** bundle manifest type fragment (fragment.xml) */
- static public final byte MANIFEST_TYPE_FRAGMENT = 0x04;
- /** bundle manifest type jared bundle */
- static public final byte MANIFEST_TYPE_JAR = 0x08;
- private static final String SEMICOLON = "; "; //$NON-NLS-1$
- private static final String UTF_8 = "UTF-8"; //$NON-NLS-1$
- private static final String LIST_SEPARATOR = ",\n "; //$NON-NLS-1$
- private static final String LINE_SEPARATOR = "\n "; //$NON-NLS-1$
- private static final String DOT = "."; //$NON-NLS-1$
- private static int MAXLINE = 511;
- private BundleContext context;
- private FrameworkAdaptor adaptor;
- private BufferedWriter out;
- private IPluginInfo pluginInfo;
- private File pluginManifestLocation;
- private ZipFile pluginZip;
- private Dictionary<String, String> generatedManifest;
- private byte manifestType;
- private Version target;
- private Dictionary<String, String> devProperties;
- static final Version TARGET31 = new Version(3, 1, 0);
- static final Version TARGET32 = new Version(3, 2, 0);
- private static final String MANIFEST_VERSION = "Manifest-Version"; //$NON-NLS-1$
- private static final String PLUGIN_PROPERTIES_FILENAME = "plugin"; //$NON-NLS-1$
- private static PluginConverterImpl instance;
- @SuppressWarnings("deprecation")
- private static final String[] ARCH_LIST = {org.eclipse.osgi.service.environment.Constants.ARCH_PA_RISC, org.eclipse.osgi.service.environment.Constants.ARCH_PPC, org.eclipse.osgi.service.environment.Constants.ARCH_SPARC, org.eclipse.osgi.service.environment.Constants.ARCH_X86, org.eclipse.osgi.service.environment.Constants.ARCH_AMD64, org.eclipse.osgi.service.environment.Constants.ARCH_IA64};
- static public final String FRAGMENT_MANIFEST = "fragment.xml"; //$NON-NLS-1$
- static public final String GENERATED_FROM = "Generated-from"; //$NON-NLS-1$
- static public final String MANIFEST_TYPE_ATTRIBUTE = "type"; //$NON-NLS-1$
- private static final String[] OS_LIST = {org.eclipse.osgi.service.environment.Constants.OS_AIX, org.eclipse.osgi.service.environment.Constants.OS_HPUX, org.eclipse.osgi.service.environment.Constants.OS_LINUX, org.eclipse.osgi.service.environment.Constants.OS_MACOSX, org.eclipse.osgi.service.environment.Constants.OS_QNX, org.eclipse.osgi.service.environment.Constants.OS_SOLARIS, org.eclipse.osgi.service.environment.Constants.OS_WIN32};
- protected static final String PI_RUNTIME = "org.eclipse.core.runtime"; //$NON-NLS-1$
- protected static final String PI_BOOT = "org.eclipse.core.boot"; //$NON-NLS-1$
- protected static final String PI_RUNTIME_COMPATIBILITY = "org.eclipse.core.runtime.compatibility"; //$NON-NLS-1$
- static public final String PLUGIN_MANIFEST = "plugin.xml"; //$NON-NLS-1$
- private static final String COMPATIBILITY_ACTIVATOR = "org.eclipse.core.internal.compatibility.PluginActivator"; //$NON-NLS-1$
- private static final String[] WS_LIST = {org.eclipse.osgi.service.environment.Constants.WS_CARBON, org.eclipse.osgi.service.environment.Constants.WS_GTK, org.eclipse.osgi.service.environment.Constants.WS_MOTIF, org.eclipse.osgi.service.environment.Constants.WS_PHOTON, org.eclipse.osgi.service.environment.Constants.WS_WIN32};
- private static final String IGNORE_DOT = "@ignoredot@"; //$NON-NLS-1$
-
- public static PluginConverterImpl getDefault() {
- return instance;
- }
-
- public PluginConverterImpl(FrameworkAdaptor adaptor, BundleContext context) {
- this.context = context;
- this.adaptor = adaptor;
- instance = this;
- }
-
- private void init() {
- // need to make sure these fields are cleared out for each conversion.
- out = null;
- pluginInfo = null;
- pluginManifestLocation = null;
- pluginZip = null;
- generatedManifest = new Hashtable<String, String>(10);
- manifestType = MANIFEST_TYPE_UNKNOWN;
- target = null;
- devProperties = null;
- }
-
- private void fillPluginInfo(File pluginBaseLocation) throws PluginConversionException {
- pluginManifestLocation = pluginBaseLocation;
- if (pluginManifestLocation == null)
- throw new IllegalArgumentException();
- InputStream pluginFile = null;
- try {
- try {
- pluginFile = findPluginManifest(pluginBaseLocation);
- } catch (IOException e) {
- throw new PluginConversionException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_FILENOTFOUND, pluginBaseLocation.getAbsolutePath()), e);
- }
- if (pluginFile == null)
- throw new PluginConversionException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_FILENOTFOUND, pluginBaseLocation.getAbsolutePath()));
- pluginInfo = parsePluginInfo(pluginFile);
- } finally {
- if (pluginZip != null)
- try {
- pluginZip.close();
- pluginZip = null;
- } catch (IOException e) {
- // ignore
- }
- }
- String validation = pluginInfo.validateForm();
- if (validation != null)
- throw new PluginConversionException(validation);
- }
-
- private Set<String> filterExport(Set<String> exportToFilter, Collection<String> filter) {
- if (filter == null || filter.contains("*")) //$NON-NLS-1$
- return exportToFilter;
- Set<String> filteredExport = new HashSet<String>(exportToFilter.size());
- for (String anExport : exportToFilter) {
- for (String aFilter : filter) {
- int dotStar = aFilter.indexOf(".*"); //$NON-NLS-1$
- if (dotStar != -1)
- aFilter = aFilter.substring(0, dotStar);
- if (anExport.equals(aFilter)) {
- filteredExport.add(anExport);
- break;
- }
- }
- }
- return filteredExport;
- }
-
- private List<String> findOSJars(File pluginRoot, String path, boolean filter) {
- path = path.substring(4);
- List<String> found = new ArrayList<String>(0);
- for (int i = 0; i < OS_LIST.length; i++) {
- //look for os/osname/path
- String searchedPath = "os/" + OS_LIST[i] + "/" + path; //$NON-NLS-1$ //$NON-NLS-2$
- if (new File(pluginRoot, searchedPath).exists())
- found.add(searchedPath + (filter ? ";(os=" + WS_LIST[i] + ")" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- //look for os/osname/archname/path
- for (int j = 0; j < ARCH_LIST.length; j++) {
- searchedPath = "os/" + OS_LIST[i] + "/" + ARCH_LIST[j] + "/" + path; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- if (new File(pluginRoot, searchedPath).exists()) {
- found.add(searchedPath + (filter ? ";(& (os=" + WS_LIST[i] + ") (arch=" + ARCH_LIST[j] + ")" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- }
- }
- }
- return found;
- }
-
- private InputStream findPluginManifest(File baseLocation) throws IOException {
- //Here, we can not use the bundlefile because it may explode the jar and returns a location from which we will not be able to derive the jars location
- if (pluginZip != null)
- try {
- pluginZip.close();
- } catch (IOException e) {
- // ignore
- }
- pluginZip = null;
- if (!baseLocation.isDirectory()) {
- manifestType |= MANIFEST_TYPE_JAR;
- pluginZip = new ZipFile(baseLocation);
- }
-
- if (pluginZip != null) {
- ZipEntry manifestEntry = pluginZip.getEntry(PLUGIN_MANIFEST);
- if (manifestEntry != null) {
- manifestType |= MANIFEST_TYPE_PLUGIN;
- return pluginZip.getInputStream(manifestEntry);
- }
- } else {
- File manifestFile = new File(baseLocation, PLUGIN_MANIFEST);
- if (manifestFile.exists()) {
- manifestType |= MANIFEST_TYPE_PLUGIN;
- return new FileInputStream(manifestFile);
- }
- }
-
- if (pluginZip != null) {
- ZipEntry manifestEntry = pluginZip.getEntry(FRAGMENT_MANIFEST);
- if (manifestEntry != null) {
- manifestType |= MANIFEST_TYPE_PLUGIN;
- return pluginZip.getInputStream(manifestEntry);
- }
- } else {
- File manifestFile = new File(baseLocation, FRAGMENT_MANIFEST);
- if (manifestFile.exists()) {
- manifestType |= MANIFEST_TYPE_FRAGMENT;
- return new FileInputStream(manifestFile);
- }
- }
-
- return null;
- }
-
- private List<String> findWSJars(File pluginRoot, String path, boolean filter) {
- path = path.substring(4);
- List<String> found = new ArrayList<String>(0);
- for (int i = 0; i < WS_LIST.length; i++) {
- String searchedPath = "ws/" + WS_LIST[i] + path; //$NON-NLS-1$
- if (new File(pluginRoot, searchedPath).exists()) {
- found.add(searchedPath + (filter ? ";(ws=" + WS_LIST[i] + ")" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- }
- return found;
- }
-
- protected void fillManifest(boolean compatibilityManifest, boolean analyseJars) {
- generateManifestVersion();
- generateHeaders();
- generateClasspath();
- generateActivator();
- generatePluginClass();
- if (analyseJars)
- generateProvidePackage();
- generateRequireBundle();
- generateLocalizationEntry();
- generateEclipseHeaders();
- if (compatibilityManifest) {
- generateTimestamp();
- }
- }
-
- @SuppressWarnings("deprecation")
- public void writeManifest(File generationLocation, Dictionary<String, String> manifestToWrite, boolean compatibilityManifest) throws PluginConversionException {
- long start = System.currentTimeMillis();
- try {
- File parentFile = new File(generationLocation.getParent());
- parentFile.mkdirs();
- generationLocation.createNewFile();
- if (!generationLocation.isFile()) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_CREATING_BUNDLE_MANIFEST, this.pluginInfo.getUniqueId(), generationLocation);
- throw new PluginConversionException(message);
- }
- // replaces any eventual existing file
- manifestToWrite = new Hashtable<String, String>((Hashtable) manifestToWrite);
- // MANIFEST.MF files must be written using UTF-8
- out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(generationLocation), UTF_8));
- writeEntry(MANIFEST_VERSION, manifestToWrite.remove(MANIFEST_VERSION));
- writeEntry(GENERATED_FROM, manifestToWrite.remove(GENERATED_FROM)); //Need to do this first uptoDate check expect the generated-from tag to be in the first line
- // always attempt to write the Bundle-ManifestVersion header if it exists (bug 109863)
- writeEntry(Constants.BUNDLE_MANIFESTVERSION, manifestToWrite.remove(Constants.BUNDLE_MANIFESTVERSION));
- writeEntry(Constants.BUNDLE_NAME, manifestToWrite.remove(Constants.BUNDLE_NAME));
- writeEntry(Constants.BUNDLE_SYMBOLICNAME, manifestToWrite.remove(Constants.BUNDLE_SYMBOLICNAME));
- writeEntry(Constants.BUNDLE_VERSION, manifestToWrite.remove(Constants.BUNDLE_VERSION));
- writeEntry(Constants.BUNDLE_CLASSPATH, manifestToWrite.remove(Constants.BUNDLE_CLASSPATH));
- writeEntry(Constants.BUNDLE_ACTIVATOR, manifestToWrite.remove(Constants.BUNDLE_ACTIVATOR));
- writeEntry(Constants.BUNDLE_VENDOR, manifestToWrite.remove(Constants.BUNDLE_VENDOR));
- writeEntry(Constants.FRAGMENT_HOST, manifestToWrite.remove(Constants.FRAGMENT_HOST));
- writeEntry(Constants.BUNDLE_LOCALIZATION, manifestToWrite.remove(Constants.BUNDLE_LOCALIZATION));
- // always attempt to write the Export-Package header if it exists (bug 109863)
- writeEntry(Constants.EXPORT_PACKAGE, manifestToWrite.remove(Constants.EXPORT_PACKAGE));
- // always attempt to write the Provide-Package header if it exists (bug 109863)
- writeEntry(Constants.PROVIDE_PACKAGE, manifestToWrite.remove(Constants.PROVIDE_PACKAGE));
- writeEntry(Constants.REQUIRE_BUNDLE, manifestToWrite.remove(Constants.REQUIRE_BUNDLE));
- Enumeration<String> keys = manifestToWrite.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement();
- writeEntry(key, manifestToWrite.get(key));
- }
- out.flush();
- } catch (IOException e) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_CREATING_BUNDLE_MANIFEST, this.pluginInfo.getUniqueId(), generationLocation);
- throw new PluginConversionException(message, e);
- } finally {
- if (out != null)
- try {
- out.close();
- } catch (IOException e) {
- // only report problems writing to/flushing the file
- }
- }
- if (DEBUG)
- System.out.println("Time to write out converted manifest to: " + generationLocation + ": " + (System.currentTimeMillis() - start) + "ms."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- private void generateLocalizationEntry() {
- generatedManifest.put(Constants.BUNDLE_LOCALIZATION, PLUGIN_PROPERTIES_FILENAME);
- }
-
- private void generateManifestVersion() {
- generatedManifest.put(MANIFEST_VERSION, "1.0"); //$NON-NLS-1$
- }
-
- private boolean requireRuntimeCompatibility() {
- ArrayList<PluginParser.Prerequisite> requireList = pluginInfo.getRequires();
- for (Iterator<PluginParser.Prerequisite> iter = requireList.iterator(); iter.hasNext();) {
- if (iter.next().getName().equalsIgnoreCase(PI_RUNTIME_COMPATIBILITY))
- return true;
- }
- return false;
- }
-
- private void generateActivator() {
- if (!pluginInfo.isFragment())
- if (!requireRuntimeCompatibility()) {
- String pluginClass = pluginInfo.getPluginClass();
- if (pluginClass != null && !pluginClass.trim().equals("")) //$NON-NLS-1$
- generatedManifest.put(Constants.BUNDLE_ACTIVATOR, pluginClass);
- } else {
- generatedManifest.put(Constants.BUNDLE_ACTIVATOR, COMPATIBILITY_ACTIVATOR);
- }
- }
-
- private void generateClasspath() {
- String[] classpath = pluginInfo.getLibrariesName();
- if (classpath.length != 0)
- generatedManifest.put(Constants.BUNDLE_CLASSPATH, getStringFromArray(classpath, LIST_SEPARATOR));
- }
-
- private void generateHeaders() {
- if (TARGET31.compareTo(target) <= 0)
- generatedManifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); //$NON-NLS-1$
- generatedManifest.put(Constants.BUNDLE_NAME, pluginInfo.getPluginName());
- generatedManifest.put(Constants.BUNDLE_VERSION, pluginInfo.getVersion());
- generatedManifest.put(Constants.BUNDLE_SYMBOLICNAME, getSymbolicNameEntry());
- String provider = pluginInfo.getProviderName();
- if (provider != null)
- generatedManifest.put(Constants.BUNDLE_VENDOR, provider);
- if (pluginInfo.isFragment()) {
- StringBuffer hostBundle = new StringBuffer();
- hostBundle.append(pluginInfo.getMasterId());
- String versionRange = getVersionRange(pluginInfo.getMasterVersion(), pluginInfo.getMasterMatch()); // TODO need to get match rule here!
- if (versionRange != null)
- hostBundle.append(versionRange);
- generatedManifest.put(Constants.FRAGMENT_HOST, hostBundle.toString());
- }
- }
-
- /*
- * Generates an entry in the form:
- * <symbolic-name>[; singleton=true]
- */
- private String getSymbolicNameEntry() {
- // false is the default, so don't bother adding anything
- if (!pluginInfo.isSingleton())
- return pluginInfo.getUniqueId();
- StringBuffer result = new StringBuffer(pluginInfo.getUniqueId());
- result.append(SEMICOLON);
- result.append(Constants.SINGLETON_DIRECTIVE);
- String assignment = TARGET31.compareTo(target) <= 0 ? ":=" : "="; //$NON-NLS-1$ //$NON-NLS-2$
- result.append(assignment).append("true"); //$NON-NLS-1$
- return result.toString();
- }
-
- private void generatePluginClass() {
- if (requireRuntimeCompatibility()) {
- String pluginClass = pluginInfo.getPluginClass();
- if (pluginClass != null)
- generatedManifest.put(Constants.PLUGIN_CLASS, pluginClass);
- }
- }
-
- @SuppressWarnings("deprecation")
- private void generateProvidePackage() {
- Set<String> exports = getExports();
- if (exports != null && exports.size() != 0) {
- generatedManifest.put(TARGET31.compareTo(target) <= 0 ? Constants.EXPORT_PACKAGE : Constants.PROVIDE_PACKAGE, getStringFromCollection(exports, LIST_SEPARATOR));
- }
- }
-
- @SuppressWarnings("deprecation")
- private void generateRequireBundle() {
- ArrayList<PluginParser.Prerequisite> requiredBundles = pluginInfo.getRequires();
- if (requiredBundles.size() == 0)
- return;
- StringBuffer bundleRequire = new StringBuffer();
- for (Iterator<PluginParser.Prerequisite> iter = requiredBundles.iterator(); iter.hasNext();) {
- PluginParser.Prerequisite element = iter.next();
- StringBuffer modImport = new StringBuffer(element.getName());
- String versionRange = getVersionRange(element.getVersion(), element.getMatch());
- if (versionRange != null)
- modImport.append(versionRange);
- if (element.isExported()) {
- if (TARGET31.compareTo(target) <= 0)
- modImport.append(';').append(Constants.VISIBILITY_DIRECTIVE).append(":=").append(Constants.VISIBILITY_REEXPORT);//$NON-NLS-1$
- else
- modImport.append(';').append(Constants.REPROVIDE_ATTRIBUTE).append("=true");//$NON-NLS-1$
- }
- if (element.isOptional()) {
- if (TARGET31.compareTo(target) <= 0)
- modImport.append(';').append(Constants.RESOLUTION_DIRECTIVE).append(":=").append(Constants.RESOLUTION_OPTIONAL);//$NON-NLS-1$
- else
- modImport.append(';').append(Constants.OPTIONAL_ATTRIBUTE).append("=true");//$NON-NLS-1$
- }
- bundleRequire.append(modImport.toString());
- if (iter.hasNext())
- bundleRequire.append(LIST_SEPARATOR);
- }
- generatedManifest.put(Constants.REQUIRE_BUNDLE, bundleRequire.toString());
- }
-
- private void generateTimestamp() {
- // so it is easy to tell which ones are generated
- generatedManifest.put(GENERATED_FROM, Long.toString(getTimeStamp(pluginManifestLocation, manifestType)) + ";" + MANIFEST_TYPE_ATTRIBUTE + "=" + manifestType); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- @SuppressWarnings("deprecation")
- private void generateEclipseHeaders() {
- if (pluginInfo.isFragment())
- return;
-
- String pluginClass = pluginInfo.getPluginClass();
- if (pluginInfo.hasExtensionExtensionPoints() || (pluginClass != null && !pluginClass.trim().equals(""))) //$NON-NLS-1$
- generatedManifest.put(TARGET32.compareTo(target) <= 0 ? Constants.ECLIPSE_LAZYSTART : Constants.ECLIPSE_AUTOSTART, "true"); //$NON-NLS-1$
- }
-
- private Set<String> getExports() {
- Map<String, List<String>> libs = pluginInfo.getLibraries();
- if (libs == null)
- return null;
-
- //If we are in dev mode, then add the binary folders on the list libs with the export clause set to be the cumulation of the export clause of the real libs
- if (devProperties != null || DevClassPathHelper.inDevelopmentMode()) {
- String[] devClassPath = DevClassPathHelper.getDevClassPath(pluginInfo.getUniqueId(), devProperties);
- // collect export clauses
- List<String> allExportClauses = new ArrayList<String>(libs.size());
- Set<Map.Entry<String, List<String>>> libEntries = libs.entrySet();
- for (Iterator<Map.Entry<String, List<String>>> iter = libEntries.iterator(); iter.hasNext();) {
- Map.Entry<String, List<String>> element = iter.next();
- allExportClauses.addAll(element.getValue());
- }
- if (devClassPath != null) {
- // bug 88498
- // if there is a devClassPath defined for this plugin and the @ignoredot@ flag is true
- // then we will ignore the '.' library specified in the plugin.xml
- String[] ignoreDotProp = DevClassPathHelper.getDevClassPath(IGNORE_DOT, devProperties);
- if (devClassPath.length > 0 && ignoreDotProp != null && ignoreDotProp.length > 0 && "true".equals(ignoreDotProp[0])) //$NON-NLS-1$
- libs.remove(DOT);
- for (int i = 0; i < devClassPath.length; i++)
- libs.put(devClassPath[i], allExportClauses);
- }
- }
-
- Set<String> result = new TreeSet<String>();
- Set<Map.Entry<String, List<String>>> libEntries = libs.entrySet();
- for (Iterator<Map.Entry<String, List<String>>> iter = libEntries.iterator(); iter.hasNext();) {
- Map.Entry<String, List<String>> element = iter.next();
- List<String> filter = element.getValue();
- if (filter.size() == 0) //If the library is not exported, then ignore it
- continue;
- String libEntryText = element.getKey().trim();
- File libraryLocation;
- if (libEntryText.equals(DOT))
- libraryLocation = pluginManifestLocation;
- else {
- // in development time, libEntries may contain absolute locations (linked folders)
- File libEntryAsPath = new File(libEntryText);
- libraryLocation = libEntryAsPath.isAbsolute() ? libEntryAsPath : new File(pluginManifestLocation, libEntryText);
- }
- Set<String> exports = null;
- if (libraryLocation.exists()) {
- if (libraryLocation.isFile())
- exports = filterExport(getExportsFromJAR(libraryLocation), filter); //TODO Need to handle $xx$ variables
- else if (libraryLocation.isDirectory())
- exports = filterExport(getExportsFromDir(libraryLocation), filter);
- } else {
- List<String> expandedLibs = getLibrariesExpandingVariables(element.getKey(), false);
- exports = new HashSet<String>();
- for (Iterator<String> iterator = expandedLibs.iterator(); iterator.hasNext();) {
- String libName = iterator.next();
- File libFile = new File(pluginManifestLocation, libName);
- if (libFile.isFile()) {
- exports.addAll(filterExport(getExportsFromJAR(libFile), filter));
- }
- }
- }
- if (exports != null)
- result.addAll(exports);
- }
- return result;
- }
-
- private Set<String> getExportsFromDir(File location) {
- return getExportsFromDir(location, ""); //$NON-NLS-1$
- }
-
- private Set<String> getExportsFromDir(File location, String packageName) {
- String prefix = (packageName.length() > 0) ? (packageName + '.') : ""; //$NON-NLS-1$
- String[] files = location.list();
- Set<String> exportedPaths = new HashSet<String>();
- boolean containsFile = false;
- if (files != null)
- for (int i = 0; i < files.length; i++) {
- if (!isValidPackageName(files[i]))
- continue;
- File pkgFile = new File(location, files[i]);
- if (pkgFile.isDirectory())
- exportedPaths.addAll(getExportsFromDir(pkgFile, prefix + files[i]));
- else
- containsFile = true;
- }
- if (containsFile)
- // Allow the default package to be provided. If the default package
- // contains a File then use "." as the package name to provide for default.
- if (packageName.length() > 0)
- exportedPaths.add(packageName);
- else
- exportedPaths.add(DOT);
- return exportedPaths;
- }
-
- private Set<String> getExportsFromJAR(File jarFile) {
- Set<String> names = new HashSet<String>();
- ZipFile file = null;
- try {
- file = new ZipFile(jarFile);
- } catch (IOException e) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_PLUGIN_LIBRARY_IGNORED, jarFile, pluginInfo.getUniqueId());
- adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
- return names;
- }
- //Run through the entries
- for (Enumeration<? extends ZipEntry> entriesEnum = file.entries(); entriesEnum.hasMoreElements();) {
- ZipEntry entry = entriesEnum.nextElement();
- String name = entry.getName();
- if (!isValidPackageName(name))
- continue;
- int lastSlash = name.lastIndexOf("/"); //$NON-NLS-1$
- //Ignore folders that do not contain files
- if (lastSlash != -1) {
- if (lastSlash != name.length() - 1 && name.lastIndexOf(' ') == -1)
- names.add(name.substring(0, lastSlash).replace('/', '.'));
- } else {
- // Allow the default package to be provided. If the default package
- // contains a File then use "." as the package name to provide for default.
- names.add(DOT);
- }
- }
- try {
- file.close();
- } catch (IOException e) {
- // Nothing to do
- }
- return names;
- }
-
- private List<String> getLibrariesExpandingVariables(String libraryPath, boolean filter) {
- String var = hasPrefix(libraryPath);
- if (var == null) {
- List<String> returnValue = new ArrayList<String>(1);
- returnValue.add(libraryPath);
- return returnValue;
- }
- if (var.equals("ws")) { //$NON-NLS-1$
- return findWSJars(pluginManifestLocation, libraryPath, filter);
- }
- if (var.equals("os")) { //$NON-NLS-1$
- return findOSJars(pluginManifestLocation, libraryPath, filter);
- }
- return new ArrayList<String>(0);
- }
-
- //return a String representing the string found between the $s
- private String hasPrefix(String libPath) {
- if (libPath.startsWith("$ws$")) //$NON-NLS-1$
- return "ws"; //$NON-NLS-1$
- if (libPath.startsWith("$os$")) //$NON-NLS-1$
- return "os"; //$NON-NLS-1$
- if (libPath.startsWith("$nl$")) //$NON-NLS-1$
- return "nl"; //$NON-NLS-1$
- return null;
- }
-
- private boolean isValidPackageName(String name) {
- if (name.indexOf(' ') > 0 || name.equalsIgnoreCase("META-INF") || name.startsWith("META-INF/")) //$NON-NLS-1$ //$NON-NLS-2$
- return false;
- return true;
- }
-
- /**
- * Parses the plugin manifest to find out: - the plug-in unique identifier -
- * the plug-in version - runtime/libraries entries - the plug-in class -
- * the master plugin (for a fragment)
- */
- private IPluginInfo parsePluginInfo(InputStream pluginLocation) throws PluginConversionException {
- InputStream input = null;
- try {
- input = new BufferedInputStream(pluginLocation);
- return new PluginParser(adaptor, context, target).parsePlugin(input);
- } catch (Exception e) {
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_PARSING_PLUGIN_MANIFEST, pluginManifestLocation);
- throw new PluginConversionException(message, e);
- } finally {
- if (input != null)
- try {
- input.close();
- } catch (IOException e) {
- //ignore exception
- }
- }
- }
-
- public static boolean upToDate(File generationLocation, File pluginLocation, byte manifestType) {
- if (!generationLocation.isFile())
- return false;
- String secondLine = null;
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new InputStreamReader(new FileInputStream(generationLocation)));
- reader.readLine();
- secondLine = reader.readLine();
- } catch (IOException e) {
- // not a big deal - we could not read an existing manifest
- return false;
- } finally {
- if (reader != null)
- try {
- reader.close();
- } catch (IOException e) {
- // ignore
- }
- }
- String tag = GENERATED_FROM + ": "; //$NON-NLS-1$
- if (secondLine == null || !secondLine.startsWith(tag))
- return false;
-
- secondLine = secondLine.substring(tag.length());
- ManifestElement generatedFrom;
- try {
- generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, secondLine)[0];
- } catch (BundleException be) {
- return false;
- }
- String timestampStr = generatedFrom.getValue();
- try {
- return Long.parseLong(timestampStr.trim()) == getTimeStamp(pluginLocation, manifestType);
- } catch (NumberFormatException nfe) {
- // not a big deal - just a bogus existing manifest that will be ignored
- }
- return false;
- }
-
- public static long getTimeStamp(File pluginLocation, byte manifestType) {
- if ((manifestType & MANIFEST_TYPE_JAR) != 0)
- return pluginLocation.lastModified();
- else if ((manifestType & MANIFEST_TYPE_PLUGIN) != 0)
- return new File(pluginLocation, PLUGIN_MANIFEST).lastModified();
- else if ((manifestType & MANIFEST_TYPE_FRAGMENT) != 0)
- return new File(pluginLocation, FRAGMENT_MANIFEST).lastModified();
- else if ((manifestType & MANIFEST_TYPE_BUNDLE) != 0)
- return new File(pluginLocation, Constants.OSGI_BUNDLE_MANIFEST).lastModified();
- return -1;
- }
-
- private void writeEntry(String key, String value) throws IOException {
- if (value != null && value.length() > 0) {
- out.write(splitOnComma(key + ": " + value)); //$NON-NLS-1$
- out.write('\n');
- }
- }
-
- private String splitOnComma(String value) {
- if (value.length() < MAXLINE || value.indexOf(LINE_SEPARATOR) >= 0)
- return value; // assume the line is already split
- String[] values = ManifestElement.getArrayFromList(value);
- if (values == null || values.length == 0)
- return value;
- StringBuffer sb = new StringBuffer(value.length() + ((values.length - 1) * LIST_SEPARATOR.length()));
- for (int i = 0; i < values.length - 1; i++)
- sb.append(values[i]).append(LIST_SEPARATOR);
- sb.append(values[values.length - 1]);
- return sb.toString();
- }
-
- private String getStringFromArray(String[] values, String separator) {
- if (values == null)
- return ""; //$NON-NLS-1$
- StringBuffer result = new StringBuffer();
- for (int i = 0; i < values.length; i++) {
- if (i > 0)
- result.append(separator);
- result.append(values[i]);
- }
- return result.toString();
- }
-
- private String getStringFromCollection(Collection<String> collection, String separator) {
- StringBuffer result = new StringBuffer();
- boolean first = true;
- for (Iterator<String> i = collection.iterator(); i.hasNext();) {
- if (first)
- first = false;
- else
- result.append(separator);
- result.append(i.next());
- }
- return result.toString();
- }
-
- public synchronized Dictionary<String, String> convertManifest(File pluginBaseLocation, boolean compatibility, String targetVersion, boolean analyseJars, Dictionary<String, String> devProps) throws PluginConversionException {
- long start = System.currentTimeMillis();
- if (DEBUG)
- System.out.println("Convert " + pluginBaseLocation); //$NON-NLS-1$
- init();
- this.target = targetVersion == null ? TARGET32 : new Version(targetVersion);
- this.devProperties = devProps;
- fillPluginInfo(pluginBaseLocation);
- fillManifest(compatibility, analyseJars);
- if (DEBUG)
- System.out.println("Time to convert manifest for: " + pluginBaseLocation + ": " + (System.currentTimeMillis() - start) + "ms."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- return generatedManifest;
- }
-
- public synchronized File convertManifest(File pluginBaseLocation, File bundleManifestLocation, boolean compatibilityManifest, String targetVersion, boolean analyseJars, Dictionary<String, String> devProps) throws PluginConversionException {
- convertManifest(pluginBaseLocation, compatibilityManifest, targetVersion, analyseJars, devProps);
- if (bundleManifestLocation == null) {
- String cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE);
- bundleManifestLocation = new File(cacheLocation, pluginInfo.getUniqueId() + '_' + pluginInfo.getVersion() + ".MF"); //$NON-NLS-1$
- }
- if (upToDate(bundleManifestLocation, pluginManifestLocation, manifestType))
- return bundleManifestLocation;
- writeManifest(bundleManifestLocation, generatedManifest, compatibilityManifest);
- return bundleManifestLocation;
- }
-
- private String getVersionRange(String reqVersion, String matchRule) {
- if (reqVersion == null)
- return null;
-
- Version minVersion = Version.parseVersion(reqVersion);
- String versionRange;
- if (matchRule != null) {
- if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_PERFECT)) {
- versionRange = new VersionRange(minVersion, true, minVersion, true).toString();
- } else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_EQUIVALENT)) {
- versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor(), minVersion.getMinor() + 1, 0, ""), false).toString(); //$NON-NLS-1$
- } else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_COMPATIBLE)) {
- versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor() + 1, 0, 0, ""), false).toString(); //$NON-NLS-1$
- } else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)) {
- // just return the reqVersion here without any version range
- versionRange = reqVersion;
- } else {
- versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor() + 1, 0, 0, ""), false).toString(); //$NON-NLS-1$
- }
- } else {
- versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor() + 1, 0, 0, ""), false).toString(); //$NON-NLS-1$
- }
-
- StringBuffer result = new StringBuffer();
- result.append(';').append(Constants.BUNDLE_VERSION_ATTRIBUTE).append('=');
- result.append('\"').append(versionRange).append('\"');
- return result.toString();
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginParser.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginParser.java
deleted file mode 100644
index 1448b28ff..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/adaptor/PluginParser.java
+++ /dev/null
@@ -1,710 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-import java.io.InputStream;
-import java.util.*;
-import javax.xml.parsers.SAXParserFactory;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Version;
-import org.osgi.util.tracker.ServiceTracker;
-import org.xml.sax.*;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * Internal class.
- */
-public class PluginParser extends DefaultHandler implements IModel {
- private static ServiceTracker<SAXParserFactory, SAXParserFactory> xmlTracker = null;
-
- private PluginInfo manifestInfo = new PluginInfo();
- private BundleContext context;
- private FrameworkAdaptor adaptor;
- Version target; // The targeted platform for the given manifest
- static final Version TARGET21 = new Version(2, 1, 0);
-
- public class PluginInfo implements IPluginInfo {
- String schemaVersion;
- String pluginId;
- String version;
- String vendor;
-
- // an ordered list of library path names.
- List<String> libraryPaths;
- // TODO Should get rid of the libraries map and just have a
- // list of library export statements instead. Library paths must
- // preserve order.
- Map<String, List<String>> libraries; //represent the libraries and their export statement
- ArrayList<PluginParser.Prerequisite> requires;
- private boolean requiresExpanded = false; //indicates if the requires have been processed.
- boolean compatibilityFound = false; //set to true is the requirement list contain compatilibity
- String pluginClass;
- String masterPluginId;
- String masterVersion;
- String masterMatch;
- private Set<String> filters;
- String pluginName;
- boolean singleton;
- boolean fragment;
- private final static String TARGET21_STRING = "2.1"; //$NON-NLS-1$
- boolean hasExtensionExtensionPoints = false;
-
- public boolean isFragment() {
- return fragment;
- }
-
- public String toString() {
- return "plugin-id: " + pluginId + " version: " + version + " libraries: " + libraries + " class:" + pluginClass + " master: " + masterPluginId + " master-version: " + masterVersion + " requires: " + requires + " singleton: " + singleton; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
- }
-
- public Map<String, List<String>> getLibraries() {
- if (libraries == null)
- return new HashMap<String, List<String>>(0);
- return libraries;
- }
-
- public ArrayList<Prerequisite> getRequires() {
- if (!TARGET21.equals(target) && schemaVersion == null && !requiresExpanded) {
- requiresExpanded = true;
- if (requires == null) {
- requires = new ArrayList<Prerequisite>(1);
- requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL));
- requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null));
- } else {
- //Add elements on the requirement list of ui and help.
- for (int i = 0; i < requires.size(); i++) {
- Prerequisite analyzed = requires.get(i);
- if ("org.eclipse.ui".equals(analyzed.getName())) { //$NON-NLS-1$
- requires.add(i + 1, new Prerequisite("org.eclipse.ui.workbench.texteditor", null, true, analyzed.isExported(), null)); //$NON-NLS-1$
- requires.add(i + 1, new Prerequisite("org.eclipse.jface.text", null, true, analyzed.isExported(), null)); //$NON-NLS-1$
- requires.add(i + 1, new Prerequisite("org.eclipse.ui.editors", null, true, analyzed.isExported(), null)); //$NON-NLS-1$
- requires.add(i + 1, new Prerequisite("org.eclipse.ui.views", null, true, analyzed.isExported(), null)); //$NON-NLS-1$
- requires.add(i + 1, new Prerequisite("org.eclipse.ui.ide", null, true, analyzed.isExported(), null)); //$NON-NLS-1$
- } else if ("org.eclipse.help".equals(analyzed.getName())) { //$NON-NLS-1$
- requires.add(i + 1, new Prerequisite("org.eclipse.help.base", null, true, analyzed.isExported(), null)); //$NON-NLS-1$
- } else if (PluginConverterImpl.PI_RUNTIME.equals(analyzed.getName()) && !compatibilityFound) {
- requires.add(i + 1, new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, analyzed.isExported(), null));
- }
- }
- if (!requires.contains(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null))) {
- requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null));
- }
- //Remove any prereq on runtime and add a prereq on runtime 2.1
- //This is used to recognize the version for which the given plugin was initially targeted.
- Prerequisite runtimePrereq = new Prerequisite(PluginConverterImpl.PI_RUNTIME, null, false, false, null);
- requires.remove(runtimePrereq);
- requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL));
- }
- }
- if (requires == null)
- return requires = new ArrayList<Prerequisite>(0);
-
- return requires;
- }
-
- public String getMasterId() {
- return masterPluginId;
- }
-
- public String getMasterVersion() {
- return masterVersion;
- }
-
- public String getMasterMatch() {
- return masterMatch;
- }
-
- public String getPluginClass() {
- return pluginClass;
- }
-
- public String getUniqueId() {
- return pluginId;
- }
-
- public String getVersion() {
- return version;
- }
-
- public Set<String> getPackageFilters() {
- return filters;
- }
-
- public String[] getLibrariesName() {
- if (libraryPaths == null)
- return new String[0];
- return libraryPaths.toArray(new String[libraryPaths.size()]);
- }
-
- public String getPluginName() {
- return pluginName;
- }
-
- public String getProviderName() {
- return vendor;
- }
-
- public boolean isSingleton() {
- return singleton;
- }
-
- public boolean hasExtensionExtensionPoints() {
- return hasExtensionExtensionPoints;
- }
-
- public String getRoot() {
- return isFragment() ? FRAGMENT : PLUGIN;
- }
-
- /*
- * Provides some basic form of validation. Since plugin/fragment is the only mandatory
- * attribute, it is the only one we cara about here.
- */
- public String validateForm() {
- if (this.pluginId == null)
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), PLUGIN_ID, getRoot()});
- if (this.pluginName == null)
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), PLUGIN_NAME, getRoot()});
- if (this.version == null)
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), PLUGIN_VERSION, getRoot()});
- if (isFragment() && this.masterPluginId == null)
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), FRAGMENT_PLUGIN_ID, getRoot()});
- if (isFragment() && this.masterVersion == null)
- return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), FRAGMENT_PLUGIN_VERSION, getRoot()});
- return null;
- }
- }
-
- // Current State Information
- Stack<Integer> stateStack = new Stack<Integer>();
-
- // Current object stack (used to hold the current object we are populating in this plugin info
- Stack<Object> objectStack = new Stack<Object>();
- Locator locator = null;
-
- // Valid States
- private static final int IGNORED_ELEMENT_STATE = 0;
- private static final int INITIAL_STATE = 1;
- private static final int PLUGIN_STATE = 2;
- private static final int PLUGIN_RUNTIME_STATE = 3;
- private static final int PLUGIN_REQUIRES_STATE = 4;
- private static final int PLUGIN_EXTENSION_POINT_STATE = 5;
- private static final int PLUGIN_EXTENSION_STATE = 6;
- private static final int RUNTIME_LIBRARY_STATE = 7;
- private static final int LIBRARY_EXPORT_STATE = 8;
- private static final int PLUGIN_REQUIRES_IMPORT_STATE = 9;
- private static final int FRAGMENT_STATE = 11;
-
- public PluginParser(FrameworkAdaptor adaptor, BundleContext context, Version target) {
- super();
- this.context = context;
- this.adaptor = adaptor;
- this.target = target;
- }
-
- /**
- * Receive a Locator object for document events.
- *
- * <p>
- * By default, do nothing. Application writers may override this method in
- * a subclass if they wish to store the locator for use with other document
- * events.
- * </p>
- *
- * @param locator A locator for all SAX document events.
- * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
- * @see org.xml.sax.Locator
- */
- public void setDocumentLocator(Locator locator) {
- this.locator = locator;
- }
-
- public void endDocument() {
- // nothing
- }
-
- public void endElement(String uri, String elementName, String qName) {
- switch (stateStack.peek().intValue()) {
- case IGNORED_ELEMENT_STATE :
- stateStack.pop();
- break;
- case INITIAL_STATE :
- // shouldn't get here
- // internalError(Policy.bind("parse.internalStack", elementName)); //$NON-NLS-1$
- break;
- case PLUGIN_STATE :
- case FRAGMENT_STATE :
- break;
- case PLUGIN_RUNTIME_STATE :
- if (elementName.equals(RUNTIME)) {
- stateStack.pop();
- }
- break;
- case PLUGIN_REQUIRES_STATE :
- if (elementName.equals(PLUGIN_REQUIRES)) {
- stateStack.pop();
- objectStack.pop();
- }
- break;
- case PLUGIN_EXTENSION_POINT_STATE :
- if (elementName.equals(EXTENSION_POINT)) {
- stateStack.pop();
- }
- break;
- case PLUGIN_EXTENSION_STATE :
- if (elementName.equals(EXTENSION)) {
- stateStack.pop();
- }
- break;
- case RUNTIME_LIBRARY_STATE :
- if (elementName.equals(LIBRARY)) {
- String curLibrary = (String) objectStack.pop();
- if (!curLibrary.trim().equals("")) { //$NON-NLS-1$
- @SuppressWarnings("unchecked")
- List<String> exports = (List<String>) objectStack.pop();
- if (manifestInfo.libraries == null) {
- manifestInfo.libraries = new HashMap<String, List<String>>(3);
- manifestInfo.libraryPaths = new ArrayList<String>(3);
- }
- manifestInfo.libraries.put(curLibrary, exports);
- manifestInfo.libraryPaths.add(curLibrary.replace('\\', '/'));
- }
- stateStack.pop();
- }
- break;
- case LIBRARY_EXPORT_STATE :
- if (elementName.equals(LIBRARY_EXPORT)) {
- stateStack.pop();
- }
- break;
- case PLUGIN_REQUIRES_IMPORT_STATE :
- if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) {
- stateStack.pop();
- }
- break;
- }
- }
-
- public void error(SAXParseException ex) {
- logStatus(ex);
- }
-
- public void fatalError(SAXParseException ex) throws SAXException {
- logStatus(ex);
- throw ex;
- }
-
- public void handleExtensionPointState(String elementName, Attributes attributes) {
- // nothing to do for extension-points' children
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- manifestInfo.hasExtensionExtensionPoints = true;
- }
-
- public void handleExtensionState(String elementName, Attributes attributes) {
- // nothing to do for extensions' children
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- manifestInfo.hasExtensionExtensionPoints = true;
- }
-
- public void handleInitialState(String elementName, Attributes attributes) {
- if (elementName.equals(PLUGIN)) {
- stateStack.push(new Integer(PLUGIN_STATE));
- parsePluginAttributes(attributes);
- } else if (elementName.equals(FRAGMENT)) {
- manifestInfo.fragment = true;
- stateStack.push(new Integer(FRAGMENT_STATE));
- parseFragmentAttributes(attributes);
- } else {
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- internalError(elementName);
- }
- }
-
- public void handleLibraryExportState(String elementName, Attributes attributes) {
- // All elements ignored.
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- }
-
- public void handleLibraryState(String elementName, Attributes attributes) {
- if (elementName.equals(LIBRARY_EXPORT)) {
- // Change State
- stateStack.push(new Integer(LIBRARY_EXPORT_STATE));
- // The top element on the stack much be a library element
- String currentLib = (String) objectStack.peek();
- if (attributes == null)
- return;
- String maskValue = attributes.getValue("", LIBRARY_EXPORT_MASK); //$NON-NLS-1$
- // pop off the library - already in currentLib
- objectStack.pop();
- @SuppressWarnings("unchecked")
- List<String> exportMask = (List<String>) objectStack.peek();
- // push library back on
- objectStack.push(currentLib);
- //Split the export upfront
- if (maskValue != null) {
- StringTokenizer tok = new StringTokenizer(maskValue, ","); //$NON-NLS-1$
- while (tok.hasMoreTokens()) {
- String value = tok.nextToken();
- if (!exportMask.contains(maskValue))
- exportMask.add(value.trim());
- }
- }
- return;
- }
- if (elementName.equals(LIBRARY_PACKAGES)) {
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- return;
- }
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- internalError(elementName);
- return;
- }
-
- public void handlePluginState(String elementName, Attributes attributes) {
- if (elementName.equals(RUNTIME)) {
- // We should only have one Runtime element in a plugin or fragment
- Object whatIsIt = objectStack.peek();
- if ((whatIsIt instanceof PluginInfo) && ((PluginInfo) objectStack.peek()).libraries != null) {
- // This is at least the 2nd Runtime element we have hit. Ignore it.
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- return;
- }
- stateStack.push(new Integer(PLUGIN_RUNTIME_STATE));
- // Push a new vector to hold all the library entries objectStack.push(new Vector());
- return;
- }
- if (elementName.equals(PLUGIN_REQUIRES)) {
- stateStack.push(new Integer(PLUGIN_REQUIRES_STATE));
- // Push a new vector to hold all the prerequisites
- objectStack.push(new ArrayList<String>());
- parseRequiresAttributes(attributes);
- return;
- }
- if (elementName.equals(EXTENSION_POINT)) {
- // mark the plugin as singleton and ignore all elements under extension (if there are any)
- manifestInfo.singleton = true;
- stateStack.push(new Integer(PLUGIN_EXTENSION_POINT_STATE));
- return;
- }
- if (elementName.equals(EXTENSION)) {
- // mark the plugin as singleton and ignore all elements under extension (if there are any)
- manifestInfo.singleton = true;
- stateStack.push(new Integer(PLUGIN_EXTENSION_STATE));
- return;
- }
- // If we get to this point, the element name is one we don't currently accept.
- // Set the state to indicate that this element will be ignored
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- internalError(elementName);
- }
-
- public void handleRequiresImportState(String elementName, Attributes attributes) {
- // All elements ignored.
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- }
-
- public void handleRequiresState(String elementName, Attributes attributes) {
- if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) {
- parsePluginRequiresImport(attributes);
- return;
- }
- // If we get to this point, the element name is one we don't currently accept.
- // Set the state to indicate that this element will be ignored
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- internalError(elementName);
- }
-
- public void handleRuntimeState(String elementName, Attributes attributes) {
- if (elementName.equals(LIBRARY)) {
- // Change State
- stateStack.push(new Integer(RUNTIME_LIBRARY_STATE));
- // Process library attributes
- parseLibraryAttributes(attributes);
- return;
- }
- // If we get to this point, the element name is one we don't currently accept.
- // Set the state to indicate that this element will be ignored
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- internalError(elementName);
- }
-
- private void logStatus(SAXParseException ex) {
- String name = ex.getSystemId();
- if (name == null)
- name = ""; //$NON-NLS-1$
- else
- name = name.substring(1 + name.lastIndexOf("/")); //$NON-NLS-1$
- String msg;
- if (name.equals("")) //$NON-NLS-1$
- msg = NLS.bind(EclipseAdaptorMsg.parse_error, ex.getMessage());
- else
- msg = NLS.bind(EclipseAdaptorMsg.parse_errorNameLineColumn, new String[] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()});
-
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, msg, 0, ex, null);
- adaptor.getFrameworkLog().log(entry);
- }
-
- synchronized public PluginInfo parsePlugin(InputStream in) throws Exception {
- SAXParserFactory factory = acquireXMLParsing(context);
- if (factory == null) {
- FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_CONVERTER_NO_SAX_FACTORY, 0, null, null);
- adaptor.getFrameworkLog().log(entry);
- return null;
- }
-
- factory.setNamespaceAware(true);
- factory.setNamespaceAware(true);
- try {
- factory.setFeature("http://xml.org/sax/features/string-interning", true); //$NON-NLS-1$
- } catch (SAXException se) {
- // ignore; we can still operate without string-interning
- }
- factory.setValidating(false);
- factory.newSAXParser().parse(in, this);
- return manifestInfo;
- }
-
- public static SAXParserFactory acquireXMLParsing(BundleContext context) {
- if (xmlTracker == null) {
- xmlTracker = new ServiceTracker<SAXParserFactory, SAXParserFactory>(context, "javax.xml.parsers.SAXParserFactory", null); //$NON-NLS-1$
- xmlTracker.open();
- }
- SAXParserFactory result = xmlTracker.getService();
- if (result != null)
- return result;
- // backup to using jaxp to create a new instance
- return SAXParserFactory.newInstance();
- }
-
- public static void releaseXMLParsing() {
- if (xmlTracker != null)
- xmlTracker.close();
- }
-
- public void parseFragmentAttributes(Attributes attributes) {
- // process attributes
- objectStack.push(manifestInfo);
- int len = attributes.getLength();
- for (int i = 0; i < len; i++) {
- String attrName = attributes.getLocalName(i);
- String attrValue = attributes.getValue(i).trim();
- if (attrName.equals(FRAGMENT_ID))
- manifestInfo.pluginId = attrValue;
- else if (attrName.equals(FRAGMENT_NAME))
- manifestInfo.pluginName = attrValue;
- else if (attrName.equals(FRAGMENT_VERSION))
- manifestInfo.version = attrValue;
- else if (attrName.equals(FRAGMENT_PROVIDER))
- manifestInfo.vendor = attrValue;
- else if (attrName.equals(FRAGMENT_PLUGIN_ID))
- manifestInfo.masterPluginId = attrValue;
- else if (attrName.equals(FRAGMENT_PLUGIN_VERSION))
- manifestInfo.masterVersion = attrValue;
- else if (attrName.equals(FRAGMENT_PLUGIN_MATCH))
- manifestInfo.masterMatch = attrValue;
- }
- }
-
- public void parseLibraryAttributes(Attributes attributes) {
- // Push a vector to hold the export mask
- objectStack.push(new ArrayList<String>());
- String current = attributes.getValue("", LIBRARY_NAME); //$NON-NLS-1$
- objectStack.push(current);
- }
-
- public void parsePluginAttributes(Attributes attributes) {
- // process attributes
- objectStack.push(manifestInfo);
- int len = attributes.getLength();
- for (int i = 0; i < len; i++) {
- String attrName = attributes.getLocalName(i);
- String attrValue = attributes.getValue(i).trim();
- if (attrName.equals(PLUGIN_ID))
- manifestInfo.pluginId = attrValue;
- else if (attrName.equals(PLUGIN_NAME))
- manifestInfo.pluginName = attrValue;
- else if (attrName.equals(PLUGIN_VERSION))
- manifestInfo.version = attrValue;
- else if (attrName.equals(PLUGIN_VENDOR) || (attrName.equals(PLUGIN_PROVIDER)))
- manifestInfo.vendor = attrValue;
- else if (attrName.equals(PLUGIN_CLASS))
- manifestInfo.pluginClass = attrValue;
- }
- }
-
- public class Prerequisite {
- String name;
- String version;
- boolean optional;
- boolean export;
- String match;
-
- public boolean isExported() {
- return export;
- }
-
- public String getMatch() {
- return match;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isOptional() {
- return optional;
- }
-
- public String getVersion() {
- return version;
- }
-
- public Prerequisite(String preqName, String prereqVersion, boolean isOtional, boolean isExported, String prereqMatch) {
- name = preqName;
- version = prereqVersion;
- optional = isOtional;
- export = isExported;
- match = prereqMatch;
- }
-
- public String toString() {
- return name;
- }
-
- public boolean equals(Object prereq) {
- if (!(prereq instanceof Prerequisite))
- return false;
- return name.equals(((Prerequisite) prereq).name);
- }
-
- public int hashCode() {
- return name.hashCode();
- }
- }
-
- public void parsePluginRequiresImport(Attributes attributes) {
- if (manifestInfo.requires == null) {
- manifestInfo.requires = new ArrayList<Prerequisite>();
- // to avoid cycles
- // if (!manifestInfo.pluginId.equals(PluginConverterImpl.PI_RUNTIME)) //$NON-NLS-1$
- // manifestInfo.requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, null, false, false, null)); //$NON-NLS-1$
- }
- // process attributes
- String plugin = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN); //$NON-NLS-1$
- if (plugin == null)
- return;
- if (plugin.equals(PluginConverterImpl.PI_BOOT))
- return;
- if (plugin.equals(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY))
- manifestInfo.compatibilityFound = true;
- String version = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN_VERSION); //$NON-NLS-1$
- String optional = attributes.getValue("", PLUGIN_REQUIRES_OPTIONAL); //$NON-NLS-1$
- String export = attributes.getValue("", PLUGIN_REQUIRES_EXPORT); //$NON-NLS-1$
- String match = attributes.getValue("", PLUGIN_REQUIRES_MATCH); //$NON-NLS-1$
- manifestInfo.requires.add(new Prerequisite(plugin, version, "true".equalsIgnoreCase(optional) ? true : false, "true".equalsIgnoreCase(export) ? true : false, match)); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- public void parseRequiresAttributes(Attributes attributes) {
- //Nothing to do.
- }
-
- static String replace(String s, String from, String to) {
- String str = s;
- int fromLen = from.length();
- int toLen = to.length();
- int ix = str.indexOf(from);
- while (ix != -1) {
- str = str.substring(0, ix) + to + str.substring(ix + fromLen);
- ix = str.indexOf(from, ix + toLen);
- }
- return str;
- }
-
- public void startDocument() {
- stateStack.push(new Integer(INITIAL_STATE));
- }
-
- public void startElement(String uri, String elementName, String qName, Attributes attributes) {
- switch (stateStack.peek().intValue()) {
- case INITIAL_STATE :
- handleInitialState(elementName, attributes);
- break;
- case FRAGMENT_STATE :
- case PLUGIN_STATE :
- handlePluginState(elementName, attributes);
- break;
- case PLUGIN_RUNTIME_STATE :
- handleRuntimeState(elementName, attributes);
- break;
- case PLUGIN_REQUIRES_STATE :
- handleRequiresState(elementName, attributes);
- break;
- case PLUGIN_EXTENSION_POINT_STATE :
- handleExtensionPointState(elementName, attributes);
- break;
- case PLUGIN_EXTENSION_STATE :
- handleExtensionState(elementName, attributes);
- break;
- case RUNTIME_LIBRARY_STATE :
- handleLibraryState(elementName, attributes);
- break;
- case LIBRARY_EXPORT_STATE :
- handleLibraryExportState(elementName, attributes);
- break;
- case PLUGIN_REQUIRES_IMPORT_STATE :
- handleRequiresImportState(elementName, attributes);
- break;
- default :
- stateStack.push(new Integer(IGNORED_ELEMENT_STATE));
- }
- }
-
- public void warning(SAXParseException ex) {
- logStatus(ex);
- }
-
- private void internalError(String elementName) {
- FrameworkLogEntry error;
- String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_PARSE_UNKNOWNTOP_ELEMENT, elementName);
- error = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, (manifestInfo.pluginId == null ? message : "Plug-in : " + manifestInfo.pluginId + ", " + message), 0, null, null); //$NON-NLS-1$ //$NON-NLS-2$
- adaptor.getFrameworkLog().log(error);
- }
-
- /**
- * @throws SAXException
- */
- public void processingInstruction(String instructionTarget, String data) throws SAXException {
- // Since 3.0, a processing instruction of the form <?eclipse version="3.0"?> at
- // the start of the manifest file is used to indicate the plug-in manifest
- // schema version in effect. Pre-3.0 (i.e., 2.1) plug-in manifest files do not
- // have one of these, and this is how we can distinguish the manifest of a
- // pre-3.0 plug-in from a post-3.0 one (for compatibility tranformations).
- if (instructionTarget.equalsIgnoreCase("eclipse")) { //$NON-NLS-1$
- // just the presence of this processing instruction indicates that this
- // plug-in is at least 3.0
- manifestInfo.schemaVersion = "3.0"; //$NON-NLS-1$
- StringTokenizer tokenizer = new StringTokenizer(data, "=\""); //$NON-NLS-1$
- while (tokenizer.hasMoreTokens()) {
- String token = tokenizer.nextToken();
- if (token.equalsIgnoreCase("version")) { //$NON-NLS-1$
- if (!tokenizer.hasMoreTokens()) {
- break;
- }
- manifestInfo.schemaVersion = tokenizer.nextToken();
- break;
- }
- }
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/BundleStats.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/BundleStats.java
deleted file mode 100644
index f021dfc9b..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/BundleStats.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.stats;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Contains information about activated bundles and acts as the main
- * entry point for logging bundle activity.
- */
-
-public class BundleStats {
- public String symbolicName;
- public long id;
- public int activationOrder;
- private long timestamp; //timeStamp at which this bundle has been activated
- private boolean duringStartup; // indicate if the bundle has been activated during startup
- private long startupTime; // the time took by the bundle to startup
- private long startupMethodTime; // the time took to run the startup method
-
- // Indicate the position of the activation trace in the file
- private long traceStart = -1;
- private long traceEnd = -1;
-
- //To keep bundle parentage
- private List<BundleStats> bundlesActivated = new ArrayList<BundleStats>(3); // TODO create lazily
- private BundleStats activatedBy = null;
-
- public BundleStats(String name, long id) {
- this.symbolicName = name;
- this.id = id;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public int getActivationOrder() {
- return activationOrder;
- }
-
- protected void activated(BundleStats info) {
- bundlesActivated.add(info);
- }
-
- public BundleStats getActivatedBy() {
- return activatedBy;
- }
-
- public long getId() {
- return id;
- }
-
- public String getSymbolicName() {
- return symbolicName;
- }
-
- public long getStartupTime() {
- return startupTime;
- }
-
- public long getStartupMethodTime() {
- return startupMethodTime;
- }
-
- public boolean isStartupBundle() {
- return duringStartup;
- }
-
- public int getClassLoadCount() {
- if (!StatsManager.MONITOR_CLASSES)
- return 0;
- ClassloaderStats loader = ClassloaderStats.getLoader(symbolicName);
- return loader == null ? 0 : loader.getClassLoadCount();
- }
-
- public long getClassLoadTime() {
- if (!StatsManager.MONITOR_CLASSES)
- return 0;
- ClassloaderStats loader = ClassloaderStats.getLoader(symbolicName);
- return loader == null ? 0 : loader.getClassLoadTime();
- }
-
- public List<BundleStats> getBundlesActivated() {
- return bundlesActivated;
- }
-
- public long getTraceStart() {
- return traceStart;
- }
-
- public long getTraceEnd() {
- return traceEnd;
- }
-
- protected void setTimestamp(long value) {
- timestamp = value;
- }
-
- protected void setActivationOrder(int value) {
- activationOrder = value;
- }
-
- protected void setTraceStart(long time) {
- traceStart = time;
- }
-
- protected void setDuringStartup(boolean value) {
- duringStartup = value;
- }
-
- protected void endActivation() {
- startupTime = System.currentTimeMillis() - timestamp;
- }
-
- protected void setTraceEnd(long position) {
- traceEnd = position;
- }
-
- protected void setActivatedBy(BundleStats value) {
- activatedBy = value;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassStats.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassStats.java
deleted file mode 100644
index 092dd156e..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassStats.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.stats;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Maintain statistics about a loaded class.
- */
-public class ClassStats {
- private String className; // fully qualified name of this class
- private ClassloaderStats classloader; // the classloader that loaded this class
- private int loadOrder = -1;
-
- private long timestamp; // time at which this class was loaded
- private long timeLoading; // time to load the class
- private long timeLoadingOthers = 0; // time spent loading classes which has been triggered by this class
-
- // parentage of classes loaded
- private ClassStats loadedBy = null; // a reference to the class that loaded this class
- private List<ClassStats> loaded = new ArrayList<ClassStats>(2); // a reference to the classes that this class loaded
-
- private boolean duringStartup; // indicate if the class was loaded during platform startup
-
- //information to retrieve the stacktrace from the file
- private long traceStart = -1;
- private long traceEnd = -1;
-
- public ClassStats(String name, ClassloaderStats classloader) {
- className = name;
- timestamp = System.currentTimeMillis();
- duringStartup = StatsManager.isBooting();
- this.classloader = classloader;
- }
-
- public void setLoadOrder(int order) {
- loadOrder = order;
- }
-
- public void loadingDone() {
- timeLoading = System.currentTimeMillis() - timestamp;
- }
-
- public long getTimeLoading() {
- return timeLoading;
- }
-
- public long getLocalTimeLoading() {
- return timeLoading - timeLoadingOthers;
- }
-
- public void addTimeLoadingOthers(long time) {
- timeLoadingOthers = timeLoadingOthers + time;
- }
-
- public long getTraceStart() {
- return traceStart;
- }
-
- public long getTraceEnd() {
- return traceEnd;
- }
-
- public void setTraceStart(long position) {
- traceStart = position;
- }
-
- public void setTraceEnd(long position) {
- traceEnd = position;
- }
-
- public void loaded(ClassStats child) {
- loaded.add(child);
- }
-
- public void setLoadedBy(ClassStats parent) {
- loadedBy = parent;
- }
-
- public ClassStats getLoadedBy() {
- return loadedBy;
- }
-
- public List<ClassStats> getLoadedClasses() {
- return loaded;
- }
-
- public String getClassName() {
- return className;
- }
-
- public boolean isStartupClass() {
- return duringStartup;
- }
-
- public ClassloaderStats getClassloader() {
- return classloader;
- }
-
- public int getLoadOrder() {
- return loadOrder;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public void toBaseClass() {
- duringStartup = true;
- loadOrder = -2;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassloaderStats.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassloaderStats.java
deleted file mode 100644
index f34da3da3..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ClassloaderStats.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.stats;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Contains information about the classes and the bundles loaded by a given classloader. Typically there is one classloader per plugin so at levels above boot, this equates to information about
- * classes and bundles in a plugin.
- */
-public class ClassloaderStats {
- private String id;
- private long loadingTime; // time spent loading classes
- /**
- * classes loaded by the plugin (key: class name, value: ClassStats)
- */
- private Map<String, ClassStats> classes = Collections.synchronizedMap(new HashMap<String, ClassStats>(20));
- private List<ResourceBundleStats> bundles = new ArrayList<ResourceBundleStats>(2); // bundles loaded
-
- private boolean keepTraces = false; // indicate whether or not the traces of classes loaded are kept
-
- // filters to indicate which classes we want to keep the traces
- private static List<String> packageFilters = new ArrayList<String>(4); // filters on a package basis
- private static Set<String> pluginFilters = new HashSet<String>(5); // filters on a plugin basis
-
- private static Hashtable<Thread, Stack<ClassStats>> classStacks = new Hashtable<Thread, Stack<ClassStats>>(); // represents the classes that are currently being loaded
- /**
- * a dictionary of the classloaderStats (key: pluginId, value: ClassloaderStats)
- */
- private static Map<String, ClassloaderStats> loaders = Collections.synchronizedMap(new HashMap<String, ClassloaderStats>(20));
- public static File traceFile;
-
- static {
- if (StatsManager.TRACE_CLASSES || StatsManager.TRACE_BUNDLES)
- initializeTraceOptions();
- }
-
- private static void initializeTraceOptions() {
- // create the trace file
- String filename = StatsManager.TRACE_FILENAME;
- traceFile = new File(filename);
- traceFile.delete();
-
- //load the filters
- if (!StatsManager.TRACE_CLASSES)
- return;
- filename = StatsManager.TRACE_FILTERS;
- if (filename == null || filename.length() == 0)
- return;
- try {
- File filterFile = new File(filename);
- System.out.print("Runtime tracing elements defined in: " + filterFile.getAbsolutePath() + "..."); //$NON-NLS-1$ //$NON-NLS-2$
- InputStream input = new FileInputStream(filterFile);
- System.out.println(" Loaded."); //$NON-NLS-1$
- Properties filters = new Properties() {
- private static final long serialVersionUID = 3546359543853365296L;
-
- public synchronized Object put(Object key, Object value) {
- addFilters((String) key, (String) value);
- return null;
- }
- };
- try {
- filters.load(input);
- } finally {
- input.close();
- }
- } catch (IOException e) {
- System.out.println(" No trace filters loaded."); //$NON-NLS-1$
- }
- }
-
- protected static void addFilters(String key, String value) {
- String[] filters = StatsManager.getArrayFromList(value);
- if ("plugins".equals(key)) //$NON-NLS-1$
- pluginFilters.addAll(Arrays.asList(filters));
- if ("packages".equals(key)) //$NON-NLS-1$
- packageFilters.addAll(Arrays.asList(filters));
- }
-
- public static void startLoadingClass(String id, String className) {
- findLoader(id).startLoadClass(className);
- }
-
- // get and create if does not exist
- private static ClassloaderStats findLoader(String id) {
- synchronized (loaders) {
- ClassloaderStats result = loaders.get(id);
- if (result == null) {
- result = new ClassloaderStats(id);
- loaders.put(id, result);
- }
- return result;
- }
- }
-
- public static synchronized Stack<ClassStats> getClassStack() {
- Stack<ClassStats> result = classStacks.get(Thread.currentThread());
- if (result == null) {
- result = new Stack<ClassStats>();
- classStacks.put(Thread.currentThread(), result);
- }
- return result;
- }
-
- public static ClassloaderStats[] getLoaders() {
- //the parameter to toArray is of size zero for thread safety, otherwise this
- //could return an array with null entries if the map shrinks concurrently
- return loaders.values().toArray(new ClassloaderStats[0]);
- }
-
- public static void endLoadingClass(String id, String className, boolean success) {
- findLoader(id).endLoadClass(className, success);
- }
-
- public static void loadedBundle(String id, ResourceBundleStats info) {
- findLoader(id).loadedBundle(info);
- }
-
- public static ClassloaderStats getLoader(String id) {
- return loaders.get(id);
- }
-
- public ClassloaderStats(String id) {
- this.id = id;
- keepTraces = pluginFilters.contains(id);
- }
-
- public void addBaseClasses(String[] baseClasses) {
- for (int i = 0; i < baseClasses.length; i++) {
- String name = baseClasses[i];
- if (classes.get(name) == null) {
- ClassStats value = new ClassStats(name, this);
- value.toBaseClass();
- classes.put(name, value);
- }
- }
- }
-
- private void loadedBundle(ResourceBundleStats bundle) {
- bundles.add(bundle);
- }
-
- public List<ResourceBundleStats> getBundles() {
- return bundles;
- }
-
- private synchronized void startLoadClass(String name) {
- getClassStack().push(findClass(name));
- }
-
- // internal method that return the existing classStats or creates one
- private ClassStats findClass(String name) {
- ClassStats result = classes.get(name);
- return result == null ? new ClassStats(name, this) : result;
- }
-
- private synchronized void endLoadClass(String name, boolean success) {
- ClassStats current = getClassStack().pop();
- if (!success)
- return;
- if (current.getLoadOrder() >= 0)
- return;
-
- classes.put(name, current);
- current.setLoadOrder(classes.size());
- current.loadingDone();
- traceLoad(name, current);
-
- // is there something on the load stack. if so, link them together...
- Stack<ClassStats> classStack = getClassStack();
- if (classStack.size() != 0) {
- // get the time spent loading cli and subtract its load time from the class that requires loading
- ClassStats previous = classStack.peek();
- previous.addTimeLoadingOthers(current.getTimeLoading());
- current.setLoadedBy(previous);
- previous.loaded(current);
- } else {
- loadingTime = loadingTime + current.getTimeLoading();
- }
- }
-
- private void traceLoad(String name, ClassStats target) {
- // Stack trace code
- if (!keepTraces) {
- boolean found = false;
- for (int i = 0; !found && i < packageFilters.size(); i++)
- if (name.startsWith(packageFilters.get(i)))
- found = true;
- if (!found)
- return;
- }
-
- // Write the stack trace. The position in the file are set to the corresponding classStat object
- try {
- target.setTraceStart(traceFile.length());
- PrintWriter output = new PrintWriter(new FileOutputStream(traceFile.getAbsolutePath(), true));
- try {
- output.println("Loading class: " + name); //$NON-NLS-1$
- output.println("Class loading stack:"); //$NON-NLS-1$
- output.println("\t" + name); //$NON-NLS-1$
- Stack<ClassStats> classStack = getClassStack();
- for (int i = classStack.size() - 1; i >= 0; i--)
- output.println("\t" + classStack.get(i).getClassName()); //$NON-NLS-1$
- output.println("Stack trace:"); //$NON-NLS-1$
- new Throwable().printStackTrace(output);
- } finally {
- output.close();
- }
- target.setTraceEnd(traceFile.length());
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
-
- public int getClassLoadCount() {
- return classes.size();
- }
-
- public long getClassLoadTime() {
- return loadingTime;
- }
-
- public ClassStats[] getClasses() {
- //the parameter to toArray is of size zero for thread safety, otherwise this
- //could return an array with null entries if the map shrinks concurrently
- return classes.values().toArray(new ClassStats[0]);
- }
-
- public String getId() {
- return id;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ResourceBundleStats.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ResourceBundleStats.java
deleted file mode 100644
index 2c072f91c..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/ResourceBundleStats.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.stats;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.*;
-
-/**
- * BundleStats is used to represent information about loaded bundle. A
- * bundlestats instance represents only one bundle.
- */
-
-public class ResourceBundleStats {
- private String pluginId; // the plugin loading this bundle
- private String fileName; // the filename of the bundle
- private int keyCount = 0; // number of keys in the bundle
- private int keySize = 0; // size of the keys in the bundle
- private int valueSize = 0; // size of the values in the bundle
- private long hashSize = 0; // size of the hashtable
- private long fileSize = 0;
-
- private static int sizeOf(String value) {
- return 44 + (2 * value.length());
- }
-
- private static int sizeOf(Properties value) {
- return (int) Math.round(44 + (16 + (value.size() * 1.25 * 4)) + (24 * value.size()));
- }
-
- public ResourceBundleStats(String pluginId, String fileName, URL input) {
- this.pluginId = pluginId;
- this.fileName = fileName;
- initialize(input);
- }
-
- public ResourceBundleStats(String pluginId, String fileName, ResourceBundle bundle) {
- this.pluginId = pluginId;
- this.fileName = fileName;
- initialize(bundle);
- }
-
- /**
- * Compute the size of bundle
- */
- private void initialize(ResourceBundle bundle) {
- for (Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) {
- String key = keys.nextElement();
- keySize += sizeOf(key);
- valueSize += sizeOf(bundle.getString(key));
- keyCount++;
- }
- }
-
- /**
- * Compute the size of stream which represents a property file
- */
- private void initialize(URL url) {
- InputStream stream = null;
- Properties props = new Properties();
- try {
- try {
- stream = url.openStream();
- fileSize = stream.available();
- props.load(stream);
- for (Iterator<Object> iter = props.keySet().iterator(); iter.hasNext();) {
- String key = (String) iter.next();
- keySize += sizeOf(key);
- valueSize += sizeOf(props.getProperty(key));
- keyCount++;
- }
- hashSize = sizeOf(props);
- } finally {
- if (stream != null)
- stream.close();
- }
- } catch (IOException e) {
- // ignore exceptions as they will be handled when the stream
- // is loaded for real. See callers.
- }
- }
-
- public long getHashSize() {
- return hashSize;
- }
-
- public int getKeyCount() {
- return keyCount;
- }
-
- public String getPluginId() {
- return pluginId;
- }
-
- public int getKeySize() {
- return keySize;
- }
-
- public int getValueSize() {
- return valueSize;
- }
-
- public long getTotalSize() {
- return keySize + valueSize + hashSize;
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public long getFileSize() {
- return fileSize;
- }
-}
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/StatsManager.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/StatsManager.java
deleted file mode 100644
index 8356d808e..000000000
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/internal/stats/StatsManager.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.stats;
-
-import java.io.*;
-import java.net.URL;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.HookConfigurator;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
-import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
-import org.eclipse.osgi.framework.adaptor.BundleWatcher;
-import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.Bundle;
-
-public class StatsManager implements BundleWatcher, HookConfigurator, ClassLoadingStatsHook {
- // This connect bundles and their info, and so allows to access the info without running through
- // the bundle registry. This map only contains activated bundles. The key is the bundle Id
- private Hashtable<Long, BundleStats> bundles = new Hashtable<Long, BundleStats>(20);
- private Map<Thread, Stack<BundleStats>> activationStacks = new HashMap<Thread, Stack<BundleStats>>(5);
- private static boolean booting = true; // the state of the platform. This value is changed by the InternalPlatform itself.
-
- private static StatsManager defaultInstance;
-
- public static boolean MONITOR_ACTIVATION = false;
- public static boolean MONITOR_CLASSES = false;
- public static boolean MONITOR_RESOURCES = false;
- public static String TRACE_FILENAME = "runtime.traces"; //$NON-NLS-1$
- public static String TRACE_FILTERS = "trace.properties"; //$NON-NLS-1$
- public static boolean TRACE_CLASSES = false;
- public static boolean TRACE_BUNDLES = false;
- public static final String FRAMEWORK_SYMBOLICNAME = "org.eclipse.osgi"; //$NON-NLS-1$
-
- //Option names for spies
- private static final String OPTION_MONITOR_ACTIVATION = FRAMEWORK_SYMBOLICNAME + "/monitor/activation"; //$NON-NLS-1$
- private static final String OPTION_MONITOR_CLASSES = FRAMEWORK_SYMBOLICNAME + "/monitor/classes"; //$NON-NLS-1$
- private static final String OPTION_MONITOR_RESOURCES = FRAMEWORK_SYMBOLICNAME + "/monitor/resources"; //$NON-NLS-1$
- private static final String OPTION_TRACE_BUNDLES = FRAMEWORK_SYMBOLICNAME + "/trace/activation"; //$NON-NLS-1$
- private static final String OPTION_TRACE_CLASSES = FRAMEWORK_SYMBOLICNAME + "/trace/classLoading"; //$NON-NLS-1$
- private static final String OPTION_TRACE_FILENAME = FRAMEWORK_SYMBOLICNAME + "/trace/filename"; //$NON-NLS-1$
- private static final String OPTION_TRACE_FILTERS = FRAMEWORK_SYMBOLICNAME + "/trace/filters"; //$NON-NLS-1$
-
- static {
- setDebugOptions();
- }
-
- public static StatsManager getDefault() {
- if (defaultInstance == null) {
- defaultInstance = new StatsManager();
- defaultInstance.initialize();
- }
- return defaultInstance;
- }
-
- public static void setDebugOptions() {
- FrameworkDebugOptions options = FrameworkDebugOptions.getDefault();
- // may be null if debugging is not enabled
- if (options == null)
- return;
- MONITOR_ACTIVATION = options.getBooleanOption(OPTION_MONITOR_ACTIVATION, false);
- MONITOR_CLASSES = options.getBooleanOption(OPTION_MONITOR_CLASSES, false);
- MONITOR_RESOURCES = options.getBooleanOption(OPTION_MONITOR_RESOURCES, false);
- TRACE_CLASSES = options.getBooleanOption(OPTION_TRACE_CLASSES, false);
- TRACE_BUNDLES = options.getBooleanOption(OPTION_TRACE_BUNDLES, false);
- TRACE_FILENAME = options.getOption(OPTION_TRACE_FILENAME, TRACE_FILENAME);
- TRACE_FILTERS = options.getOption(OPTION_TRACE_FILTERS, TRACE_FILTERS);
- }
-
- public static void doneBooting() {
- booting = false;
- }
-
- public static boolean isBooting() {
- return booting;
- }
-
- /**
- * Returns the result of converting a list of comma-separated tokens into an array
- *
- * @return the array of string tokens
- * @param prop the initial comma-separated string
- */
- public static String[] getArrayFromList(String prop) {
- return ManifestElement.getArrayFromList(prop, ","); //$NON-NLS-1$
- }
-
- private void initialize() {
- // add the system bundle
- BundleStats bundle = findBundle(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, 0);
- bundle.setTimestamp(System.currentTimeMillis());
- bundle.setActivationOrder(bundles.size());
- bundle.setDuringStartup(booting);
- }
-
- public void watchBundle(Bundle bundle, int type) {
- switch (type) {
- case BundleWatcher.START_ACTIVATION :
- startActivation(bundle);
- break;
- case BundleWatcher.END_ACTIVATION :
- endActivation(bundle);
- break;
- }
- }
-
- public void startActivation(Bundle bundle) {
- // should be called from a synchronized location to protect against concurrent updates
- BundleStats info = findBundle(bundle.getSymbolicName(), bundle.getBundleId());
- info.setTimestamp(System.currentTimeMillis());
- info.setActivationOrder(bundles.size());
- info.setDuringStartup(booting);
-
- Stack<BundleStats> activationStack = activationStacks.get(Thread.currentThread());
- if (activationStack == null) {
- activationStack = new Stack<BundleStats>();
- activationStacks.put(Thread.currentThread(), activationStack);
- }
-
- // set the parentage of activation
- if (activationStack.size() != 0) {
- BundleStats activatedBy = activationStack.peek();
- activatedBy.activated(info);
- info.setActivatedBy(activatedBy);
- }
- activationStack.push(info);
-
- if (TRACE_BUNDLES == true) {
- traceActivate(bundle, info);
- }
- }
-
- public void endActivation(Bundle symbolicName) {
- Stack<BundleStats> activationStack = activationStacks.get(Thread.currentThread());
- // should be called from a synchronized location to protect against concurrent updates
- BundleStats info = activationStack.pop();
- info.endActivation();
- }
-
- private void traceActivate(Bundle bundle, BundleStats info) {
- try {
- PrintWriter output = new PrintWriter(new FileOutputStream(ClassloaderStats.traceFile.getAbsolutePath(), true));
- try {
- long startPosition = ClassloaderStats.traceFile.length();
- output.println("Activating bundle: " + bundle.getSymbolicName()); //$NON-NLS-1$
- output.println("Bundle activation stack:"); //$NON-NLS-1$
- Stack<BundleStats> activationStack = activationStacks.get(Thread.currentThread());
- for (int i = activationStack.size() - 1; i >= 0; i--)
- output.println("\t" + activationStack.get(i).getSymbolicName()); //$NON-NLS-1$
- output.println("Class loading stack:"); //$NON-NLS-1$
- Stack<ClassStats> classStack = ClassloaderStats.getClassStack();
- for (int i = classStack.size() - 1; i >= 0; i--)
- output.println("\t" + classStack.get(i).getClassName()); //$NON-NLS-1$
- output.println("Stack trace:"); //$NON-NLS-1$
- new Throwable().printStackTrace(output);
- info.setTraceStart(startPosition);
- } finally {
- output.close();
- info.setTraceEnd(ClassloaderStats.traceFile.length());
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- public BundleStats findBundle(String symbolicName, long id) {
- BundleStats result = bundles.get(new Long(id));
- try {
- if (result == null) {
- result = new BundleStats(symbolicName, id);
- bundles.put(new Long(id), result);
- }
- } catch (IllegalAccessError e) {
- e.printStackTrace();
- }
- return result;
- }
-
- public BundleStats[] getBundles() {
- return bundles.values().toArray(new BundleStats[bundles.size()]);
- }
-
- public BundleStats getBundle(long id) {
- return bundles.get(new Long(id));
- }
-
- /**
- * @throws ClassNotFoundException
- */
- public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
- if (StatsManager.MONITOR_CLASSES) //Support for performance analysis
- ClassloaderStats.startLoadingClass(getClassloaderId(manager), name);
- }
-
- public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) {
- if (StatsManager.MONITOR_CLASSES)
- ClassloaderStats.endLoadingClass(getClassloaderId(manager), name, clazz != null);
- }
-
- public void preFindLocalResource(String name, ClasspathManager manager) {
- // do nothing
- }
-
- public void postFindLocalResource(String name, URL resource, ClasspathManager manager) {
- if (StatsManager.MONITOR_RESOURCES)
- if (resource != null && name.endsWith(".properties")) //$NON-NLS-1$
- ClassloaderStats.loadedBundle(getClassloaderId(manager), new ResourceBundleStats(getClassloaderId(manager), name, resource));
- return;
- }
-
- public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
- // do nothing
- }
-
- private String getClassloaderId(ClasspathManager loader) {
- return loader.getBaseData().getSymbolicName();
- }
-
- public void addHooks(HookRegistry hookRegistry) {
- if (Debug.MONITOR_ACTIVATION)
- hookRegistry.addWatcher(StatsManager.getDefault());
- if (StatsManager.MONITOR_CLASSES || StatsManager.MONITOR_RESOURCES)
- hookRegistry.addClassLoadingStatsHook(StatsManager.getDefault());
- }
-}
diff --git a/bundles/org.eclipse.osgi/hookconfigurators.properties b/bundles/org.eclipse.osgi/hookconfigurators.properties
deleted file mode 100644
index db4cebc30..000000000
--- a/bundles/org.eclipse.osgi/hookconfigurators.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-###############################################################################
-# Copyright (c) 2005, 2010 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-hook.configurators= \
- org.eclipse.osgi.internal.baseadaptor.BaseHookConfigurator,\
- org.eclipse.osgi.internal.baseadaptor.DevClassLoadingHook,\
- org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook,\
- org.eclipse.core.runtime.internal.adaptor.EclipseLogHook,\
- org.eclipse.core.runtime.internal.adaptor.EclipseErrorHandler,\
- org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorHook,\
- org.eclipse.core.runtime.internal.adaptor.EclipseClassLoadingHook,\
- org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter,\
- org.eclipse.core.runtime.internal.stats.StatsManager,\
- org.eclipse.osgi.internal.signedcontent.SignedBundleHook,\
- org.eclipse.osgi.internal.composite.CompositeConfigurator,\
- org.eclipse.osgi.internal.baseadaptor.weaving.WeavingHookConfigurator
-builtin.hooks = true
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundle.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundle.java
deleted file mode 100644
index f935f9b87..000000000
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundle.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.service.framework;
-
-import java.io.InputStream;
-import java.util.Map;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.launch.Framework;
-
-/**
- * Composite bundles are composed of other bundles. The component bundles which
- * make up the content of a composite bundle are installed into a child
- * framework. Like a normal bundle, a composite bundle may import packages and
- * use services from other bundles which are installed in the same framework as
- * the composite bundle. The packages imported and the services used by a
- * composite bundle are shared with the components of a composite bundle through
- * a surrogate bundle installed in the child framework. Also like a normal
- * bundle, a composite bundle may export packages and register services which
- * can be used by bundles installed in the same framework as the composite
- * bundle. The packages exported and the services registered by a composite
- * bundle are acquired from the components of a composite bundle by the
- * surrogate bundle installed in the child framework
- * <p>
- * A framework has one composite bundle for each of its child frameworks. A
- * framework can have zero or more composite bundles installed. A child
- * framework must have one and only one surrogate bundle which represents the
- * composite bundle in the parent framework. In other words, a parent framework
- * can have many child frameworks but a child framework can have only one
- * parent.
- * <p>
- * A composite bundle does the following as specified by the composite manifest
- * map:
- * <ul>
- * <li>Exports packages to the parent framework from the child framework. These
- * packages are imported by the surrogate bundle installed in the child
- * framework.</li>
- * <li>Imports packages from the parent framework. These packages are exported
- * by the surrogate bundle installed in the child framework.</li>
- * <li>Registers services to the parent framework from the child framework.
- * These services are acquired by the surrogate bundle installed in the child
- * framework.</li>
- * <li>Acquires services from the parent framework. These services are
- * registered by the surrogate bundle installed in the child framework.</li>
- * </ul>
- *
- * A newly created child <code>Framework</code> will be in the
- * {@link Bundle#STARTING STARTING} state. This child <code>Framework</code> can
- * then be used to manage and control the child framework instance. The child
- * framework instance is persistent and uses a storage area associated with the
- * installed composite bundle. The child framework's lifecycle is tied to its
- * composite bundle's lifecycle in the following ways:
- * <p>
- * <ul>
- * <li>If the composite bundle is marked to be persistently started (see
- * StartLevel.isBundlePersistentlyStarted(Bundle)) then the child framework
- * instance will automatically be started when the composite bundle's
- * start-level is met.</li>
- * <li>The child framework instance will be stopped if the composite bundle is
- * persistently stopped or its start level is no longer met. Performing
- * operations which transiently stop a composite bundle do not cause the child
- * framework to stop (e.g. {@link Bundle#stop(int) stop(Bundle.STOP_TRANSIENT)},
- * {@link Bundle#update() update}, refreshPackages etc.).</li>
- * <li>If the composite bundle is uninstalled, the child framework's persistent
- * storage area is also uninstalled.</li>
- * </ul>
- * <p>
- * The child framework may be persistently started and stopped by persistently
- * starting and stopping the composite bundle, but it is still possible to
- * initialize and start the child framework explicitly while the composite
- * bundle is not persistently started. This allows for the child framework to be
- * initialized and populated with a set of bundles before starting the composite
- * bundle. The set of bundles installed into the child framework are the
- * component bundles which comprise the composite bundle.
- * <p>
- * The child framework's lifecycle is also tied to the lifecycle of its
- * parent framework. When the parent <code>Framework</code> enters the
- * {@link Bundle#STOPPING STOPPING} state, all active child frameworks of that
- * parent are shutdown using the {@link Framework#stop()} method. The parent
- * framework must not enter the {@link Bundle#RESOLVED} state until all the
- * child frameworks have completed their shutdown process. Just as with other
- * Bundles, references to child frameworks (or the associated composite and
- * surrogate bundles) become invalid after the parent framework has completed
- * the shutdown process, and must not be allowed to re-initialize or re-start
- * the child framework.
- *
- * @see SurrogateBundle
- * @deprecated This API proposal was rejected by the OSGi Alliance and will
- * not be part of any OSGi specification. Please transition to the
- * org.osgi.framework.hooks API to control resolution, bundle, and service
- * isolation. This API will be removed from Equinox in the 3.9 release
- * You are cautioned against relying upon this API.
- * @ThreadSafe
- * @version $Revision: 6860 $
- */
-public interface CompositeBundle extends Bundle {
- /**
- * Returns the child framework associated with this composite bundle.
- *
- * @return the child framework.
- */
- Framework getCompositeFramework();
-
- /**
- * Returns the surrogate bundle associated with this composite bundle. The
- * surrogate bundle is installed in the child framework.
- *
- * @return the surrogate bundle.
- */
- SurrogateBundle getSurrogateBundle();
-
- /**
- * Updates this composite bundle with the specified manifest.
- * <p>
- * Similar to normal bundle updates, the packages exported by a composite or
- * surrogate bundle can not change as a result of calling update: the
- * previous package exports must be available to other consuming bundles (in
- * either the parent or child framework) until the
- * PackageAdmin.refreshPackages method has been called to refresh the
- * composite, or the parent Framework is re-launched.
- *
- * @param compositeManifest
- * the new composite manifest.
- * @throws BundleException
- * If the update fails.
- * @see CompositeBundleFactory#installCompositeBundle(Map, String, Map)
- */
- void update(Map /* <String, String> */compositeManifest) throws BundleException;
-
- /**
- * This operation is not supported for composite bundles. A
- * <code>BundleException</code> of type
- * {@link BundleException#INVALID_OPERATION invalid operation} must be
- * thrown.
- */
- void update() throws BundleException;
-
- /**
- * This operation is not supported for composite bundles. A
- * <code>BundleException</code> of type
- * {@link BundleException#INVALID_OPERATION invalid operation} must be
- * thrown.
- */
- void update(InputStream input) throws BundleException;
-
- /**
- * Uninstalls this composite bundle. The associated child framework
- * is shutdown, and its persistent storage area is deleted.
- */
- void uninstall() throws BundleException;
-}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundleFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundleFactory.java
deleted file mode 100644
index 67e9de76d..000000000
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/CompositeBundleFactory.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.service.framework;
-
-import java.util.Map;
-import org.osgi.framework.*;
-import org.osgi.framework.launch.Framework;
-
-/**
- * Framework service that is used to create composite bundles.
- * <p>
- * If present, there will only be a single instance of this service registered
- * with the Framework.
- *
- * @deprecated This API proposal was rejected by the OSGi Alliance and will
- * not be part of any OSGi specification. Please transition to the
- * org.osgi.framework.hooks API to control resolution, bundle, and service
- * isolation. This API will be removed from Equinox in the 3.9 release
- * You are cautioned against relying upon this API.
- * @ThreadSafe
- * @version $Revision: 6860 $
- */
-// TODO javadoc needs review
-public interface CompositeBundleFactory {
- /**
- * Manifest header (named &quot;CompositeServiceFilter-Import&quot;)
- * identifying the service filters that are used by a composite bundle
- * to select services that will be registered into a child framework by its
- * associated surrogate bundle.
- */
- public static final String COMPOSITE_SERVICE_FILTER_IMPORT = "CompositeServiceFilter-Import";
-
- /**
- * Manifest header (named &quot;CompositeServiceFilter-Export&quot;)
- * identifying the service filters that are used by a surrogate
- * bundle to select services that will be registered into a parent framework
- * by its associated composite bundle.
- */
- public static final String COMPOSITE_SERVICE_FILTER_EXPORT = "CompositeServiceFilter-Export";
-
- /**
- * Installs a <code>CompositeBundle</code>. The composite bundle has a new
- * child <code>Framework</code> associated with it and a surrogate bundle
- * which is installed in the child framework. Composite bundles share
- * packages and services between the parent framework they are installed in and
- * the child framework.
- * <p>
- * The following steps are required to create a composite bundle:
- * <ol>
- * <li>If a bundle containing the same location string is already installed
- * and the Bundle object is a <code>CompositeBundle</code>, then that
- * composite bundle is returned; otherwise a <code>BundleException</code>
- * is thrown indicating that an incompatible bundle is already installed at the
- * specified location.</li>
- * <li>The composite bundle's associated resources are allocated. The
- * associated resources minimally consist of a unique identifier and a
- * persistent storage area. If this step fails, a <code>BundleException</code>
- * is thrown.</li>
- * <li>The <code>compositeManifest</code> map is used to provide the headers for the
- * composite bundle and its surrogate bundle.
- * <p>
- * If composite manifest map does not contain the following header(s) then a
- * BundleException is thrown:
- * <ul>
- * <li> {@link Constants#BUNDLE_SYMBOLICNAME Bundle-SymbolicName} the
- * symbolic name used for the composite bundle and its surrogate bundle.
- * </ul>
- * </p><p>
- * The composite manifest map may optionally contain the following
- * header(s):
- * <ul>
- * <li> {@link Constants#BUNDLE_VERSION Bundle-Version} the bundle version
- * used for the composite bundle and its surrogate bundle.</li>
- * <li> {@link Constants#IMPORT_PACKAGE Import-Package} the packages which
- * are imported from the parent framework by the composite bundle and are
- * exported to the child framework by the surrogate bundle.</li>
- * <li>{@link Constants#EXPORT_PACKAGE Export-Package} the packages which
- * are imported from the child framework by the surrogate bundle and are
- * exported to the parent framework by the composite bundle.</li>
- * <li>{@link #COMPOSITE_SERVICE_FILTER_IMPORT
- * CompositeServiceFilter-Import} the service filters which are acquired
- * from the parent framework by the composite bundle and are registered in
- * the child framework by the surrogate bundle.</li>
- * <li>{@link #COMPOSITE_SERVICE_FILTER_EXPORT
- * CompositeServiceFilter-Export} the service filters which are acquired
- * from the child framework by the surrogate bundle and are registered in
- * the parent framework by the composite bundle.</li>
- * <li>{@link Constants#BUNDLE_MANIFESTVERSION Bundle-ManifestVersion} the
- * bundle manifest version. If this header is not specified then the default
- * is to use version 2. A <code>BundleException</code> is thrown if this header is
- * specified and the version is less than 2.</li>
- * <li>{@link Constants#REQUIRE_BUNDLE Require-Bundle} a bundle from the parent
- * which is required by the child. Support for this header is experimental: a
- * <code>BundleException</code> should be thrown if the header is present and
- * the framework doesn't support it.
- * </ul>
- * </p><p>
- * The composite manifest map must not contain the following headers. If a
- * composite manifest map does contain one of the following headers then a
- * <code>BundleException</code> is thrown:
- * <br/>
- * {@link Constants#BUNDLE_ACTIVATIONPOLICY Bundle-ActivationPolicy}<br/>
- * {@link Constants#BUNDLE_ACTIVATOR Bundle-Activator}<br/>
- * {@link Constants#BUNDLE_CLASSPATH Bundle-ClassPath}<br/>
- * {@link Constants#BUNDLE_LOCALIZATION Bundle-Localization}<br/>
- * {@link Constants#BUNDLE_NATIVECODE Bundle-NativeCode}<br/>
- * {@link Constants#FRAGMENT_HOST Fragment-Host}<br/>
- * {@link Constants#DYNAMICIMPORT_PACKAGE DynamicImport-Package}<br/>
- * <br/>
- * </li>
- * <li>A child framework is created which uses a storage area associated with
- * the composite bundle's persistent storage. The framework configuration
- * property {@link Constants#FRAMEWORK_STORAGE org.osgi.framework.storage},
- * if specified, is ignored.</li>
- * <li>The child framework is initialized (see {@link Framework#init()}).
- * <li>A surrogate bundle is created and installed into the child framework.</li>
- * <li>The composite bundle's state is set to INSTALLED.</li>
- * <li>A bundle event of type {@link BundleEvent#INSTALLED} is fired for the
- * composite bundle.
- * <li>The <code>CompositeBundle</code> object for the new composite
- * bundle is returned.
- * </ol>
- * <p>
- *
- * @param frameworkConfig A map containing configuration parameters used to
- * initialize and launch the child framework.
- * @param location The bundle location used for the composite and surrogate bundles.
- * @param compositeManifest A map containing the manifest used to create the composite
- * and surrogate bundles
- * @return A new composite bundle in INSTALLED state.
- * @throws BundleException If the composite manifest is invalid or there is
- * some other problem with installing the composite bundle.
- * @throws SecurityException If the caller does not have
- * <code>AllPermission</code>.
- * @see Framework
- * @see CompositeBundle
- */
- CompositeBundle installCompositeBundle(Map /* <String, String> */frameworkConfig, String location, Map /* <String, String> */compositeManifest) throws BundleException;
-
-}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/SurrogateBundle.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/SurrogateBundle.java
deleted file mode 100644
index 932654be7..000000000
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/framework/SurrogateBundle.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.service.framework;
-
-import java.io.InputStream;
-import org.osgi.framework.*;
-
-/**
- * A surrogate bundle is installed in a child framework, and is the child-facing
- * representation of the composite bundle in the parent framework.
- * <p>
- * A surrogate bundle does the following as specified by the composite manifest:
- * <ul>
- * <li>Exports packages to the child framework from the parent framework. These
- * packages are imported by the composite bundle installed in the parent
- * framework.</li>
- * <li>Imports packages from the child framework. These packages are exported
- * by the composite bundle installed in the parent framework.</li>
- * <li>Registers services from the parent framework with the child framework.
- * These services are acquired by the composite bundle installed in the
- * parent framework.</li>
- * <li>Acquires services from the child framework. These services are
- * registered by the composite bundle installed in the parent framework.</li>
- * </ul>
- * <p>
- * @see CompositeBundle
- * @deprecated This API proposal was rejected by the OSGi Alliance and will
- * not be part of any OSGi specification. Please transition to the
- * org.osgi.framework.hooks API to control resolution, bundle, and service
- * isolation. This API will be removed from Equinox in the 3.9 release
- * You are cautioned against relying upon this API.
- */
-public interface SurrogateBundle extends Bundle {
- /**
- * Returns the bundle context of the associated composite bundle.
- * @return the bundle context of the composite bundle. A value
- * of <code>null</code> is returned if the composite bundle does
- * not have a valid bundle context.
- */
- BundleContext getCompositeBundleContext();
-
- /**
- * This operation is not supported for surrogate bundles. A
- * <code>BundleException</code> of type
- * {@link BundleException#INVALID_OPERATION invalid operation} must be
- * thrown.
- */
- void update() throws BundleException;
-
- /**
- * This operation is not supported for surrogate bundles. A
- * <code>BundleException</code> of type
- * {@link BundleException#INVALID_OPERATION invalid operation} must be
- * thrown.
- */
- void update(InputStream input) throws BundleException;
-
- /**
- * This operation is not supported for surrogate bundles. A
- * <code>BundleException</code> of type
- * {@link BundleException#INVALID_OPERATION invalid operation} must be
- * thrown.
- */
- void uninstall() throws BundleException;
-}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/HostedCapability.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/HostedCapability.java
new file mode 100644
index 000000000..db698baa0
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/HostedCapability.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.resolver;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+/**
+ * A capability hosted by a resource.
+ *
+ * <p>
+ * A HostedCapability is a Capability where the {@link #getResource()} method
+ * returns a Resource that hosts this Capability instead of declaring it. This
+ * is necessary for cases where the declaring Resource of a Capability does not
+ * match the runtime state. For example, this is the case for fragments attached
+ * to a host. Most fragment declared capabilities and requirements become hosted
+ * by the host resource. Since a fragment can attach to multiple hosts, a single
+ * capability can actually be hosted multiple times.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @version $Id$
+ */
+public interface HostedCapability extends Capability {
+
+ /**
+ * Return the Resource that hosts this Capability.
+ *
+ * @return The Resource that hosts this Capability.
+ */
+ Resource getResource();
+
+ /**
+ * Return the Capability hosted by the Resource.
+ *
+ * @return The Capability hosted by the Resource.
+ */
+ Capability getDeclaredCapability();
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolutionException.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolutionException.java
new file mode 100644
index 000000000..42e5773e3
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolutionException.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.resolver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.osgi.resource.Requirement;
+
+/**
+ * Indicates failure to resolve a set of requirements.
+ *
+ * <p>
+ * If a resolution failure is caused by a missing mandatory dependency a
+ * resolver may include any requirements it has considered in the resolution
+ * exception. Clients may access this set of dependencies via the
+ * {@link #getUnresolvedRequirements()} method.
+ *
+ * <p>
+ * Resolver implementations may extend this class to provide extra state
+ * information about the reason for the resolution failure.
+ *
+ * @version $Id$
+ */
+public class ResolutionException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Collection<Requirement> unresolvedRequirements;
+
+ /**
+ * Create a {@code ResolutionException} with the specified message, cause
+ * and unresolved requirements.
+ *
+ * @param message The message.
+ * @param cause The cause of this exception.
+ * @param unresolvedRequirements The unresolved mandatory requirements from
+ * mandatory resources or {@code null} if no unresolved requirements
+ * information is provided.
+ */
+ public ResolutionException(String message, Throwable cause, Collection<Requirement> unresolvedRequirements) {
+ super(message, cause);
+ if ((unresolvedRequirements == null) || unresolvedRequirements.isEmpty()) {
+ this.unresolvedRequirements = emptyCollection();
+ } else {
+ this.unresolvedRequirements = Collections.unmodifiableCollection(new ArrayList<Requirement>(unresolvedRequirements));
+ }
+ }
+
+ /**
+ * Create a {@code ResolutionException} with the specified message.
+ *
+ * @param message The message.
+ */
+ public ResolutionException(String message) {
+ super(message);
+ unresolvedRequirements = emptyCollection();
+ }
+
+ /**
+ * Create a {@code ResolutionException} with the specified cause.
+ *
+ * @param cause The cause of this exception.
+ */
+ public ResolutionException(Throwable cause) {
+ super(cause);
+ unresolvedRequirements = emptyCollection();
+ }
+
+ private static <T> Collection<T> emptyCollection() {
+ return Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Return the unresolved requirements, if any, for this exception.
+ *
+ * <p>
+ * The unresolved requirements are provided for informational purposes and
+ * the specific set of unresolved requirements that are provided after a
+ * resolve failure is not defined.
+ *
+ * @return A collection of the unresolved requirements for this exception.
+ * The returned collection may be empty if no unresolved
+ * requirements information is provided.
+ */
+ public Collection<Requirement> getUnresolvedRequirements() {
+ return unresolvedRequirements;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolveContext.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolveContext.java
new file mode 100644
index 000000000..f92eae32a
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/ResolveContext.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.resolver;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wiring;
+
+/**
+ * A resolve context provides resources, options and constraints to the
+ * potential solution of a {@link Resolver#resolve(ResolveContext) resolve}
+ * operation.
+ *
+ * <p>
+ * Resolve Contexts:
+ * <ul>
+ * <li>Specify the mandatory and optional resources to resolve. The mandatory
+ * and optional resources must be consistent and correct. For example, they must
+ * not violate the singleton policy of the implementer.</li>
+ * <li>Provide {@link Capability capabilities} that the Resolver can use to
+ * satisfy {@link Requirement requirements} via the
+ * {@link #findProviders(Requirement)} method</li>
+ * <li>Constrain solutions via the {@link #getWirings()} method. A wiring
+ * consists of a map of existing {@link Resource resources} to {@link Wiring
+ * wiring}.</li>
+ * <li>Filter requirements that are part of a resolve operation via the
+ * {@link #isEffective(Requirement)}.</li>
+ * </ul>
+ *
+ * <p>
+ * A resolver may call the methods on the resolve context any number of times
+ * during a resolve operation using any thread. Implementors should ensure that
+ * this class is properly thread safe.
+ *
+ * <p>
+ * Except for {@link #insertHostedCapability(List, HostedCapability)}, the
+ * resolve context methods must be <i>idempotent</i>. This means that resources
+ * must have constant capabilities and requirements and the resolve context must
+ * return a consistent set of capabilities, wires and effective requirements.
+ *
+ * @ThreadSafe
+ * @version $Id$
+ */
+public abstract class ResolveContext {
+ /**
+ * Return the resources that must be resolved for this resolve context.
+ *
+ * <p>
+ * The default implementation returns an empty collection.
+ *
+ * @return The resources that must be resolved for this resolve context. May
+ * be empty if there are no mandatory resources.
+ */
+ public Collection<Resource> getMandatoryResources() {
+ return emptyCollection();
+ }
+
+ /**
+ * Return the resources that the resolver should attempt to resolve for this
+ * resolve context. Inability to resolve one of the specified resources will
+ * not result in a resolution exception.
+ *
+ * <p>
+ * The default implementation returns an empty collection.
+ *
+ * @return The resources that the resolver should attempt to resolve for
+ * this resolve context. May be empty if there are no mandatory
+ * resources.
+ */
+ public Collection<Resource> getOptionalResources() {
+ return emptyCollection();
+ }
+
+ private static <T> Collection<T> emptyCollection() {
+ return Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Find Capabilities that match the given Requirement.
+ * <p>
+ * The returned list contains {@link Capability} objects where the Resource
+ * must be the declared Resource of the Capability. The Resolver can then
+ * add additional {@link HostedCapability} objects with the
+ * {@link #insertHostedCapability(List, HostedCapability)} method when it,
+ * for example, attaches fragments. Those {@link HostedCapability} objects
+ * will then use the host's Resource which likely differs from the declared
+ * Resource of the corresponding Capability.
+ *
+ * <p>
+ * The returned list is in priority order such that the Capabilities with a
+ * lower index have a preference over those with a higher index. The
+ * resolver must use the
+ * {@link #insertHostedCapability(List, HostedCapability)} method to add
+ * additional Capabilities to maintain priority order. In general, this is
+ * necessary when the Resolver uses Capabilities declared in a Resource but
+ * that must originate from an attached host.
+ *
+ * <p>
+ * Each returned Capability must match the given Requirement. This implies
+ * that the filter in the Requirement must match as well as any namespace
+ * specific directives. For example, the mandatory attributes for the
+ * {@code osgi.wiring.package} namespace.
+ *
+ * @param requirement The requirement that a resolver is attempting to
+ * satisfy. Must not be {@code null}.
+ * @return A list of {@link Capability} objects that match the specified
+ * requirement.
+ */
+ public abstract List<Capability> findProviders(Requirement requirement);
+
+ /**
+ * Add a {@link HostedCapability} to the list of capabilities returned from
+ * {@link #findProviders(Requirement)}.
+ *
+ * <p>
+ * This method is used by the {@link Resolver} to add Capabilities that are
+ * hosted by another Resource to the list of Capabilities returned from
+ * {@link #findProviders(Requirement)}. This function is necessary to allow
+ * fragments to attach to hosts, thereby changing the origin of a
+ * Capability. This method must insert the specified HostedCapability in a
+ * place that makes the list maintain the preference order. It must return
+ * the index in the list of the inserted {@link HostedCapability}.
+ *
+ * @param capabilities The list returned from
+ * {@link #findProviders(Requirement)}. Must not be {@code null}.
+ * @param hostedCapability The HostedCapability to insert in the specified
+ * list. Must not be {@code null}.
+ * @return The index in the list of the inserted HostedCapability.
+ *
+ */
+ public abstract int insertHostedCapability(List<Capability> capabilities, HostedCapability hostedCapability);
+
+ /**
+ * Test if a given requirement should be wired in the resolve operation. If
+ * this method returns {@code false}, then the resolver should ignore this
+ * requirement during the resolve operation.
+ *
+ * <p>
+ * The primary use case for this is to test the {@code effective} directive
+ * on the requirement, though implementations are free to use any effective
+ * test.
+ *
+ * @param requirement The Requirement to test. Must not be {@code null}.
+ * @return {@code true} if the requirement should be considered as part of
+ * the resolve operation.
+ */
+ public abstract boolean isEffective(Requirement requirement);
+
+ /**
+ * Returns the wirings for existing resolved resources.
+ *
+ * <p>
+ * For example, if this resolve context is for an OSGi framework, then the
+ * result would contain all the currently resolved bundles with each
+ * bundle's current wiring.
+ *
+ * <p>
+ * Multiple calls to this method for this resolve context must return the
+ * same result.
+ *
+ * @return The wirings for existing resolved resources. The returned map is
+ * unmodifiable.
+ */
+ public abstract Map<Resource, Wiring> getWirings();
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java
new file mode 100644
index 000000000..dfb89b8d0
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) OSGi Alliance (2006, 2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This document is an experimental draft to enable interoperability
+// between bundle repositories. There is currently no commitment to
+// turn this draft into an official specification.
+
+package org.osgi.service.resolver;
+
+import java.util.List;
+import java.util.Map;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+
+/**
+ * A resolver service resolves the specified resources in the context supplied
+ * by the caller.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @version $Id$
+ */
+public interface Resolver {
+ /**
+ * Resolve the specified resolve context and return any new resources and
+ * wires to the caller.
+ *
+ * <p>
+ * The resolver considers two groups of resources:
+ * <ul>
+ * <li>Mandatory - any resource in the
+ * {@link ResolveContext#getMandatoryResources() mandatory group} must be
+ * resolved. A failure to satisfy any mandatory requirement for these
+ * resources will result in throwing a {@link ResolutionException}</li>
+ * <li>Optional - any resource in the
+ * {@link ResolveContext#getOptionalResources() optional group} may be
+ * resolved. A failure to satisfy a mandatory requirement for a resource in
+ * this group will not fail the overall resolution but no resources or wires
+ * will be returned for that resource.</li>
+ * </ul>
+ *
+ * <p>
+ * The resolve method returns the delta between the start state defined by
+ * {@link ResolveContext#getWirings()} and the end resolved state. That is,
+ * only new resources and wires are included.
+ *
+ * <p>
+ * The behavior of the resolver is not defined if the specified resolve
+ * context supplies inconsistent information.
+ *
+ * @param context The resolve context for the resolve operation. Must not be
+ * {@code null}.
+ * @return The new resources and wires required to satisfy the specified
+ * resolve context. The returned map is the property of the caller
+ * and can be modified by the caller.
+ * @throws ResolutionException If the resolution cannot be satisfied.
+ */
+ Map<Resource, List<Wire>> resolve(ResolveContext context) throws ResolutionException;
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/package-info.java
new file mode 100644
index 000000000..db1706d83
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/package-info.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Resolver Service Package Version 1.0.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.resolver; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.resolver; version="[1.0,1.1)"}
+ *
+ * @version $Id$
+ */
+
+package org.osgi.service.resolver;
+
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo
new file mode 100644
index 000000000..7c8de0324
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java
index beeed64c9..912a520f6 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java
@@ -11,13 +11,15 @@
******************************************************************************/
package org.eclipse.osgi.internal.module;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.debug.FrameworkDebugOptions;
+
import java.security.AccessController;
import java.util.*;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.internal.baseadaptor.ArrayMap;
import org.eclipse.osgi.internal.module.GroupingChecker.PackageRoots;
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java
index a24cf9b0b..60d3f2b30 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java
@@ -14,7 +14,6 @@ package org.eclipse.osgi.internal.resolver;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.osgi.service.resolver.BaseDescription;
-import org.eclipse.osgi.service.resolver.extras.DescriptionReference;
import org.osgi.framework.Version;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
@@ -115,7 +114,7 @@ public abstract class BaseDescriptionImpl implements BaseDescription {
this.userObject = userObject;
}
- class BaseCapability implements BundleCapability, DescriptionReference {
+ class BaseCapability implements BundleCapability {
private final String namespace;
public BaseCapability(String namespace) {
@@ -171,9 +170,5 @@ public abstract class BaseDescriptionImpl implements BaseDescription {
public BundleRevision getResource() {
return getRevision();
}
-
- public BaseDescription getDescription() {
- return BaseDescriptionImpl.this;
- }
}
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java
index e887f0622..f0a30cbd2 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java
@@ -11,8 +11,9 @@
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+
import java.util.*;
-import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.eclipse.osgi.service.resolver.*;
import org.osgi.framework.*;
import org.osgi.resource.Namespace;
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java
index f1f54b17e..1e3e1d137 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java
@@ -11,9 +11,10 @@
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+
import java.util.*;
import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.*;
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java
index 59d55d1d3..1c2bfc382 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java
@@ -11,8 +11,9 @@
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;
+import org.eclipse.osgi.internal.framework.AliasMapper;
+
import java.util.*;
-import org.eclipse.osgi.framework.internal.core.AliasMapper;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.service.resolver.*;
import org.osgi.framework.Filter;
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java
index b6964980a..cf65e77be 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java
@@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+
import java.lang.reflect.Constructor;
import java.util.*;
import org.eclipse.osgi.framework.internal.core.*;
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java
index 75d62d808..4f4e5c546 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java
@@ -12,11 +12,13 @@
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;
+import org.eclipse.osgi.internal.framework.FilterImpl;
+
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.debug.FrameworkDebugOptions;
+
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
import org.eclipse.osgi.framework.internal.core.Constants;
-import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.eclipse.osgi.framework.util.*;
import org.eclipse.osgi.internal.baseadaptor.StateManager;
import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java
index 1cc7e5eeb..3f0e2f078 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java
@@ -17,7 +17,6 @@ import java.util.Map;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.internal.resolver.BaseDescriptionImpl.BaseCapability;
import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.service.resolver.extras.SpecificationReference;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
@@ -125,7 +124,7 @@ abstract class VersionConstraintImpl implements VersionConstraint {
this.userObject = userObject;
}
- class BundleRequirementImpl implements BundleRequirement, SpecificationReference {
+ class BundleRequirementImpl implements BundleRequirement {
private final String namespace;
public BundleRequirementImpl(String namespace) {
@@ -193,10 +192,6 @@ abstract class VersionConstraintImpl implements VersionConstraint {
public BundleRevision getResource() {
return getRevision();
}
-
- public VersionConstraint getSpecification() {
- return VersionConstraintImpl.this;
- }
}
static StringBuffer addFilterAttributes(StringBuffer filter, Map<String, ?> attributes) {
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/DefaultAuthorizationEngine.java b/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/DefaultAuthorizationEngine.java
deleted file mode 100644
index 4257bf0a4..000000000
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/service/security/DefaultAuthorizationEngine.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.service.security;
-
-import java.io.*;
-import java.security.cert.CertificateException;
-import java.util.Properties;
-import org.eclipse.core.runtime.adaptor.LocationManager;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.internal.core.AbstractBundle;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.baseadaptor.DevClassPathHelper;
-import org.eclipse.osgi.internal.provisional.service.security.*;
-import org.eclipse.osgi.internal.signedcontent.SignedBundleHook;
-import org.eclipse.osgi.internal.signedcontent.SignedStorageHook;
-import org.eclipse.osgi.service.resolver.*;
-import org.eclipse.osgi.signedcontent.SignedContent;
-import org.eclipse.osgi.signedcontent.SignerInfo;
-import org.osgi.framework.*;
-
-public class DefaultAuthorizationEngine extends AuthorizationEngine {
-
- private static final String VERSION_PROP = "Version"; //$NON-NLS-1$
- private static final String VERSION_NUM = "1.0"; //$NON-NLS-1$
- private static final Version VERSION_MAX = new Version(2, 0, 0);
-
- private final State systemState;
- private final BundleContext bundleContext;
-
- public static final int ENFORCE_NONE = 0x0000;
- public static final int ENFORCE_SIGNED = 0x0001;
- public static final int ENFORCE_TRUSTED = 0x0002;
- public static final int ENFORCE_VALIDITY = 0x0004;
-
- private static final String STR_ENFORCE_NONE = "any"; //$NON-NLS-1$
- private static final String STR_ENFORCE_SIGNED = "signed"; //$NON-NLS-1$
- private static final String STR_ENFORCE_TRUSTED = "trusted"; //$NON-NLS-1$
- private static final String STR_ENFORCE_VALIDITY = "validity"; //$NON-NLS-1$
-
- private static final String POLICY_NAME = "org.eclipse.equinox.security"; //$NON-NLS-1$
- private static final String POLICY_PROP = "osgi.signedcontent.authorization.engine.policy"; //$NON-NLS-1$
- private static final String FILE_LOAD_POLICY = ".loadpolicy"; //$NON-NLS-1$
- private static int enforceFlags = 0;
-
- private static final File policyFile;
- static {
- File osgiFile = LocationManager.getOSGiConfigurationDir();
- policyFile = new File(osgiFile.getPath() + File.separatorChar + FILE_LOAD_POLICY);
-
- Properties properties = null;
- // load the policy file, if not exist, create it and load it
- if (policyFile.exists()) {
- try {
- properties = new Properties();
- properties.load(new FileInputStream(policyFile));
- } catch (IOException e) {
- SignedBundleHook.log("Error loading policy file", FrameworkLogEntry.ERROR, e); //$NON-NLS-1$
- }
- }
-
- if (properties != null) {
- Version version = new Version(0, 0, 0);
- String versionProp = properties.getProperty(VERSION_PROP);
- if (versionProp != null)
- try {
- version = new Version(versionProp);
- } catch (IllegalArgumentException e) {
- // do nothing;
- }
- if (VERSION_MAX.compareTo(version) > 0) {
- String policy = properties.getProperty(POLICY_PROP);
- if (policy != null)
- try {
- enforceFlags = Integer.parseInt(policy);
- } catch (NumberFormatException e) {
- // do nothing;
- }
- }
- } else {
- String policy = FrameworkProperties.getProperty(POLICY_PROP);
- if (policy == null || STR_ENFORCE_NONE.equals(policy))
- enforceFlags = ENFORCE_NONE;
- else if (STR_ENFORCE_TRUSTED.equals(policy))
- enforceFlags = ENFORCE_TRUSTED | ENFORCE_SIGNED;
- else if (STR_ENFORCE_SIGNED.equals(policy))
- enforceFlags = ENFORCE_SIGNED;
- else if (STR_ENFORCE_VALIDITY.equals(policy))
- enforceFlags = ENFORCE_TRUSTED | ENFORCE_SIGNED | ENFORCE_VALIDITY;
- }
-
- }
-
- public DefaultAuthorizationEngine(BundleContext context, State systemState) {
- super(context);
- this.bundleContext = context;
- this.systemState = systemState;
- }
-
- protected AuthorizationEvent doAuthorize(SignedContent content, Object context) {
- boolean enabled = isEnabled(content, context);
- AuthorizationEvent event = null;
- if (context instanceof Bundle) {
- BundleDescription desc = systemState.getBundle(((Bundle) context).getBundleId());
- if (!enabled) {
- DisabledInfo info = new DisabledInfo(POLICY_NAME, null, desc); // TODO add an error message
- systemState.addDisabledInfo(info);
- event = new AuthorizationEvent(AuthorizationEvent.DENIED, content, context, 0); // TODO severity??
- } else {
- DisabledInfo info = systemState.getDisabledInfo(desc, POLICY_NAME);
- if (info != null) {
- systemState.removeDisabledInfo(info);
- }
- event = new AuthorizationEvent(AuthorizationEvent.ALLOWED, content, context, 0);
- }
- }
- return event;
- }
-
- private boolean isEnabled(SignedContent content, Object context) {
- if (context instanceof Bundle && DevClassPathHelper.inDevelopmentMode()) {
- String[] devClassPath = DevClassPathHelper.getDevClassPath(((Bundle) context).getSymbolicName());
- if (devClassPath != null && devClassPath.length > 0)
- return true; // always enabled bundles from workspace; they never are signed
- }
- if ((0 != (enforceFlags & ENFORCE_SIGNED)) && ((content == null) || !content.isSigned()))
- return false;
-
- SignerInfo[] signerInfos = content == null ? new SignerInfo[0] : content.getSignerInfos();
- for (int i = 0; i < signerInfos.length; i++) {
- if ((0 != (enforceFlags & ENFORCE_TRUSTED)) && !signerInfos[i].isTrusted())
- return false;
- if ((0 != (enforceFlags & ENFORCE_VALIDITY)))
- try {
- content.checkValidity(signerInfos[i]);
- } catch (CertificateException e) {
- return false;
- }
- }
- return true;
- }
-
- public int getStatus() {
- if (0 != systemState.getDisabledBundles().length) {
- return AuthorizationStatus.ERROR;
- }
- return AuthorizationStatus.OK;
- }
-
- public void processInstalledBundles() {
- Bundle[] bundles = bundleContext.getBundles();
- for (int i = 0; i < bundles.length; i++) {
- BaseData baseData = (BaseData) ((AbstractBundle) bundles[i]).getBundleData();
- SignedStorageHook hook = (SignedStorageHook) baseData.getStorageHook(SignedStorageHook.KEY);
- SignedContent signedContent = hook != null ? hook.getSignedContent() : null;
- authorize(signedContent, bundles[i]);
- }
- }
-
- public void setLoadPolicy(int policy) {
- if ((policy | ENFORCE_SIGNED | ENFORCE_TRUSTED | ENFORCE_VALIDITY) != (ENFORCE_SIGNED | ENFORCE_TRUSTED | ENFORCE_VALIDITY))
- throw new IllegalArgumentException("Invalid policy: " + policy); //$NON-NLS-1$
- enforceFlags = policy;
- Properties properties = new Properties();
- properties.setProperty(POLICY_PROP, Integer.toString(policy));
- properties.setProperty(VERSION_PROP, VERSION_NUM); // need to act different when we have different versions
- try {
- properties.store(new FileOutputStream(policyFile), null);
- } catch (IOException e) {
- SignedBundleHook.log("Error saving load policy file", FrameworkLogEntry.ERROR, e); //$NON-NLS-1$
- }
- }
-
- public int getLoadPolicy() {
- return enforceFlags;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BundleInstallListener.java b/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BundleInstallListener.java
deleted file mode 100644
index 47c8066fe..000000000
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/BundleInstallListener.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.osgi.internal.signedcontent;
-
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.internal.core.AbstractBundle;
-import org.eclipse.osgi.internal.provisional.service.security.AuthorizationEngine;
-import org.eclipse.osgi.signedcontent.SignedContent;
-import org.osgi.framework.*;
-
-public class BundleInstallListener implements SynchronousBundleListener {
-
- public void bundleChanged(BundleEvent event) {
- Bundle bundle = event.getBundle();
- switch (event.getType()) {
- case BundleEvent.UPDATED :
- // fall through to INSTALLED
- case BundleEvent.INSTALLED :
- TrustEngineListener listener = TrustEngineListener.getInstance();
- AuthorizationEngine authEngine = listener == null ? null : listener.getAuthorizationEngine();
- if (authEngine != null) {
- BaseData baseData = (BaseData) ((AbstractBundle) bundle).getBundleData();
- SignedStorageHook hook = (SignedStorageHook) baseData.getStorageHook(SignedStorageHook.KEY);
- SignedContent signedContent = hook != null ? hook.signedContent : null;
- authEngine.authorize(signedContent, bundle);
- }
- break;
- default :
- break;
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/LegacyVerifierFactory.java b/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/LegacyVerifierFactory.java
deleted file mode 100644
index d0ecae651..000000000
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/LegacyVerifierFactory.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.osgi.internal.signedcontent;
-
-import java.io.File;
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.cert.*;
-import java.util.*;
-import org.eclipse.osgi.internal.provisional.verifier.*;
-import org.eclipse.osgi.signedcontent.*;
-import org.osgi.framework.Bundle;
-
-public class LegacyVerifierFactory implements CertificateVerifierFactory {
- private final SignedContentFactory signedContentFactory;
-
- public LegacyVerifierFactory(SignedContentFactory signedContentFactory) {
- this.signedContentFactory = signedContentFactory;
- }
-
- public CertificateVerifier getVerifier(File content) throws IOException {
- try {
- return new LegacyVerifier(signedContentFactory.getSignedContent(content));
- } catch (GeneralSecurityException e) {
- throw (IOException) new IOException(e.getMessage()).initCause(e);
- }
- }
-
- public CertificateVerifier getVerifier(Bundle bundle) throws IOException {
- try {
- return new LegacyVerifier(signedContentFactory.getSignedContent(bundle));
- } catch (GeneralSecurityException e) {
- throw (IOException) new IOException(e.getMessage()).initCause(e);
- }
- }
-
- static class LegacyVerifier implements CertificateVerifier {
- private final SignedContent signedContent;
-
- public LegacyVerifier(SignedContent signedContent) {
- this.signedContent = signedContent;
- }
-
- public void checkContent() throws CertificateException, CertificateExpiredException {
- SignedContentEntry[] entries = signedContent.getSignedEntries();
- for (int i = 0; i < entries.length; i++) {
- try {
- entries[i].verify();
- } catch (InvalidContentException e) {
- throw (SecurityException) new SecurityException(e.getMessage()).initCause(e);
- } catch (IOException e) {
- throw (SecurityException) new SecurityException(e.getMessage()).initCause(e);
- }
- }
- SignerInfo[] infos = signedContent.getSignerInfos();
- for (int i = 0; i < infos.length; i++)
- signedContent.checkValidity(infos[i]);
- }
-
- public CertificateChain[] getChains() {
- SignerInfo infos[] = signedContent.getSignerInfos();
- CertificateChain[] chains = new CertificateChain[infos.length];
- for (int i = 0; i < chains.length; i++)
- chains[i] = new LegacyChain(infos[i], signedContent);
- return chains;
- }
-
- public boolean isSigned() {
- return signedContent.isSigned();
- }
-
- public String[] verifyContent() {
- List<String> invalidContent = new ArrayList<String>(0);
- SignedContentEntry[] entries = signedContent.getSignedEntries();
- for (int i = 0; i < entries.length; i++) {
- try {
- entries[i].verify();
- } catch (InvalidContentException e) {
- invalidContent.add(entries[i].getName());
- } catch (IOException e) {
- invalidContent.add(entries[i].getName());
- }
- }
- return invalidContent.toArray(new String[invalidContent.size()]);
- }
- }
-
- static class LegacyChain implements CertificateChain {
- private final SignerInfo signerInfo;
- private final SignedContent content;
-
- public LegacyChain(SignerInfo signerInfo, SignedContent content) {
- this.signerInfo = signerInfo;
- this.content = content;
- }
-
- public Certificate[] getCertificates() {
- return signerInfo.getCertificateChain();
- }
-
- public String getChain() {
- StringBuffer sb = new StringBuffer();
- Certificate[] certs = getCertificates();
- for (int i = 0; i < certs.length; i++) {
- X509Certificate x509Cert = ((X509Certificate) certs[i]);
- sb.append(x509Cert.getSubjectDN().getName());
- sb.append("; "); //$NON-NLS-1$
- }
- return sb.toString();
- }
-
- public Certificate getRoot() {
- Certificate[] certs = getCertificates();
- return certs.length > 0 ? certs[certs.length - 1] : null;
- }
-
- public Certificate getSigner() {
- Certificate[] certs = getCertificates();
- return certs.length > 0 ? certs[0] : null;
- }
-
- public Date getSigningTime() {
- return content.getSigningTime(signerInfo);
- }
-
- public boolean isTrusted() {
- return signerInfo.isTrusted();
- }
-
- }
-}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java b/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java
deleted file mode 100644
index 2fe55e59c..000000000
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/SignedStorageHook.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2010 IBM Corporation and others. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.osgi.internal.signedcontent;
-
-import java.io.*;
-import java.security.cert.*;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
-import org.eclipse.osgi.framework.util.KeyedElement;
-import org.eclipse.osgi.signedcontent.SignedContent;
-import org.eclipse.osgi.signedcontent.SignerInfo;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-
-public class SignedStorageHook implements StorageHook {
- public static final String KEY = SignedStorageHook.class.getName();
- public static final int HASHCODE = KEY.hashCode();
- private static final int STORAGE_VERSION = 3;
- private static List<SignerInfo> savedSignerInfo = new ArrayList<SignerInfo>(5);
- private static long firstIDSaved = -1;
- private static long lastIDSaved = -1;
- private static List<SignerInfo> loadedSignerInfo = new ArrayList<SignerInfo>(5);
- private static long lastIDLoaded;
-
- private BaseData bundledata;
- SignedContentImpl signedContent;
-
- public int getStorageVersion() {
- return STORAGE_VERSION;
- }
-
- /**
- * @throws BundleException
- */
- public StorageHook create(BaseData data) throws BundleException {
- SignedStorageHook hook = new SignedStorageHook();
- hook.bundledata = data;
- return hook;
- }
-
- /**
- * @throws BundleException
- */
- public void initialize(Dictionary<String, String> manifest) throws BundleException {
- // do nothing
- }
-
- public StorageHook load(BaseData target, DataInputStream is) throws IOException {
- if (lastIDLoaded > target.getBundleID())
- loadedSignerInfo.clear();
- lastIDLoaded = target.getBundleID();
- SignedStorageHook hook = new SignedStorageHook();
- hook.bundledata = target;
- boolean signed = is.readBoolean();
- if (!signed)
- return hook;
- int numSigners = is.readInt();
- SignerInfo[] signerInfos = new SignerInfo[numSigners];
- for (int i = 0; i < numSigners; i++)
- signerInfos[i] = readSignerInfo(is);
-
- int resultsSize = is.readInt();
- Map<String, Object> contentMDResults = null;
- if (resultsSize > 0) {
- contentMDResults = new HashMap<String, Object>(resultsSize);
- for (int i = 0; i < resultsSize; i++) {
- String path = is.readUTF();
- int numEntrySigners = is.readInt();
- SignerInfo[] entrySigners = new SignerInfo[numEntrySigners];
- byte[][] entryResults = new byte[numEntrySigners][];
- for (int j = 0; j < numEntrySigners; j++) {
- entrySigners[j] = readSignerInfo(is);
- int resultSize = is.readInt();
- entryResults[j] = new byte[resultSize];
- is.readFully(entryResults[j]);
- }
- contentMDResults.put(path, new Object[] {entrySigners, entryResults});
- }
- }
- SignedContentImpl result = new SignedContentImpl(signerInfos, contentMDResults);
- for (int i = 0; i < numSigners; i++) {
- boolean hasTSA = is.readBoolean();
- if (!hasTSA)
- continue;
- SignerInfo tsaSigner = readSignerInfo(is);
- Date signingDate = new Date(is.readLong());
- result.addTSASignerInfo(signerInfos[i], tsaSigner, signingDate);
- }
- hook.signedContent = result;
- return hook;
- }
-
- public void save(DataOutputStream os) throws IOException {
- getFirstLastID();
- if (firstIDSaved == bundledata.getBundleID())
- savedSignerInfo.clear();
- if (lastIDSaved == bundledata.getBundleID())
- firstIDSaved = lastIDSaved = -1;
- os.writeBoolean(signedContent != null);
- if (signedContent == null)
- return;
- SignerInfo[] signerInfos = signedContent.getSignerInfos();
- os.writeInt(signerInfos.length);
- for (int i = 0; i < signerInfos.length; i++)
- saveSignerInfo(signerInfos[i], os);
-
- // keyed by entry path -> {SignerInfo[] infos, byte[][] results)}
- Map<String, Object> contentMDResults = signedContent.getContentMDResults();
- os.writeInt(contentMDResults == null ? -1 : contentMDResults.size());
- if (contentMDResults != null)
- for (Map.Entry<String, Object> entry : contentMDResults.entrySet()) {
- String path = entry.getKey();
- os.writeUTF(path);
- Object[] signerResults = (Object[]) entry.getValue();
- SignerInfo[] entrySigners = (SignerInfo[]) signerResults[0];
- byte[][] entryResults = (byte[][]) signerResults[1];
- os.writeInt(entrySigners.length);
- for (int i = 0; i < entrySigners.length; i++) {
- saveSignerInfo(entrySigners[i], os);
- os.writeInt(entryResults[i].length);
- os.write(entryResults[i]);
- }
- }
-
- for (int i = 0; i < signerInfos.length; i++) {
- SignerInfo tsaInfo = signedContent.getTSASignerInfo(signerInfos[i]);
- os.writeBoolean(tsaInfo != null);
- if (tsaInfo == null)
- continue;
- saveSignerInfo(tsaInfo, os);
- Date signingTime = signedContent.getSigningTime(signerInfos[i]);
- os.writeLong(signingTime != null ? signingTime.getTime() : Long.MIN_VALUE);
- }
- }
-
- private void saveSignerInfo(SignerInfo signerInfo, DataOutputStream os) throws IOException {
- int cacheIdx = savedSignerInfo.indexOf(signerInfo);
- os.writeInt(cacheIdx);
- if (cacheIdx >= 0)
- return;
- Certificate[] certs = signerInfo.getCertificateChain();
- int anchorIndex = -1;
- os.writeInt(certs == null ? 0 : certs.length);
- if (certs != null)
- for (int i = 0; i < certs.length; i++) {
- if (certs[i].equals(signerInfo.getTrustAnchor()))
- anchorIndex = i;
- byte[] certBytes;
- try {
- certBytes = certs[i].getEncoded();
- } catch (CertificateEncodingException e) {
- throw (IOException) new IOException(e.getMessage()).initCause(e);
- }
- os.writeInt(certBytes.length);
- os.write(certBytes);
- }
- os.writeInt(anchorIndex);
- os.writeUTF(signerInfo.getMessageDigestAlgorithm());
- savedSignerInfo.add(signerInfo);
- }
-
- private SignerInfo readSignerInfo(DataInputStream is) throws IOException {
- int index = is.readInt();
- if (index >= 0)
- return loadedSignerInfo.get(index);
- int numCerts = is.readInt();
- Certificate[] certs = new Certificate[numCerts];
- for (int i = 0; i < numCerts; i++) {
- int certSize = is.readInt();
- byte[] certBytes = new byte[certSize];
- is.readFully(certBytes);
- try {
- certs[i] = PKCS7Processor.certFact.generateCertificate(new ByteArrayInputStream(certBytes));
- } catch (CertificateException e) {
- throw (IOException) new IOException(e.getMessage()).initCause(e);
- }
- }
- int anchorIdx = is.readInt();
- SignerInfoImpl result = new SignerInfoImpl(certs, anchorIdx >= 0 ? certs[anchorIdx] : null, is.readUTF());
- loadedSignerInfo.add(result);
- return result;
- }
-
- private void getFirstLastID() {
- if (firstIDSaved >= 0)
- return;
- Bundle[] bundles = bundledata.getAdaptor().getContext().getBundles();
- if (bundles.length > 1) {
- firstIDSaved = bundles[1].getBundleId();
- lastIDSaved = bundles[bundles.length - 1].getBundleId();
- }
- }
-
- public void copy(StorageHook storageHook) {
- // do nothing
- }
-
- public void validate() throws IllegalArgumentException {
- // do nothing
- }
-
- /**
- * @throws BundleException
- */
- public Dictionary<String, String> getManifest(boolean firstLoad) throws BundleException {
- // do nothing
- return null;
- }
-
- public boolean forgetStatusChange(int status) {
- // do nothing
- return false;
- }
-
- public boolean forgetStartLevelChange(int startlevel) {
- // do nothing
- return false;
- }
-
- public int getKeyHashCode() {
- return HASHCODE;
- }
-
- public boolean compare(KeyedElement other) {
- return other.getKey() == KEY;
- }
-
- public Object getKey() {
- return KEY;
- }
-
- public SignedContent getSignedContent() {
- return signedContent;
- }
-
-}
diff --git a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java b/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java
deleted file mode 100644
index e965a401f..000000000
--- a/bundles/org.eclipse.osgi/security/src/org/eclipse/osgi/internal/signedcontent/TrustEngineListener.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.osgi.internal.signedcontent;
-
-import java.security.cert.Certificate;
-import java.util.*;
-import org.eclipse.osgi.baseadaptor.BaseData;
-import org.eclipse.osgi.framework.internal.core.*;
-import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.internal.provisional.service.security.AuthorizationEngine;
-import org.eclipse.osgi.signedcontent.SignerInfo;
-import org.osgi.framework.*;
-import org.osgi.framework.Constants;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-
-public class TrustEngineListener {
- // this is a singleton listener; see SignedBundleHook for initialization
- private volatile static TrustEngineListener instance;
- private final BundleContext context;
- private final ServiceTracker<AuthorizationEngine, AuthorizationEngine> authorizationTracker;
-
- TrustEngineListener(BundleContext context) {
- this.context = context;
- // read the trust provider security property
- String authEngineProp = FrameworkProperties.getProperty(SignedContentConstants.AUTHORIZATION_ENGINE);
- Filter filter = null;
- if (authEngineProp != null)
- try {
- filter = FilterImpl.newInstance("(&(" + Constants.OBJECTCLASS + "=" + AuthorizationEngine.class.getName() + ")(" + SignedContentConstants.AUTHORIZATION_ENGINE + "=" + authEngineProp + "))"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$
- } catch (InvalidSyntaxException e) {
- SignedBundleHook.log("Invalid authorization filter", FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
- }
- if (filter != null)
- authorizationTracker = new ServiceTracker<AuthorizationEngine, AuthorizationEngine>(context, filter, null);
- else
- authorizationTracker = new ServiceTracker<AuthorizationEngine, AuthorizationEngine>(context, AuthorizationEngine.class.getName(), null);
- authorizationTracker.open();
- instance = this;
- }
-
- public static TrustEngineListener getInstance() {
- return instance;
- }
-
- void stopTrustEngineListener() {
- authorizationTracker.close();
- instance = null;
- }
-
- public void addedTrustAnchor(Certificate anchor) {
- // find any SignedContent with SignerInfos that do not have an anchor;
- // re-evaluate trust and check authorization for these SignedContents
- Bundle[] bundles = context.getBundles();
- Set<Bundle> unresolved = new HashSet<Bundle>();
- for (int i = 0; i < bundles.length; i++) {
- SignedContentImpl signedContent = getSignedContent(bundles[i]);
- if (signedContent != null && signedContent.isSigned()) {
- // check the SignerInfos for this content
- SignerInfo[] infos = signedContent.getSignerInfos();
- for (int j = 0; j < infos.length; j++) {
- if (infos[j].getTrustAnchor() == null)
- // one of the signers is not trusted
- unresolved.add(bundles[i]);
- SignerInfo tsa = signedContent.getTSASignerInfo(infos[j]);
- if (tsa != null && tsa.getTrustAnchor() == null)
- // one of the tsa signers is not trusted
- unresolved.add(bundles[i]);
- }
- }
- if (unresolved.contains(bundles[i])) {
- // found an untrusted signer for this bundle re-evaluate trust
- SignedBundleFile.determineTrust(signedContent, SignedBundleHook.VERIFY_TRUST);
- // now check the authorization handler
- checkAuthorization(signedContent, bundles[i]);
- }
- }
- // try to resolve
- if (unresolved.size() > 0)
- resolveBundles(unresolved.toArray(new Bundle[unresolved.size()]), false);
- }
-
- private void checkAuthorization(SignedContentImpl signedContent, Bundle bundle) {
- AuthorizationEngine authEngine = getAuthorizationEngine();
- if (authEngine != null)
- authEngine.authorize(signedContent, bundle);
- }
-
- AuthorizationEngine getAuthorizationEngine() {
- return authorizationTracker.getService();
- }
-
- private void resolveBundles(Bundle[] bundles, boolean refresh) {
- ServiceReference<?> ref = context.getServiceReference(PackageAdmin.class.getName());
- if (ref == null)
- return;
- PackageAdmin pa = (PackageAdmin) context.getService(ref);
- if (pa == null)
- return;
- try {
- if (refresh)
- pa.refreshPackages(bundles);
- else
- pa.resolveBundles(bundles);
- } finally {
- context.ungetService(ref);
- }
- }
-
- public void removedTrustAnchor(Certificate anchor) {
- // find any signed content that has signerinfos with the supplied anchor
- // re-evaluate trust and check authorization again.
- Bundle[] bundles = context.getBundles();
- Set<Bundle> usingAnchor = new HashSet<Bundle>();
- Set<SignerInfo> untrustedSigners = new HashSet<SignerInfo>();
- for (int i = 0; i < bundles.length; i++) {
- SignedContentImpl signedContent = getSignedContent(bundles[i]);
- if (signedContent != null && signedContent.isSigned()) {
- // check signer infos for this content
- SignerInfo[] infos = signedContent.getSignerInfos();
- for (int j = 0; j < infos.length; j++) {
- if (anchor.equals(infos[j].getTrustAnchor())) {
- // one of the signers uses this anchor
- untrustedSigners.add(infos[j]);
- usingAnchor.add(bundles[i]);
- }
- SignerInfo tsa = signedContent.getTSASignerInfo(infos[j]);
- if (tsa != null && anchor.equals(tsa.getTrustAnchor())) {
- // one of the tsa signers uses this anchor
- usingAnchor.add(bundles[i]);
- untrustedSigners.add(tsa);
- }
- }
- }
- }
- // remove trust anchors from untrusted signers
- for (Iterator<SignerInfo> untrusted = untrustedSigners.iterator(); untrusted.hasNext();)
- ((SignerInfoImpl) untrusted.next()).setTrustAnchor(null);
- // re-establish trust and check authorization
- for (Iterator<Bundle> untrustedBundles = usingAnchor.iterator(); untrustedBundles.hasNext();) {
- Bundle bundle = untrustedBundles.next();
- SignedContentImpl signedContent = getSignedContent(bundle);
- // found an signer using the anchor for this bundle re-evaluate trust
- SignedBundleFile.determineTrust(signedContent, SignedBundleHook.VERIFY_TRUST);
- // now check the authorization handler
- checkAuthorization(signedContent, bundle);
- }
- // TODO an optimization here would be to check for real DisabledInfo objects for each bundle
- // try to refresh
- if (usingAnchor.size() > 0)
- resolveBundles(usingAnchor.toArray(new Bundle[usingAnchor.size()]), true);
- }
-
- private SignedContentImpl getSignedContent(Bundle bundle) {
- BaseData data = (BaseData) ((AbstractBundle) bundle).getBundleData();
- SignedStorageHook hook = (SignedStorageHook) data.getStorageHook(SignedStorageHook.KEY);
- if (hook == null)
- return null;
- return (SignedContentImpl) hook.getSignedContent();
- }
-}
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/ExternalMessages.properties b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/ExternalMessages.properties
index e0e3f9d60..7174046a1 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/ExternalMessages.properties
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/ExternalMessages.properties
@@ -63,3 +63,13 @@ STARTLEVEL_CANT_CHANGE_SYSTEMBUNDLE_STARTLEVEL=The System Bundle's start level c
CANNOT_SET_CONTEXTFINDER=The context finder has not been installed.
URL_HANDLER_INCORRECT_TYPE=The service property "{0}" is not the correct type for the service "{1}" registered by the bundle "{2}"
+
+HEADER_REQUIRED=The \"{0}\" header must be specified
+HEADER_PACKAGE_DUPLICATES=Cannot import a package more than once \"{0}\"
+HEADER_PACKAGE_JAVA=Cannot specify java.* packages in Import/Export headers \"{0}\"
+HEADER_VERSION_ERROR=The attributes \"{0}\" and \"{1}\" must match
+HEADER_EXPORT_ATTR_ERROR=Specifying \"{0}\" in the \"{1}\" header is not permitted
+HEADER_DIRECTIVE_DUPLICATES=Duplicate directives are not permitted \"{0}\"
+HEADER_ATTRIBUTE_DUPLICATES=Duplicate attributes are not permitted \"{0}\"
+HEADER_EXTENSION_ERROR=Extension bundle is not a fragment to the system bundle \"{0}\"
+
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/FrameworkProperties.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/FrameworkProperties.java
deleted file mode 100644
index 7767c0512..000000000
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/FrameworkProperties.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Cognos Incorporated, IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- *******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
-
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.security.CodeSource;
-import java.util.*;
-import org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorMsg;
-import org.eclipse.osgi.util.NLS;
-
-/*
- * This class should be used in ALL places in the framework implementation to get "system" properties.
- * The static methods on this class should be used instead of the System#getProperty, System#setProperty etc methods.
- */
-public class FrameworkProperties {
-
- /**@GuardedBy FrameworkProperties.class*/
- private static Properties properties;
-
- // A flag of some sort will have to be supported.
- // Many existing plugins get framework propeties directly from System instead of BundleContext.
- // Note that the OSGi TCK is one example where this property MUST be set to false because many TCK bundles set and read system properties.
- private static final String USING_SYSTEM_PROPERTIES_KEY = "osgi.framework.useSystemProperties"; //$NON-NLS-1$
- private static final String PROP_FRAMEWORK = "osgi.framework"; //$NON-NLS-1$
- private static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
-
- public static Properties getProperties() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPropertiesAccess();
- return internalGetProperties(null);
- }
-
- public static String getProperty(String key) {
- return getProperty(key, null);
- }
-
- public static String getProperty(String key, String defaultValue) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPropertyAccess(key);
- return internalGetProperties(null).getProperty(key, defaultValue);
- }
-
- public static String setProperty(String key, String value) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new PropertyPermission(key, "write")); //$NON-NLS-1$
- return (String) internalGetProperties(null).put(key, value);
- }
-
- public static String clearProperty(String key) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new PropertyPermission(key, "write")); //$NON-NLS-1$
- return (String) internalGetProperties(null).remove(key);
- }
-
- private static synchronized Properties internalGetProperties(String usingSystemProperties) {
- if (properties == null) {
- Properties systemProperties = System.getProperties();
- if (usingSystemProperties == null)
- usingSystemProperties = systemProperties.getProperty(USING_SYSTEM_PROPERTIES_KEY);
- if (usingSystemProperties == null || usingSystemProperties.equalsIgnoreCase(Boolean.TRUE.toString())) {
- properties = systemProperties;
- } else {
- // use systemProperties for a snapshot
- // also see requirements in Bundlecontext.getProperty(...))
- properties = new Properties();
- // snapshot of System properties for uses of getProperties who expect to see framework properties set as System properties
- // we need to do this for all system properties because the properties object is used to back
- // BundleContext#getProperty method which expects all system properties to be available
- synchronized (systemProperties) {
- // bug 360198 - must synchronize on systemProperties to avoid concurrent modification exception
- properties.putAll(systemProperties);
- }
- }
- }
- return properties;
- }
-
- public static synchronized void setProperties(Map<String, String> input) {
- if (input == null) {
- // just use internal props; note that this will reuse a previous set of properties if they were set
- internalGetProperties("false"); //$NON-NLS-1$
- return;
- }
- properties = null;
- Properties toSet = internalGetProperties("false"); //$NON-NLS-1$
- for (Iterator<String> keys = input.keySet().iterator(); keys.hasNext();) {
- String key = keys.next();
- Object value = input.get(key);
- if (value instanceof String) {
- toSet.setProperty(key, (String) value);
- continue;
- }
- value = input.get(key);
- if (value != null)
- toSet.put(key, value);
- else
- toSet.remove(key);
- }
- }
-
- public static synchronized boolean inUse() {
- return properties != null;
- }
-
- public static void initializeProperties() {
- // initialize some framework properties that must always be set
- if (getProperty(PROP_FRAMEWORK) == null || getProperty(PROP_INSTALL_AREA) == null) {
- CodeSource cs = FrameworkProperties.class.getProtectionDomain().getCodeSource();
- if (cs == null)
- throw new IllegalArgumentException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_PROPS_NOT_SET, PROP_FRAMEWORK + ", " + PROP_INSTALL_AREA)); //$NON-NLS-1$
- URL url = cs.getLocation();
- // allow props to be preset
- if (getProperty(PROP_FRAMEWORK) == null)
- setProperty(PROP_FRAMEWORK, url.toExternalForm());
- if (getProperty(PROP_INSTALL_AREA) == null) {
- String filePart = url.getFile();
- setProperty(PROP_INSTALL_AREA, filePart.substring(0, filePart.lastIndexOf('/')));
- }
- }
- // always decode these properties
- setProperty(PROP_FRAMEWORK, decode(getProperty(PROP_FRAMEWORK)));
- setProperty(PROP_INSTALL_AREA, decode(getProperty(PROP_INSTALL_AREA)));
- }
-
- public static String decode(String urlString) {
- //try to use Java 1.4 method if available
- try {
- Class<? extends URLDecoder> clazz = URLDecoder.class;
- Method method = clazz.getDeclaredMethod("decode", new Class[] {String.class, String.class}); //$NON-NLS-1$
- //first encode '+' characters, because URLDecoder incorrectly converts
- //them to spaces on certain class library implementations.
- if (urlString.indexOf('+') >= 0) {
- int len = urlString.length();
- StringBuffer buf = new StringBuffer(len);
- for (int i = 0; i < len; i++) {
- char c = urlString.charAt(i);
- if (c == '+')
- buf.append("%2B"); //$NON-NLS-1$
- else
- buf.append(c);
- }
- urlString = buf.toString();
- }
- Object result = method.invoke(null, new Object[] {urlString, "UTF-8"}); //$NON-NLS-1$
- if (result != null)
- return (String) result;
- } catch (Exception e) {
- //JDK 1.4 method not found -- fall through and decode by hand
- }
- //decode URL by hand
- boolean replaced = false;
- byte[] encodedBytes = urlString.getBytes();
- int encodedLength = encodedBytes.length;
- byte[] decodedBytes = new byte[encodedLength];
- int decodedLength = 0;
- for (int i = 0; i < encodedLength; i++) {
- byte b = encodedBytes[i];
- if (b == '%') {
- byte enc1 = encodedBytes[++i];
- byte enc2 = encodedBytes[++i];
- b = (byte) ((hexToByte(enc1) << 4) + hexToByte(enc2));
- replaced = true;
- }
- decodedBytes[decodedLength++] = b;
- }
- if (!replaced)
- return urlString;
- try {
- return new String(decodedBytes, 0, decodedLength, "UTF-8"); //$NON-NLS-1$
- } catch (UnsupportedEncodingException e) {
- //use default encoding
- return new String(decodedBytes, 0, decodedLength);
- }
- }
-
- private static int hexToByte(byte b) {
- switch (b) {
- case '0' :
- return 0;
- case '1' :
- return 1;
- case '2' :
- return 2;
- case '3' :
- return 3;
- case '4' :
- return 4;
- case '5' :
- return 5;
- case '6' :
- return 6;
- case '7' :
- return 7;
- case '8' :
- return 8;
- case '9' :
- return 9;
- case 'A' :
- case 'a' :
- return 10;
- case 'B' :
- case 'b' :
- return 11;
- case 'C' :
- case 'c' :
- return 12;
- case 'D' :
- case 'd' :
- return 13;
- case 'E' :
- case 'e' :
- return 14;
- case 'F' :
- case 'f' :
- return 15;
- default :
- throw new IllegalArgumentException("Switch error decoding URL"); //$NON-NLS-1$
- }
- }
-}
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Msg.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Msg.java
index fd32c8c28..a09bc6ee7 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Msg.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Msg.java
@@ -81,8 +81,17 @@ public class Msg extends NLS {
public static String URL_HANDLER_INCORRECT_TYPE;
+ public static String HEADER_REQUIRED;
+ public static String HEADER_PACKAGE_DUPLICATES;
+ public static String HEADER_PACKAGE_JAVA;
+ public static String HEADER_VERSION_ERROR;
+ public static String HEADER_EXPORT_ATTR_ERROR;
+ public static String HEADER_DIRECTIVE_DUPLICATES;
+ public static String HEADER_ATTRIBUTE_DUPLICATES;
+ public static String HEADER_EXTENSION_ERROR;
+
static {
// initialize resource bundles
NLS.initializeMessages(BUNDLE_NAME, Msg.class);
}
-} \ No newline at end of file
+}
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/reliablefile/ReliableFile.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/reliablefile/ReliableFile.java
index 9582ee5f5..6db71a435 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/reliablefile/ReliableFile.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/reliablefile/ReliableFile.java
@@ -15,7 +15,6 @@ import java.io.*;
import java.util.*;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
/**
* ReliableFile class used by ReliableFileInputStream and ReliableOutputStream.
@@ -71,7 +70,7 @@ public class ReliableFile {
*/
public static final String PROP_MAX_GENERATIONS = "osgi.ReliableFile.maxGenerations"; //$NON-NLS-1$
/**
- * @see org.eclipse.core.runtime.internal.adaptor.BasicLocation#PROP_OSGI_LOCKING
+ * @see org.eclipse.osgi.internal.location.BasicLocation#PROP_OSGI_LOCKING
*/
public static final String PROP_OSGI_LOCKING = "osgi.locking"; //$NON-NLS-1$
@@ -92,7 +91,7 @@ public class ReliableFile {
private static final Object lastGenerationLock = new Object();
static {
- String prop = FrameworkProperties.getProperty(PROP_MAX_BUFFER);
+ String prop = System.getProperty(PROP_MAX_BUFFER);
int tmpMaxInput = 128 * 1024; //128k
if (prop != null) {
try {
@@ -103,7 +102,7 @@ public class ReliableFile {
maxInputStreamBuffer = tmpMaxInput;
int tmpDefaultMax = 2;
- prop = FrameworkProperties.getProperty(PROP_MAX_GENERATIONS);
+ prop = System.getProperty(PROP_MAX_GENERATIONS);
if (prop != null) {
try {
tmpDefaultMax = Integer.parseInt(prop);
@@ -112,7 +111,7 @@ public class ReliableFile {
}
defaultMaxGenerations = tmpDefaultMax;
- prop = FrameworkProperties.getProperty(PROP_OSGI_LOCKING);
+ prop = System.getProperty(PROP_OSGI_LOCKING);
boolean tmpFileSharing = true;
if (prop != null) {
if (prop.equals("none")) { //$NON-NLS-1$
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/util/SecureAction.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/util/SecureAction.java
index 2e654b16c..7db659307 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/util/SecureAction.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/util/SecureAction.java
@@ -14,10 +14,8 @@ package org.eclipse.osgi.framework.util;
import java.io.*;
import java.net.*;
import java.security.*;
-import java.util.Properties;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
@@ -70,43 +68,10 @@ public class SecureAction {
*/
public String getProperty(final String property) {
if (System.getSecurityManager() == null)
- return FrameworkProperties.getProperty(property);
+ return System.getProperty(property);
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
- return FrameworkProperties.getProperty(property);
- }
- }, controlContext);
- }
-
- /**
- * Returns a system property. Same as calling
- * System.getProperty(String,String).
- * @param property the property key.
- * @param def the default value if the property key does not exist.
- * @return the value of the property or the def value if the property
- * does not exist.
- */
- public String getProperty(final String property, final String def) {
- if (System.getSecurityManager() == null)
- return FrameworkProperties.getProperty(property, def);
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
- public String run() {
- return FrameworkProperties.getProperty(property, def);
- }
- }, controlContext);
- }
-
- /**
- * Returns the system properties. Same as calling
- * System.getProperties().
- * @return the system properties.
- */
- public Properties getProperties() {
- if (System.getSecurityManager() == null)
- return FrameworkProperties.getProperties();
- return AccessController.doPrivileged(new PrivilegedAction<Properties>() {
- public Properties run() {
- return FrameworkProperties.getProperties();
+ return System.getProperty(property);
}
}, controlContext);
}
@@ -213,6 +178,16 @@ public class SecureAction {
}, controlContext).booleanValue();
}
+ public boolean mkdirs(final File file) {
+ if (System.getSecurityManager() == null)
+ return file.mkdirs();
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ return file.mkdirs() ? Boolean.TRUE : Boolean.FALSE;
+ }
+ }, controlContext).booleanValue();
+ }
+
/**
* Returns true if a file is a directory, otherwise false is returned. Same as calling
* file.isDirectory().
@@ -463,4 +438,15 @@ public class SecureAction {
public void start(final Bundle bundle) throws BundleException {
start(bundle, 0);
}
+
+ public BundleContext getContext(final Bundle bundle) {
+ if (System.getSecurityManager() == null) {
+ return bundle.getBundleContext();
+ }
+ return AccessController.doPrivileged(new PrivilegedAction<BundleContext>() {
+ public BundleContext run() {
+ return bundle.getBundleContext();
+ }
+ }, controlContext);
+ }
}
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/Debug.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/Debug.java
index b9443df43..ced7f37cc 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/Debug.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/Debug.java
@@ -9,10 +9,12 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.debug;
+package org.eclipse.osgi.internal.debug;
import java.io.PrintStream;
import java.lang.reflect.*;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
+import org.eclipse.osgi.service.debug.DebugOptions;
/**
* This class has debug constants which can be used by the Framework implementation
@@ -21,160 +23,174 @@ import java.lang.reflect.*;
*/
public class Debug {
/**
- * Indicates if tracing is enabled
+ * Base debug option key (org.eclispe.osgi).
*/
- public static boolean DEBUG_ENABLED = false;
-
+ public static final String ECLIPSE_OSGI = EquinoxContainer.NAME;
/**
- * General debug flag.
+ * General Debug option key.
*/
- public static boolean DEBUG_GENERAL = false; // "debug"
+ public static final String OPTION_DEBUG_GENERAL = ECLIPSE_OSGI + "/debug"; //$NON-NLS-1$
/**
- * Bundle time debug flag.
+ * Bundle time Debug option key.
*/
- public static boolean DEBUG_BUNDLE_TIME = false; //"debug.bundleTime"
+ // TODO remove this or use it somewhere
+ public static final String OPTION_DEBUG_BUNDLE_TIME = ECLIPSE_OSGI + "/debug/bundleTime"; //$NON-NLS-1$
/**
- * Loader debug flag.
+ * Loader Debug option key.
*/
- public static boolean DEBUG_LOADER = false; // "debug.loader"
+ public static final String OPTION_DEBUG_LOADER = ECLIPSE_OSGI + "/debug/loader"; //$NON-NLS-1$
/**
- * Events debug flag.
+ * Events Debug option key.
*/
- public static boolean DEBUG_EVENTS = false; // "debug.events"
+ public static final String OPTION_DEBUG_EVENTS = ECLIPSE_OSGI + "/debug/events"; //$NON-NLS-1$
/**
- * Services debug flag.
+ * Services Debug option key.
*/
- public static boolean DEBUG_SERVICES = false; // "debug.services"
-
+ public static final String OPTION_DEBUG_SERVICES = ECLIPSE_OSGI + "/debug/services"; //$NON-NLS-1$
/**
- * Hooks debug flag.
+ * Services Debug option key.
*/
- public static boolean DEBUG_HOOKS = false; // "debug.hooks"
+ public static final String OPTION_DEBUG_HOOKS = ECLIPSE_OSGI + "/debug/hooks"; //$NON-NLS-1$
/**
- * Packages debug flag.
+ * Packages Debug option key.
*/
- // TODO remove this or use it somewhere
- public static boolean DEBUG_PACKAGES = false; // "debug.packages"
+ public static final String OPTION_DEBUG_PACKAGES = ECLIPSE_OSGI + "/debug/packages"; //$NON-NLS-1$
/**
- * Manifest debug flag.
+ * Manifest Debug option key.
*/
- public static boolean DEBUG_MANIFEST = false; // "debug.manifest"
+ public static final String OPTION_DEBUG_MANIFEST = ECLIPSE_OSGI + "/debug/manifest"; //$NON-NLS-1$
/**
- * Filter debug flag.
+ * Filter Debug option key.
*/
- public static boolean DEBUG_FILTER = false; // "debug.filter"
+ public static final String OPTION_DEBUG_FILTER = ECLIPSE_OSGI + "/debug/filter"; //$NON-NLS-1$
/**
- * Security debug flag.
+ * Security Debug option key.
*/
- public static boolean DEBUG_SECURITY = false; // "debug.security"
+ public static final String OPTION_DEBUG_SECURITY = ECLIPSE_OSGI + "/debug/security"; //$NON-NLS-1$
/**
- * Start level debug flag.
+ * Start level Debug option key.
*/
- public static boolean DEBUG_STARTLEVEL = false; // "debug.startlevel"
+ public static final String OPTION_DEBUG_STARTLEVEL = ECLIPSE_OSGI + "/debug/startlevel"; //$NON-NLS-1$
/**
- * PackageAdmin debug flag.
+ * PackageAdmin Debug option key.
*/
- public static boolean DEBUG_PACKAGEADMIN = false; // "debug.packageadmin"
+ public static final String OPTION_DEBUG_PACKAGEADMIN = ECLIPSE_OSGI + "/debug/packageadmin"; //$NON-NLS-1$
/**
- * PackageAdmin timing debug flag.
+ * PackageAdmin timing Debug option key.
*/
- // TODO remove this or use it somewhere
- public static boolean DEBUG_PACKAGEADMIN_TIMING = false; //"debug.packageadmin/timing"
+ public static final String OPTION_DEBUG_PACKAGEADMIN_TIMING = ECLIPSE_OSGI + "/debug/packageadmin/timing"; //$NON-NLS-1$
/**
- * Message debug flag.
+ * Monitor activation Debug option key.
*/
- public static boolean DEBUG_MESSAGE_BUNDLES = false; //"/debug/messageBundles"
+ public static final String OPTION_MONITOR_ACTIVATION = ECLIPSE_OSGI + "/monitor/activation"; //$NON-NLS-1$
/**
- * Monitor activation debug flag.
+ * Message bundles Debug option key.
*/
- public static boolean MONITOR_ACTIVATION = false; // "monitor/bundles"
+ public static final String OPTION_DEBUG_MESSAGE_BUNDLES = ECLIPSE_OSGI + "/debug/messageBundles"; //$NON-NLS-1$
+
+ public static final String OPTION_DEBUG_LOCATION = ECLIPSE_OSGI + "/debug/location"; //$NON-NLS-1$
/**
- * Base debug option key (org.eclispe.osgi).
+ * Indicates if tracing is enabled
*/
- public static final String ECLIPSE_OSGI = "org.eclipse.osgi"; //$NON-NLS-1$
+ public boolean DEBUG_ENABLED = false;
+
+ // these static debug options are left overs because it would be messy to fix references to them
+ // this means that if multiple frameworks are using this class these debug options may get overwritten
+ public static boolean STATIC_DEBUG_GENERAL = false; // "debug"
+ public static boolean STATIC_DEBUG_MANIFEST = false; // "debug.manifest"
+ public static boolean STATIC_DEBUG_MESSAGE_BUNDLES = false; //"/debug/messageBundles"
+
/**
- * General Debug option key.
+ * General debug flag.
*/
- public static final String OPTION_DEBUG_GENERAL = ECLIPSE_OSGI + "/debug"; //$NON-NLS-1$
+ public boolean DEBUG_GENERAL = false; // "debug"
/**
- * Bundle time Debug option key.
+ * Bundle time debug flag.
*/
- // TODO remove this or use it somewhere
- public static final String OPTION_DEBUG_BUNDLE_TIME = ECLIPSE_OSGI + "/debug/bundleTime"; //$NON-NLS-1$
+ public boolean DEBUG_BUNDLE_TIME = false; //"debug.bundleTime"
/**
- * Loader Debug option key.
+ * Loader debug flag.
*/
- public static final String OPTION_DEBUG_LOADER = ECLIPSE_OSGI + "/debug/loader"; //$NON-NLS-1$
+ public boolean DEBUG_LOADER = false; // "debug.loader"
/**
- * Events Debug option key.
+ * Events debug flag.
*/
- public static final String OPTION_DEBUG_EVENTS = ECLIPSE_OSGI + "/debug/events"; //$NON-NLS-1$
+ public boolean DEBUG_EVENTS = false; // "debug.events"
/**
- * Services Debug option key.
+ * Services debug flag.
*/
- public static final String OPTION_DEBUG_SERVICES = ECLIPSE_OSGI + "/debug/services"; //$NON-NLS-1$
+ public boolean DEBUG_SERVICES = false; // "debug.services"
+
/**
- * Services Debug option key.
+ * Hooks debug flag.
*/
- public static final String OPTION_DEBUG_HOOKS = ECLIPSE_OSGI + "/debug/hooks"; //$NON-NLS-1$
+ public boolean DEBUG_HOOKS = false; // "debug.hooks"
/**
- * Packages Debug option key.
+ * Packages debug flag.
*/
- public static final String OPTION_DEBUG_PACKAGES = ECLIPSE_OSGI + "/debug/packages"; //$NON-NLS-1$
+ // TODO remove this or use it somewhere
+ public boolean DEBUG_PACKAGES = false; // "debug.packages"
/**
- * Manifest Debug option key.
+ * Manifest debug flag.
*/
- public static final String OPTION_DEBUG_MANIFEST = ECLIPSE_OSGI + "/debug/manifest"; //$NON-NLS-1$
+ public boolean DEBUG_MANIFEST = false; // "debug.manifest"
/**
- * Filter Debug option key.
+ * Filter debug flag.
*/
- public static final String OPTION_DEBUG_FILTER = ECLIPSE_OSGI + "/debug/filter"; //$NON-NLS-1$
+ public boolean DEBUG_FILTER = false; // "debug.filter"
/**
- * Security Debug option key.
+ * Security debug flag.
*/
- public static final String OPTION_DEBUG_SECURITY = ECLIPSE_OSGI + "/debug/security"; //$NON-NLS-1$
+ public boolean DEBUG_SECURITY = false; // "debug.security"
/**
- * Start level Debug option key.
+ * Start level debug flag.
*/
- public static final String OPTION_DEBUG_STARTLEVEL = ECLIPSE_OSGI + "/debug/startlevel"; //$NON-NLS-1$
+ public boolean DEBUG_STARTLEVEL = false; // "debug.startlevel"
/**
- * PackageAdmin Debug option key.
+ * PackageAdmin debug flag.
*/
- public static final String OPTION_DEBUG_PACKAGEADMIN = ECLIPSE_OSGI + "/debug/packageadmin"; //$NON-NLS-1$
+ public boolean DEBUG_PACKAGEADMIN = false; // "debug.packageadmin"
/**
- * PackageAdmin timing Debug option key.
+ * PackageAdmin timing debug flag.
*/
- public static final String OPTION_DEBUG_PACKAGEADMIN_TIMING = ECLIPSE_OSGI + "/debug/packageadmin/timing"; //$NON-NLS-1$
+ // TODO remove this or use it somewhere
+ public boolean DEBUG_PACKAGEADMIN_TIMING = false; //"debug.packageadmin/timing"
/**
- * Monitor activation Debug option key.
+ * Message debug flag.
*/
- public static final String OPTION_MONITOR_ACTIVATION = ECLIPSE_OSGI + "/monitor/activation"; //$NON-NLS-1$
+ public boolean DEBUG_MESSAGE_BUNDLES = false; //"/debug/messageBundles"
/**
- * Message bundles Debug option key.
+ * Monitor activation debug flag.
*/
- public static final String OPTION_DEBUG_MESSAGE_BUNDLES = ECLIPSE_OSGI + "/debug/messageBundles"; //$NON-NLS-1$
+ public boolean MONITOR_ACTIVATION = false; // "monitor/bundles"
+
+ public boolean DEBUG_LOCATION = false; // debug/location
- static {
- FrameworkDebugOptions dbgOptions = FrameworkDebugOptions.getDefault();
- if (dbgOptions != null) {
- DEBUG_ENABLED = dbgOptions.isDebugEnabled();
- DEBUG_GENERAL = dbgOptions.getBooleanOption(OPTION_DEBUG_GENERAL, false);
- DEBUG_BUNDLE_TIME = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_TIME, false) || dbgOptions.getBooleanOption("org.eclipse.core.runtime/timing/startup", false); //$NON-NLS-1$
- DEBUG_LOADER = dbgOptions.getBooleanOption(OPTION_DEBUG_LOADER, false);
- DEBUG_EVENTS = dbgOptions.getBooleanOption(OPTION_DEBUG_EVENTS, false);
- DEBUG_SERVICES = dbgOptions.getBooleanOption(OPTION_DEBUG_SERVICES, false);
- DEBUG_HOOKS = dbgOptions.getBooleanOption(OPTION_DEBUG_HOOKS, false);
- DEBUG_PACKAGES = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGES, false);
- DEBUG_MANIFEST = dbgOptions.getBooleanOption(OPTION_DEBUG_MANIFEST, false);
- DEBUG_FILTER = dbgOptions.getBooleanOption(OPTION_DEBUG_FILTER, false);
- DEBUG_SECURITY = dbgOptions.getBooleanOption(OPTION_DEBUG_SECURITY, false);
- DEBUG_STARTLEVEL = dbgOptions.getBooleanOption(OPTION_DEBUG_STARTLEVEL, false);
- DEBUG_PACKAGEADMIN = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN, false);
- DEBUG_PACKAGEADMIN_TIMING = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN_TIMING, false) || dbgOptions.getBooleanOption("org.eclipse.core.runtime/debug", false); //$NON-NLS-1$
- DEBUG_MESSAGE_BUNDLES = dbgOptions.getBooleanOption(OPTION_DEBUG_MESSAGE_BUNDLES, false);
- MONITOR_ACTIVATION = dbgOptions.getBooleanOption(OPTION_MONITOR_ACTIVATION, false);
+ public Debug(DebugOptions dbgOptions) {
+ if (dbgOptions == null) {
+ return;
}
+ DEBUG_ENABLED = dbgOptions.isDebugEnabled();
+ DEBUG_GENERAL = dbgOptions.getBooleanOption(OPTION_DEBUG_GENERAL, false);
+ STATIC_DEBUG_GENERAL = DEBUG_GENERAL;
+ DEBUG_BUNDLE_TIME = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_TIME, false) || dbgOptions.getBooleanOption("org.eclipse.core.runtime/timing/startup", false); //$NON-NLS-1$
+ DEBUG_LOADER = dbgOptions.getBooleanOption(OPTION_DEBUG_LOADER, false);
+ DEBUG_EVENTS = dbgOptions.getBooleanOption(OPTION_DEBUG_EVENTS, false);
+ DEBUG_SERVICES = dbgOptions.getBooleanOption(OPTION_DEBUG_SERVICES, false);
+ DEBUG_HOOKS = dbgOptions.getBooleanOption(OPTION_DEBUG_HOOKS, false);
+ DEBUG_PACKAGES = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGES, false);
+ DEBUG_MANIFEST = dbgOptions.getBooleanOption(OPTION_DEBUG_MANIFEST, false);
+ STATIC_DEBUG_MANIFEST = DEBUG_MANIFEST;
+ DEBUG_FILTER = dbgOptions.getBooleanOption(OPTION_DEBUG_FILTER, false);
+ DEBUG_SECURITY = dbgOptions.getBooleanOption(OPTION_DEBUG_SECURITY, false);
+ DEBUG_STARTLEVEL = dbgOptions.getBooleanOption(OPTION_DEBUG_STARTLEVEL, false);
+ DEBUG_PACKAGEADMIN = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN, false);
+ DEBUG_PACKAGEADMIN_TIMING = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN_TIMING, false) || dbgOptions.getBooleanOption("org.eclipse.core.runtime/debug", false); //$NON-NLS-1$
+ DEBUG_MESSAGE_BUNDLES = dbgOptions.getBooleanOption(OPTION_DEBUG_MESSAGE_BUNDLES, false);
+ STATIC_DEBUG_MESSAGE_BUNDLES = DEBUG_MESSAGE_BUNDLES;
+ MONITOR_ACTIVATION = dbgOptions.getBooleanOption(OPTION_MONITOR_ACTIVATION, false);
+ DEBUG_LOCATION = dbgOptions.getBooleanOption(OPTION_DEBUG_LOCATION, false);
}
/**
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/EclipseDebugTrace.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/EclipseDebugTrace.java
index de13dcd70..09cc632d4 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/EclipseDebugTrace.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/EclipseDebugTrace.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.debug;
+package org.eclipse.osgi.internal.debug;
import java.io.*;
import java.security.AccessController;
@@ -369,7 +369,7 @@ class EclipseDebugTrace implements DebugTrace {
*/
private void readLogProperties() {
- String newMaxTraceFileSize = secureAction.getProperty(PROP_TRACE_SIZE_MAX);
+ String newMaxTraceFileSize = debugOptions.getConfiguration().getConfiguration(PROP_TRACE_SIZE_MAX);
if (newMaxTraceFileSize != null) {
maxTraceFileSize = Integer.parseInt(newMaxTraceFileSize);
if (maxTraceFileSize != 0 && maxTraceFileSize < DEFAULT_TRACE_FILE_MIN_SIZE) {
@@ -379,7 +379,7 @@ class EclipseDebugTrace implements DebugTrace {
}
}
- String newMaxLogFiles = secureAction.getProperty(PROP_TRACE_FILE_MAX);
+ String newMaxLogFiles = debugOptions.getConfiguration().getConfiguration(PROP_TRACE_FILE_MAX);
if (newMaxLogFiles != null) {
maxTraceFiles = Integer.parseInt(newMaxLogFiles);
if (maxTraceFiles < 1) {
@@ -523,7 +523,7 @@ class EclipseDebugTrace implements DebugTrace {
writeComment(traceWriter, EclipseDebugTrace.TRACE_FILE_VERSION_COMMENT + EclipseDebugTrace.TRACE_FILE_VERSION);
writeComment(traceWriter, EclipseDebugTrace.TRACE_FILE_VERBOSE_COMMENT + debugOptions.isVerbose());
writeComment(traceWriter, "The following option strings are specified for this debug session:"); //$NON-NLS-1$
- final String[] allOptions = FrameworkDebugOptions.getDefault().getAllOptions();
+ final String[] allOptions = debugOptions.getAllOptions();
for (int i = 0; i < allOptions.length; i++) {
writeComment(traceWriter, "\t" + allOptions[i]); //$NON-NLS-1$
}
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/FrameworkDebugOptions.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java
index 7c245f649..71fe5a28a 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/FrameworkDebugOptions.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java
@@ -8,13 +8,13 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.debug;
+package org.eclipse.osgi.internal.debug;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.service.debug.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
@@ -32,35 +32,33 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
private static final String OSGI_DEBUG = "osgi.debug"; //$NON-NLS-1$
private static final String OSGI_DEBUG_VERBOSE = "osgi.debug.verbose"; //$NON-NLS-1$
public static final String PROP_TRACEFILE = "osgi.tracefile"; //$NON-NLS-1$
+ /** The default name of the .options file if loading when the -debug command-line argument is used */
+ private static final String OPTIONS = ".options"; //$NON-NLS-1$
+
/** monitor used to lock the options maps */
private final Object lock = new Object();
/** A current map of all the options with values set */
private Properties options = null;
/** A map of all the disabled options with values set at the time debug was disabled */
private Properties disabledOptions = null;
- /** The singleton object of this class */
- private static FrameworkDebugOptions singleton = null;
- /** The default name of the .options file if loading when the -debug command-line argument is used */
- private static final String OPTIONS = ".options"; //$NON-NLS-1$
/** A cache of all of the bundles <code>DebugTrace</code> in the format <key,value> --> <bundle name, DebugTrace> */
- protected final static Map<String, DebugTrace> debugTraceCache = new HashMap<String, DebugTrace>();
+ protected final Map<String, DebugTrace> debugTraceCache = new HashMap<String, DebugTrace>();
/** The File object to store messages. This value may be null. */
protected File outFile = null;
/** Is verbose debugging enabled? Changing this value causes a new tracing session to start. */
protected boolean verboseDebug = true;
+ private final EquinoxConfiguration environmentInfo;
private volatile BundleContext context;
private volatile ServiceTracker<DebugOptionsListener, DebugOptionsListener> listenerTracker;
- /**
- * Internal constructor to create a <code>FrameworkDebugOptions</code> singleton object.
- */
- private FrameworkDebugOptions() {
+ public FrameworkDebugOptions(EquinoxConfiguration environmentInfo) {
+ this.environmentInfo = environmentInfo;
// check if verbose debugging was set during initialization. This needs to be set even if debugging is disabled
- this.verboseDebug = Boolean.valueOf(FrameworkProperties.getProperty(OSGI_DEBUG_VERBOSE, Boolean.TRUE.toString())).booleanValue();
+ this.verboseDebug = Boolean.valueOf(environmentInfo.getConfiguration(OSGI_DEBUG_VERBOSE, Boolean.TRUE.toString())).booleanValue();
// if no debug option was specified, don't even bother to try.
// Must ensure that the options slot is null as this is the signal to the
// platform that debugging is not enabled.
- String debugOptionsFilename = FrameworkProperties.getProperty(OSGI_DEBUG);
+ String debugOptionsFilename = environmentInfo.getConfiguration(OSGI_DEBUG);
if (debugOptionsFilename == null)
return;
options = new Properties();
@@ -69,7 +67,7 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
// default options location is user.dir (install location may be r/o so
// is not a good candidate for a trace options that need to be updatable by
// by the user)
- String userDir = FrameworkProperties.getProperty("user.dir").replace(File.separatorChar, '/'); //$NON-NLS-1$
+ String userDir = System.getProperty("user.dir").replace(File.separatorChar, '/'); //$NON-NLS-1$
if (!userDir.endsWith("/")) //$NON-NLS-1$
userDir += "/"; //$NON-NLS-1$
debugOptionsFilename = new File(userDir, OPTIONS).toString();
@@ -112,18 +110,6 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
this.context = null;
}
- /**
- * Returns the singleton instance of <code>FrameworkDebugOptions</code>.
- * @return the instance of <code>FrameworkDebugOptions</code>
- */
- public static FrameworkDebugOptions getDefault() {
-
- if (FrameworkDebugOptions.singleton == null) {
- FrameworkDebugOptions.singleton = new FrameworkDebugOptions();
- }
- return FrameworkDebugOptions.singleton;
- }
-
@SuppressWarnings("deprecation")
private static URL buildURL(String spec, boolean trailingSlash) {
if (spec == null)
@@ -363,7 +349,7 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
EclipseDebugTrace.newSession = true;
// enable platform debugging - there is no .options file
- FrameworkProperties.setProperty(OSGI_DEBUG, ""); //$NON-NLS-1$
+ environmentInfo.setConfiguration(OSGI_DEBUG, ""); //$NON-NLS-1$
if (disabledOptions != null) {
options = disabledOptions;
disabledOptions = null;
@@ -376,7 +362,7 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
if (options == null)
return;
// disable platform debugging.
- FrameworkProperties.clearProperty(OSGI_DEBUG);
+ environmentInfo.clearConfiguration(OSGI_DEBUG);
if (options.size() > 0) {
// Save the current options off in case debug is re-enabled
disabledOptions = options;
@@ -408,11 +394,11 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
public final DebugTrace newDebugTrace(String bundleSymbolicName, Class<?> traceEntryClass) {
DebugTrace debugTrace = null;
- synchronized (FrameworkDebugOptions.debugTraceCache) {
- debugTrace = FrameworkDebugOptions.debugTraceCache.get(bundleSymbolicName);
+ synchronized (debugTraceCache) {
+ debugTrace = debugTraceCache.get(bundleSymbolicName);
if (debugTrace == null) {
- debugTrace = new EclipseDebugTrace(bundleSymbolicName, FrameworkDebugOptions.singleton, traceEntryClass);
- FrameworkDebugOptions.debugTraceCache.put(bundleSymbolicName, debugTrace);
+ debugTrace = new EclipseDebugTrace(bundleSymbolicName, this, traceEntryClass);
+ debugTraceCache.put(bundleSymbolicName, debugTrace);
}
}
return debugTrace;
@@ -434,7 +420,7 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
public synchronized void setFile(final File traceFile) {
this.outFile = traceFile;
- FrameworkProperties.setProperty(PROP_TRACEFILE, this.outFile.getAbsolutePath());
+ environmentInfo.setConfiguration(PROP_TRACEFILE, this.outFile.getAbsolutePath());
// the file changed so start a new session
EclipseDebugTrace.newSession = true;
}
@@ -448,6 +434,10 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom
return this.verboseDebug;
}
+ EquinoxConfiguration getConfiguration() {
+ return this.environmentInfo;
+ }
+
/*
* (non-Javadoc)
* @see org.eclipse.osgi.service.debug.DebugOptions#setVerbose(boolean)
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/FrameworkDebugTraceEntry.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/FrameworkDebugTraceEntry.java
index 0fca678b9..98678539c 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/debug/FrameworkDebugTraceEntry.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/debug/FrameworkDebugTraceEntry.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.debug;
+package org.eclipse.osgi.internal.debug;
/**
* A framework trace entry is a bean containing all of the attributes for a single trace message.
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/BasicLocation.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/BasicLocation.java
index aa5d1f44b..f8c2e35e8 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/BasicLocation.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/BasicLocation.java
@@ -8,12 +8,12 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.location;
import java.io.File;
import java.io.IOException;
import java.net.URL;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
@@ -21,6 +21,9 @@ import org.eclipse.osgi.util.NLS;
* Internal class.
*/
public class BasicLocation implements Location {
+ public static final String PROP_OSGI_LOCKING = "osgi.locking"; //$NON-NLS-1$
+ private static String DEFAULT_LOCK_FILENAME = ".metadata/.lock"; //$NON-NLS-1$
+
static class MockLocker implements Locker {
/**
* @throws IOException
@@ -42,32 +45,20 @@ public class BasicLocation implements Location {
}
final private boolean isReadOnly;
- private URL location = null;
- private Location parent;
final private URL defaultValue;
final private String property;
final private String dataAreaPrefix;
+ final private EquinoxConfiguration environmentInfo;
+ final private boolean debug;
+
+ private URL location = null;
+ private Location parent;
// locking related fields
private File lockFile;
private Locker locker;
- public static final String PROP_OSGI_LOCKING = "osgi.locking"; //$NON-NLS-1$
- private static String DEFAULT_LOCK_FILENAME = ".metadata/.lock"; //$NON-NLS-1$
- public static boolean DEBUG;
-
- private static boolean isRunningWithNio() {
- try {
- Class.forName("java.nio.channels.FileLock"); //$NON-NLS-1$
- } catch (ClassNotFoundException e) {
- return false;
- }
- return true;
- }
-
- public static Locker createLocker(File lock, String lockMode) {
- if (lockMode == null)
- lockMode = FrameworkProperties.getProperty(PROP_OSGI_LOCKING);
+ public static Locker createLocker(File lock, String lockMode, boolean debug) {
if ("none".equals(lockMode)) //$NON-NLS-1$
return new MockLocker();
@@ -75,25 +66,20 @@ public class BasicLocation implements Location {
return new Locker_JavaIo(lock);
if ("java.nio".equals(lockMode)) { //$NON-NLS-1$
- if (isRunningWithNio())
- return new Locker_JavaNio(lock);
- // TODO should we return null here. NIO was requested but we could not do it...
- return new Locker_JavaIo(lock);
+ return new Locker_JavaNio(lock, debug);
}
// Backup case if an invalid value has been specified
- if (isRunningWithNio())
- return new Locker_JavaNio(lock);
- return new Locker_JavaIo(lock);
-
+ return new Locker_JavaNio(lock, debug);
}
- public BasicLocation(String property, URL defaultValue, boolean isReadOnly, String dataAreaPrefix) {
- super();
+ public BasicLocation(String property, URL defaultValue, boolean isReadOnly, String dataAreaPrefix, EquinoxConfiguration environmentInfo) {
this.property = property;
this.defaultValue = defaultValue;
this.isReadOnly = isReadOnly;
this.dataAreaPrefix = dataAreaPrefix == null ? "" : dataAreaPrefix; //$NON-NLS-1$
+ this.environmentInfo = environmentInfo;
+ this.debug = environmentInfo.getDebug().DEBUG_LOCATION;
}
public boolean allowsDefault() {
@@ -167,7 +153,7 @@ public class BasicLocation implements Location {
lockFile = file;
location = value;
if (property != null)
- FrameworkProperties.setProperty(property, location.toExternalForm());
+ environmentInfo.setConfiguration(property, location.toExternalForm());
return lock;
}
@@ -236,8 +222,8 @@ public class BasicLocation implements Location {
private void setLocker(File lock) {
if (locker != null)
return;
- String lockMode = FrameworkProperties.getProperty(PROP_OSGI_LOCKING);
- locker = createLocker(lock, lockMode);
+ String lockMode = environmentInfo.getConfiguration(PROP_OSGI_LOCKING);
+ locker = createLocker(lock, lockMode, debug);
}
public synchronized void release() {
@@ -246,7 +232,7 @@ public class BasicLocation implements Location {
}
public Location createLocation(Location parentLocation, URL defaultLocation, boolean readonly) {
- BasicLocation result = new BasicLocation(null, defaultLocation, readonly, dataAreaPrefix);
+ BasicLocation result = new BasicLocation(null, defaultLocation, readonly, dataAreaPrefix, environmentInfo);
result.setParent(parentLocation);
return result;
}
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorMessages.properties b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/EclipseAdaptorMessages.properties
index 4e67bcb00..4e67bcb00 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorMessages.properties
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/EclipseAdaptorMessages.properties
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorMsg.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/EclipseAdaptorMsg.java
index 4b965a35a..4d84d8cbd 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/EclipseAdaptorMsg.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/EclipseAdaptorMsg.java
@@ -8,12 +8,12 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.location;
import org.eclipse.osgi.util.NLS;
public class EclipseAdaptorMsg extends NLS {
- private static final String BUNDLE_NAME = "org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorMessages"; //$NON-NLS-1$
+ private static final String BUNDLE_NAME = "org.eclipse.osgi.internal.location.EclipseAdaptorMessages"; //$NON-NLS-1$
public static String ECLIPSE_MISSING_IMPORTED_PACKAGE;
public static String ECLIPSE_MISSING_OPTIONAL_IMPORTED_PACKAGE;
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/LocationHelper.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java
index 0180bf04c..a8ee6af5c 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/LocationHelper.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.location;
import java.io.File;
import java.net.MalformedURLException;
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker.java
index 0031f5ed6..91c224e7d 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.location;
import java.io.IOException;
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaIo.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker_JavaIo.java
index a0e16699c..ebd96c94f 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaIo.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker_JavaIo.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.location;
import java.io.*;
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaNio.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker_JavaNio.java
index 3009b12a9..d6319fe5f 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/core/runtime/internal/adaptor/Locker_JavaNio.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/Locker_JavaNio.java
@@ -10,7 +10,7 @@
* Danail Nachev (Prosyst) - bug 185654
* Andrei Loskutov - bug 44735
*******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
+package org.eclipse.osgi.internal.location;
import java.io.*;
import java.nio.channels.FileLock;
@@ -22,11 +22,13 @@ import org.eclipse.osgi.util.NLS;
*/
public class Locker_JavaNio implements Locker {
private final File lockFile;
+ private final boolean debug;
private FileLock fileLock;
private RandomAccessFile raFile;
- public Locker_JavaNio(File lockFile) {
+ public Locker_JavaNio(File lockFile, boolean debug) {
this.lockFile = lockFile;
+ this.debug = debug;
}
public synchronized boolean lock() throws IOException {
@@ -39,7 +41,7 @@ public class Locker_JavaNio implements Locker {
fileLock = raFile.getChannel().tryLock(0, 1, false);
} catch (IOException ioe) {
// print exception if debugging
- if (BasicLocation.DEBUG)
+ if (debug)
System.out.println(NLS.bind(EclipseAdaptorMsg.location_cannotLock, lockFile));
// produce a more specific message for clients
String specificMessage = NLS.bind(EclipseAdaptorMsg.location_cannotLockNIO, new Object[] {lockFile, ioe.getMessage(), "\"-D" + BasicLocation.PROP_OSGI_LOCKING + "=none\""}); //$NON-NLS-1$ //$NON-NLS-2$
@@ -89,7 +91,7 @@ public class Locker_JavaNio implements Locker {
try {
tempLock = temp.getChannel().tryLock(0, 1, false);
} catch (IOException ioe) {
- if (BasicLocation.DEBUG)
+ if (debug)
System.out.println(NLS.bind(EclipseAdaptorMsg.location_cannotLock, lockFile));
// produce a more specific message for clients
String specificMessage = NLS.bind(EclipseAdaptorMsg.location_cannotLockNIO, new Object[] {lockFile, ioe.getMessage(), "\"-D" + BasicLocation.PROP_OSGI_LOCKING + "=none\""}); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/storagemanager/StorageManager.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/storagemanager/StorageManager.java
index 396e0e8fc..f975dfe95 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/storagemanager/StorageManager.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/storagemanager/StorageManager.java
@@ -13,9 +13,9 @@ package org.eclipse.osgi.storagemanager;
import java.io.*;
import java.security.AccessController;
import java.util.*;
-import org.eclipse.core.runtime.internal.adaptor.*;
import org.eclipse.osgi.framework.internal.reliablefile.*;
import org.eclipse.osgi.framework.util.SecureAction;
+import org.eclipse.osgi.internal.location.*;
/**
* Storage managers provide a facility for tracking the state of a group of files having
@@ -187,7 +187,7 @@ public final class StorageManager {
return;
this.instanceFile = File.createTempFile(".tmp", ".instance", managerRoot); //$NON-NLS-1$//$NON-NLS-2$
this.instanceFile.deleteOnExit();
- instanceLocker = BasicLocation.createLocker(instanceFile, lockMode);
+ instanceLocker = BasicLocation.createLocker(instanceFile, lockMode, false);
instanceLocker.lock();
}
@@ -382,7 +382,7 @@ public final class StorageManager {
if (readOnly)
return false;
if (locker == null) {
- locker = BasicLocation.createLocker(lockFile, lockMode);
+ locker = BasicLocation.createLocker(lockFile, lockMode, false);
if (locker == null)
throw new IOException(EclipseAdaptorMsg.fileManager_cannotLock);
}
@@ -608,7 +608,7 @@ public final class StorageManager {
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].endsWith(".instance") && (instanceFile == null || !files[i].equalsIgnoreCase(instanceFile.getName()))) { //$NON-NLS-1$
- Locker tmpLocker = BasicLocation.createLocker(new File(managerRoot, files[i]), lockMode);
+ Locker tmpLocker = BasicLocation.createLocker(new File(managerRoot, files[i]), lockMode, false);
if (tmpLocker.lock()) {
//If I can lock it is a file that has been left behind by a crash
tmpLocker.release();
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java
index f19cbd909..f8d3ab3e5 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java
@@ -13,9 +13,9 @@ package org.eclipse.osgi.util;
import java.io.*;
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.framework.internal.core.Tokenizer;
+import org.eclipse.osgi.internal.debug.Debug;
import org.osgi.framework.BundleException;
/**
@@ -355,7 +355,7 @@ public class ManifestElement {
StringBuffer headerValue = new StringBuffer(next);
headerValues.add(next);
- if (Debug.DEBUG_MANIFEST)
+ if (Debug.STATIC_DEBUG_MANIFEST)
Debug.print("parseHeader: " + next); //$NON-NLS-1$
boolean directive = false;
char c = tokenizer.getChar();
@@ -379,7 +379,7 @@ public class ManifestElement {
if (c == ';' || c == ',' || c == '\0') /* more */{
headerValues.add(next);
headerValue.append(";").append(next); //$NON-NLS-1$
- if (Debug.DEBUG_MANIFEST)
+ if (Debug.STATIC_DEBUG_MANIFEST)
Debug.print(";" + next); //$NON-NLS-1$
}
}
@@ -413,7 +413,7 @@ public class ManifestElement {
if (val == null)
throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
- if (Debug.DEBUG_MANIFEST)
+ if (Debug.STATIC_DEBUG_MANIFEST)
Debug.print(";" + next + "=" + val); //$NON-NLS-1$ //$NON-NLS-2$
try {
if (directive)
@@ -433,7 +433,7 @@ public class ManifestElement {
}
}
headerElements.add(manifestElement);
- if (Debug.DEBUG_MANIFEST)
+ if (Debug.STATIC_DEBUG_MANIFEST)
Debug.println(""); //$NON-NLS-1$
if (c == ',') /* another manifest element */
continue parseloop;
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java
index c7776d2ff..407fba9d5 100644
--- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java
@@ -17,10 +17,9 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.debug.Debug;
/**
* Common superclass for all message bundle classes. Provides convenience
@@ -57,7 +56,7 @@ public abstract class NLS {
private static String[] nlSuffixes;
private static final String PROP_WARNINGS = "osgi.nls.warnings"; //$NON-NLS-1$
private static final String IGNORE = "ignore"; //$NON-NLS-1$
- private static final boolean ignoreWarnings = IGNORE.equals(FrameworkProperties.getProperty(PROP_WARNINGS));
+ private static final boolean ignoreWarnings = IGNORE.equals(System.getProperty(PROP_WARNINGS));
/*
* NOTE do not change the name of this field; it is set by the Framework using reflection
@@ -282,7 +281,7 @@ public abstract class NLS {
// log it and continue. This means that the field will (most likely) be un-initialized and
// will fail later in the code and if so then we will see both the NPE and this error.
String value = "NLS missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$
- if (Debug.DEBUG_MESSAGE_BUNDLES)
+ if (Debug.STATIC_DEBUG_MESSAGE_BUNDLES)
System.out.println(value);
log(SEVERITY_WARNING, value, null);
if (!isAccessible)
@@ -334,7 +333,7 @@ public abstract class NLS {
}
}
computeMissingMessages(bundleName, clazz, fields, fieldArray, isAccessible);
- if (Debug.DEBUG_MESSAGE_BUNDLES)
+ if (Debug.STATIC_DEBUG_MESSAGE_BUNDLES)
System.out.println("Time to load message bundle: " + bundleName + " was " + (System.currentTimeMillis() - start) + "ms."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -407,7 +406,7 @@ public abstract class NLS {
return null;
if (fieldObject == null) {
final String msg = "NLS unused message: " + key + " in: " + bundleName;//$NON-NLS-1$ //$NON-NLS-2$
- if (Debug.DEBUG_MESSAGE_BUNDLES)
+ if (Debug.STATIC_DEBUG_MESSAGE_BUNDLES)
System.out.println(msg);
log(SEVERITY_WARNING, msg, null);
return null;

Back to the top