Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2013-06-21 17:22:50 +0000
committerThomas Watson2013-07-18 20:21:26 +0000
commit2d9f0da79b5fda166e19b0d4af79f638da3ff332 (patch)
tree76edc46ba56364d5344212caa016e1e6f1c2678d /bundles
parent74dbf9088435ef5cfed74f1265f7509f7472c5cd (diff)
downloadrt.equinox.framework-2d9f0da79b5fda166e19b0d4af79f638da3ff332.tar.gz
rt.equinox.framework-2d9f0da79b5fda166e19b0d4af79f638da3ff332.tar.xz
rt.equinox.framework-2d9f0da79b5fda166e19b0d4af79f638da3ff332.zip
Bug 411404 - Build from source for osgi.services and osgi.util bundles
Diffstat (limited to 'bundles')
-rw-r--r--bundles/org.eclipse.osgi.services/.classpath8
-rw-r--r--bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs13
-rw-r--r--bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF20
-rw-r--r--bundles/org.eclipse.osgi.services/build.properties13
-rw-r--r--bundles/org.eclipse.osgi.services/customBuildCallbacks.xml162
-rw-r--r--bundles/org.eclipse.osgi.services/lib/osgi.annotation.jarbin0 -> 13179 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/Configuration.classbin674 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationAdmin.classbin743 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationEvent.classbin1651 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationException.classbin1469 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationListener.classbin218 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermission.classbin5843 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermissionCollection.classbin5594 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPlugin.classbin492 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedService.classbin315 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedServiceFactory.classbin448 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentConstants.classbin861 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentContext.classbin763 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentException.classbin1007 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentFactory.classbin235 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentInstance.classbin211 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Activate.classbin406 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Component.classbin1028 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ConfigurationPolicy.classbin1495 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Deactivate.classbin410 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Modified.classbin406 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Reference.classbin1182 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferenceCardinality.classbin1568 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicy.classbin1396 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicyOption.classbin1442 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/device/Constants.classbin303 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/device/Device.classbin201 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/device/Driver.classbin311 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverLocator.classbin312 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverSelector.classbin280 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/device/Match.classbin207 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/Event$FilterProperties.classbin2779 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/Event.classbin3719 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/EventAdmin.classbin200 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/EventConstants.classbin1211 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/EventHandler.classbin186 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/EventProperties.classbin4275 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermission.classbin4627 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermissionCollection.classbin5545 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpContext.classbin689 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpService.classbin597 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/http/NamespaceException.classbin958 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectionFactory.classbin349 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectorService.classbin857 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/log/LogEntry.classbin384 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/log/LogListener.classbin209 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/log/LogReaderService.classbin272 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/log/LogService.classbin529 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/metatype/AttributeDefinition.classbin852 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeInformation.classbin314 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeProvider.classbin460 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeService.classbin355 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/metatype/ObjectClassDefinition.classbin523 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/provisioning/ProvisioningService.classbin1292 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPAction.classbin490 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPDevice.classbin1605 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPEventListener.classbin311 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPException.classbin1172 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPIcon.classbin345 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPLocalStateVariable.classbin243 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPService.classbin632 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPStateVariable.classbin1456 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Authorization.classbin260 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Group.classbin356 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Role.classbin405 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/User.classbin273 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdmin.classbin668 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminEvent.classbin1048 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminListener.classbin213 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermission.classbin5628 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermissionCollection.classbin2851 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/BasicEnvelope.classbin882 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Consumer.classbin268 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Envelope.classbin236 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Producer.classbin266 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Wire.classbin445 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdmin.classbin531 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminEvent.classbin1460 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminListener.classbin216 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireConstants.classbin1522 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermission.classbin4504 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermissionCollection.classbin2818 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/pom.xml23
-rw-r--r--bundles/org.eclipse.osgi.services/src.zipbin161040 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/Configuration.java275
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationAdmin.java290
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationEvent.java180
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationException.java102
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationListener.java51
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPermission.java622
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPlugin.java127
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedService.java155
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedServiceFactory.java180
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/SynchronousConfigurationListener.java48
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/package-info.java42
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java126
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java187
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java79
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java49
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentInstance.java49
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java44
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java200
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ConfigurationPolicy.java61
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java44
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java44
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java152
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceCardinality.java63
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicy.java57
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicyOption.java56
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java31
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java42
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Constants.java75
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Device.java65
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Driver.java108
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverLocator.java65
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverSelector.java54
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Match.java46
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/device/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/Event.java294
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventAdmin.java56
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventConstants.java243
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventHandler.java72
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventProperties.java261
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/TopicPermission.java548
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/package-info.java42
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/event/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpContext.java162
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpService.java172
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/http/NamespaceException.java87
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/http/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/http/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogEntry.java110
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogListener.java51
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogReaderService.java100
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java156
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/log/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/AttributeDefinition.java304
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeInformation.java53
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeProvider.java81
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeService.java54
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/ObjectClassDefinition.java119
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/ProvisioningService.java213
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPAction.java142
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPDevice.java291
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPEventListener.java85
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPException.java115
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPIcon.java122
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPLocalStateVariable.java48
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPService.java194
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPStateVariable.java378
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Authorization.java103
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Group.java157
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Role.java117
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/User.java94
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdmin.java155
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminEvent.java111
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminListener.java44
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminPermission.java606
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/BasicEnvelope.java65
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Consumer.java102
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Envelope.java79
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Producer.java124
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Wire.java271
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdmin.java164
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminEvent.java267
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminListener.java72
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireConstants.java224
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WirePermission.java459
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.util/.classpath8
-rw-r--r--bundles/org.eclipse.osgi.util/.settings/org.eclipse.jdt.core.prefs13
-rw-r--r--bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF8
-rw-r--r--bundles/org.eclipse.osgi.util/build.properties11
-rw-r--r--bundles/org.eclipse.osgi.util/customBuildCallbacks.xml162
-rw-r--r--bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Measurement.classbin4700 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/org/osgi/util/measurement/State.classbin1607 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Unit.classbin6182 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/org/osgi/util/position/Position.classbin2798 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/org/osgi/util/xml/XMLParserActivator.classbin7598 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/pom.xml2
-rw-r--r--bundles/org.eclipse.osgi.util/src.zipbin20755 -> 0 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Measurement.java476
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/State.java145
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Unit.java477
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/package-info.java34
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/position/Position.java232
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/position/package-info.java34
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/position/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/XMLParserActivator.java479
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/package-info.java34
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/packageinfo1
211 files changed, 13823 insertions, 402 deletions
diff --git a/bundles/org.eclipse.osgi.services/.classpath b/bundles/org.eclipse.osgi.services/.classpath
index 6b1debc73..64c5e31b7 100644
--- a/bundles/org.eclipse.osgi.services/.classpath
+++ b/bundles/org.eclipse.osgi.services/.classpath
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry path="" kind="lib" exported="true" sourcepath="src.zip"/>
- <classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/OSGi%Minimum-1.2" kind="con"/>
- <classpathentry path="org.eclipse.pde.core.requiredPlugins" kind="con"/>
- <classpathentry path="bin" kind="output"/>
+ <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.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs
index 8e730b080..db619c076 100644
--- a/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,3 @@
-#Tue Dec 02 09:03:08 CST 2008
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
@@ -7,24 +6,24 @@ org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
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=disabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=error
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
@@ -71,6 +70,6 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=en
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
index 747dae5f4..fcd6ae66f 100644
--- a/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
@@ -2,19 +2,18 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %osgiServices
Bundle-SymbolicName: org.eclipse.osgi.services
-Bundle-Version: 3.3.100.qualifier
+Bundle-Version: 3.4.0.qualifier
Bundle-Description: %osgiServicesDes
Bundle-Localization: plugin
Bundle-Vendor: %eclipse.org
Bundle-DocUrl: http://www.eclipse.org
Bundle-ContactAddress: www.eclipse.org
-Export-Package: org.osgi.service.cm; version="1.4",
- org.osgi.service.component; version="1.2",
+Export-Package: org.osgi.service.cm; version="1.5",
+ org.osgi.service.component; version="1.2.2",
org.osgi.service.component.annotations; version="1.2",
org.osgi.service.device; version="1.1",
org.osgi.service.event; version="1.3",
org.osgi.service.http; version="1.2.1",
- org.osgi.service.io; version="1.0",
org.osgi.service.log; version="1.3",
org.osgi.service.metatype; version="1.2",
org.osgi.service.provisioning; version="1.2",
@@ -22,12 +21,12 @@ Export-Package: org.osgi.service.cm; version="1.4",
org.osgi.service.useradmin; version="1.1",
org.osgi.service.wireadmin; version="1.0.1"
Import-Package: org.osgi.framework; version=1.6,
- org.osgi.service.cm; version="[1.4, 1.5)",
- org.osgi.service.component; version="[1.2, 1.3)",
+ org.osgi.service.cm; version="[1.5, 1.6)",
+ org.osgi.service.component; version="[1.2.2, 1.3)",
+ org.osgi.service.component.annotations; version="[1.2, 1.3)",
org.osgi.service.device; version="[1.1, 1.2)",
org.osgi.service.event; version="[1.3, 1.4)",
org.osgi.service.http; version="[1.2.1, 1.3)",
- org.osgi.service.io; version="[1.0, 1.1)",
org.osgi.service.log; version="[1.3, 1.4)",
org.osgi.service.metatype; version="[1.2, 1.3)",
org.osgi.service.provisioning; version="[1.2, 1.3)",
@@ -37,8 +36,5 @@ Import-Package: org.osgi.framework; version=1.6,
javax.servlet; resolution:="optional",
javax.servlet.http; resolution:="optional"
DynamicImport-Package: javax.servlet,
- javax.servlet.http,
- javax.microedition.io
-Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2,
- CDC-1.1/Foundation-1.1,
- J2SE-1.4
+ javax.servlet.http
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/bundles/org.eclipse.osgi.services/build.properties b/bundles/org.eclipse.osgi.services/build.properties
index cf8b197e9..88dcd9445 100644
--- a/bundles/org.eclipse.osgi.services/build.properties
+++ b/bundles/org.eclipse.osgi.services/build.properties
@@ -11,13 +11,10 @@
bin.includes = plugin.properties,\
about.html,\
META-INF/,\
- org/,\
about_files/
-src.includes = src.zip,\
- about.html,\
+src.includes = about.html,\
about_files/
-source.. = .
-output.. = .
-customBuildCallbacks=customBuildCallbacks.xml
-javacSource = 1.5
-javacTarget = 1.5
+
+source.. = src/
+output.. = bin/
+jars.extra.classpath = lib/osgi.annotation.jar \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.services/customBuildCallbacks.xml b/bundles/org.eclipse.osgi.services/customBuildCallbacks.xml
deleted file mode 100644
index 91871121b..000000000
--- a/bundles/org.eclipse.osgi.services/customBuildCallbacks.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-<!-- ===================================================================== -->
-<!-- Custom targets called from a project's generated build.xml -->
-<!-- Set customBuildCallbacks=<path/to/this/file> in your build.properties.-->
-<!-- ===================================================================== -->
-<project name="Build specific targets and properties" default="noDefault">
-
- <!-- ===================================================================== -->
- <!-- Default target -->
- <!-- ===================================================================== -->
- <target name="noDefault">
- <echo message="This file must be called with explicit targets" />
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target build.jars -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="pre.build.jars">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target build.jars -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="post.build.jars">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target build.sources -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="pre.build.sources">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target build.sources -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="post.build.sources">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the compilation target <name> -->
- <!-- Substitute "name" with the name of the compilation target, eg @dot -->
- <!-- Available parameters : -->
- <!-- source.foldern : n = 1 ... N, the source folders -->
- <!-- target.folder : where the results of the compilation go -->
- <!-- <name>.classpath : name = name of the compilation target. A -->
- <!-- reference to the classpath structure. -->
- <!-- ===================================================================== -->
- <target name="pre.name">
- </target>
-
- <target name="pre.@dot">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do during the compilation target <name>, after the compile -->
- <!-- but before jaring. Substitute "name" with the name of the compilation-->
- <!-- target, eg @dot -->
- <!-- Available parameters : -->
- <!-- source.foldern : n = 1 ... N, the source folders -->
- <!-- target.folder : where the results of the compilation go -->
- <!-- <name>.classpath : name = name of the compilation target. A -->
- <!-- reference to the classpath structure. -->
- <!-- ===================================================================== -->
- <target name="post.compile.name">
- </target>
-
- <target name="post.compile.@dot">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the compilation target <name> -->
- <!-- Substitute "name" with the name of the compilation target, eg @dot -->
- <!-- Available parameters : -->
- <!-- jar.location - the location of the compilation results -->
- <!-- <name>.classpath : name = name of the compilation target. A -->
- <!-- reference to the classpath structure. -->
- <!-- ===================================================================== -->
- <target name="post.name">
- </target>
-
- <target name="post.@dot">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target gather.bin.parts -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder containing the build results -->
- <!-- target.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.gather.bin.parts">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target gather.bin.parts -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder containing the build results -->
- <!-- target.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="post.gather.bin.parts">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target gather.sources -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.gather.sources">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target gather.sources -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="post.gather.sources">
- <unzip src="${target.folder}/src.zip" dest="${target.folder}" overwrite="false"/>
- <delete file="${destination.temp.folder}/src.zip" />
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target gather.logs -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.gather.logs">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target gather.logs -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="post.gather.logs">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target clean -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.clean">
- <move file="src.zip" tofile="services_src.zip"/>
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target clean -->
- <!-- Available parameters : -->
- <!-- plugin.destination - final destination of the build -->
- <!-- build.result.folder - results of the compilation -->
- <!-- temp.folder - temporary folder -->
- <!-- ===================================================================== -->
- <target name="post.clean">
- <move file="services_src.zip" tofile="src.zip"/>
- </target>
-</project>
diff --git a/bundles/org.eclipse.osgi.services/lib/osgi.annotation.jar b/bundles/org.eclipse.osgi.services/lib/osgi.annotation.jar
new file mode 100644
index 000000000..947f158fb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/lib/osgi.annotation.jar
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/Configuration.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/Configuration.class
deleted file mode 100644
index ceeb65785..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/Configuration.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationAdmin.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationAdmin.class
deleted file mode 100644
index 9fabc2f49..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationAdmin.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationEvent.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationEvent.class
deleted file mode 100644
index e25f669a2..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationEvent.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationException.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationException.class
deleted file mode 100644
index 1d92348c9..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationException.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationListener.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationListener.class
deleted file mode 100644
index 656435048..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationListener.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermission.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermission.class
deleted file mode 100644
index bd359a4d8..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermission.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermissionCollection.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermissionCollection.class
deleted file mode 100644
index 25058cab5..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPermissionCollection.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPlugin.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPlugin.class
deleted file mode 100644
index db03a9a07..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ConfigurationPlugin.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedService.class
deleted file mode 100644
index 1265e1e73..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedServiceFactory.class b/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedServiceFactory.class
deleted file mode 100644
index eccb28301..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/cm/ManagedServiceFactory.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentConstants.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentConstants.class
deleted file mode 100644
index 4a05902dd..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentConstants.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentContext.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentContext.class
deleted file mode 100644
index ae69ba583..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentContext.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentException.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentException.class
deleted file mode 100644
index 5d3cd8557..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentException.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentFactory.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentFactory.class
deleted file mode 100644
index 3b00ffad4..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentFactory.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentInstance.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentInstance.class
deleted file mode 100644
index f7ec3659f..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/ComponentInstance.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Activate.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Activate.class
deleted file mode 100644
index 5791c6b75..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Activate.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Component.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Component.class
deleted file mode 100644
index 04ad0654c..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Component.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ConfigurationPolicy.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ConfigurationPolicy.class
deleted file mode 100644
index 43e7f5b0f..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ConfigurationPolicy.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Deactivate.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Deactivate.class
deleted file mode 100644
index 5b11dd292..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Deactivate.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Modified.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Modified.class
deleted file mode 100644
index f5fc7fb81..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Modified.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Reference.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Reference.class
deleted file mode 100644
index 8cc770674..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/Reference.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferenceCardinality.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferenceCardinality.class
deleted file mode 100644
index 64c12e561..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferenceCardinality.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicy.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicy.class
deleted file mode 100644
index 4c63e7d69..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicy.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicyOption.class b/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicyOption.class
deleted file mode 100644
index 71061d218..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/component/annotations/ReferencePolicyOption.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Constants.class b/bundles/org.eclipse.osgi.services/org/osgi/service/device/Constants.class
deleted file mode 100644
index f782f7945..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Constants.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Device.class b/bundles/org.eclipse.osgi.services/org/osgi/service/device/Device.class
deleted file mode 100644
index 237f58196..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Device.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Driver.class b/bundles/org.eclipse.osgi.services/org/osgi/service/device/Driver.class
deleted file mode 100644
index 7fec66046..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Driver.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverLocator.class b/bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverLocator.class
deleted file mode 100644
index cae1e557f..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverLocator.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverSelector.class b/bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverSelector.class
deleted file mode 100644
index 9e5d67d4c..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/device/DriverSelector.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Match.class b/bundles/org.eclipse.osgi.services/org/osgi/service/device/Match.class
deleted file mode 100644
index a28afde31..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/device/Match.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/Event$FilterProperties.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/Event$FilterProperties.class
deleted file mode 100644
index de3131d47..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/Event$FilterProperties.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/Event.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/Event.class
deleted file mode 100644
index 99374d710..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/Event.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventAdmin.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventAdmin.class
deleted file mode 100644
index bb2044fc0..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventAdmin.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventConstants.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventConstants.class
deleted file mode 100644
index 824facdef..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventConstants.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventHandler.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventHandler.class
deleted file mode 100644
index 2bf6d1e24..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventHandler.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventProperties.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventProperties.class
deleted file mode 100644
index 9f89ef509..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/EventProperties.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermission.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermission.class
deleted file mode 100644
index 1165dde99..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermission.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermissionCollection.class b/bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermissionCollection.class
deleted file mode 100644
index cd19b3325..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/event/TopicPermissionCollection.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpContext.class b/bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpContext.class
deleted file mode 100644
index b7208d697..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpContext.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpService.class
deleted file mode 100644
index f77415f4a..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/http/HttpService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/http/NamespaceException.class b/bundles/org.eclipse.osgi.services/org/osgi/service/http/NamespaceException.class
deleted file mode 100644
index 01aff3c87..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/http/NamespaceException.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectionFactory.class b/bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectionFactory.class
deleted file mode 100644
index ac4f846ab..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectionFactory.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectorService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectorService.class
deleted file mode 100644
index 22a782b0b..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/io/ConnectorService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogEntry.class b/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogEntry.class
deleted file mode 100644
index 0fcaca353..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogEntry.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogListener.class b/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogListener.class
deleted file mode 100644
index 0a6017705..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogListener.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogReaderService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogReaderService.class
deleted file mode 100644
index 9cdf6c839..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogReaderService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogService.class
deleted file mode 100644
index 0f1ed6b85..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/log/LogService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/AttributeDefinition.class b/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/AttributeDefinition.class
deleted file mode 100644
index 199e92065..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/AttributeDefinition.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeInformation.class b/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeInformation.class
deleted file mode 100644
index a3821db48..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeInformation.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeProvider.class b/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeProvider.class
deleted file mode 100644
index d20da8931..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeProvider.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeService.class
deleted file mode 100644
index f92f16556..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/MetaTypeService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/ObjectClassDefinition.class b/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/ObjectClassDefinition.class
deleted file mode 100644
index 5621a0ac8..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/metatype/ObjectClassDefinition.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/provisioning/ProvisioningService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/provisioning/ProvisioningService.class
deleted file mode 100644
index a132ad929..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/provisioning/ProvisioningService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPAction.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPAction.class
deleted file mode 100644
index b7279940d..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPAction.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPDevice.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPDevice.class
deleted file mode 100644
index 8ecffa2d8..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPDevice.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPEventListener.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPEventListener.class
deleted file mode 100644
index c13a53898..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPEventListener.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPException.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPException.class
deleted file mode 100644
index 42e5976a8..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPException.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPIcon.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPIcon.class
deleted file mode 100644
index b45f77320..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPIcon.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPLocalStateVariable.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPLocalStateVariable.class
deleted file mode 100644
index 57c2e5e61..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPLocalStateVariable.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPService.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPService.class
deleted file mode 100644
index d76ec452d..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPService.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPStateVariable.class b/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPStateVariable.class
deleted file mode 100644
index bc6e34a99..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/upnp/UPnPStateVariable.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Authorization.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Authorization.class
deleted file mode 100644
index 7e6df682d..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Authorization.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Group.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Group.class
deleted file mode 100644
index 17964f8c3..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Group.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Role.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Role.class
deleted file mode 100644
index e632ee16e..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/Role.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/User.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/User.class
deleted file mode 100644
index 775838b69..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/User.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdmin.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdmin.class
deleted file mode 100644
index a2398ea96..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdmin.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminEvent.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminEvent.class
deleted file mode 100644
index 5c38bc47b..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminEvent.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminListener.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminListener.class
deleted file mode 100644
index b7204c96e..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminListener.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermission.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermission.class
deleted file mode 100644
index d7a09edda..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermission.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermissionCollection.class b/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermissionCollection.class
deleted file mode 100644
index e9ecf3515..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/useradmin/UserAdminPermissionCollection.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/BasicEnvelope.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/BasicEnvelope.class
deleted file mode 100644
index 508637d6d..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/BasicEnvelope.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Consumer.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Consumer.class
deleted file mode 100644
index 421afec68..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Consumer.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Envelope.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Envelope.class
deleted file mode 100644
index 82c60f556..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Envelope.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Producer.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Producer.class
deleted file mode 100644
index 5f1eeebff..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Producer.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Wire.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Wire.class
deleted file mode 100644
index c09aaad64..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/Wire.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdmin.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdmin.class
deleted file mode 100644
index 802f62676..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdmin.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminEvent.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminEvent.class
deleted file mode 100644
index 57749c724..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminEvent.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminListener.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminListener.class
deleted file mode 100644
index bed095153..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireAdminListener.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireConstants.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireConstants.class
deleted file mode 100644
index 9564c6433..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WireConstants.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermission.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermission.class
deleted file mode 100644
index f39b8c8a8..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermission.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermissionCollection.class b/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermissionCollection.class
deleted file mode 100644
index 16571c3f1..000000000
--- a/bundles/org.eclipse.osgi.services/org/osgi/service/wireadmin/WirePermissionCollection.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/pom.xml b/bundles/org.eclipse.osgi.services/pom.xml
index 6686d5e04..8be589aeb 100644
--- a/bundles/org.eclipse.osgi.services/pom.xml
+++ b/bundles/org.eclipse.osgi.services/pom.xml
@@ -19,27 +19,6 @@
</parent>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
- <version>3.3.100-SNAPSHOT</version>
+ <version>3.4.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.eclipse.tycho</groupId>
- <artifactId>target-platform-configuration</artifactId>
- <!--
- When building monolith, optional import-package javax.microedition.io causes circular dependency
- between this org.eclipse.osgi.services bundle and org.eclipse.equinox.io.
- Since this bundle does not need to compile anything, we just disable optional dependencies during
- the build.
- -->
- <configuration>
- <dependency-resolution>
- <optionalDependencies>ignore</optionalDependencies>
- </dependency-resolution>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
</project>
diff --git a/bundles/org.eclipse.osgi.services/src.zip b/bundles/org.eclipse.osgi.services/src.zip
deleted file mode 100644
index 9117081e6..000000000
--- a/bundles/org.eclipse.osgi.services/src.zip
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/Configuration.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/Configuration.java
new file mode 100644
index 000000000..1bfb10729
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/Configuration.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.cm;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Filter;
+
+/**
+ * The configuration information for a {@code ManagedService} or
+ * {@code ManagedServiceFactory} object.
+ *
+ * The Configuration Admin service uses this interface to represent the
+ * configuration information for a {@code ManagedService} or for a service
+ * instance of a {@code ManagedServiceFactory}.
+ *
+ * <p>
+ * A {@code Configuration} object contains a configuration dictionary and allows
+ * the properties to be updated via this object. Bundles wishing to receive
+ * configuration dictionaries do not need to use this class - they register a
+ * {@code ManagedService} or {@code ManagedServiceFactory}. Only administrative
+ * bundles, and bundles wishing to update their own configurations need to use
+ * this class.
+ *
+ * <p>
+ * The properties handled in this configuration have case insensitive
+ * {@code String} objects as keys. However, case must be preserved from the last
+ * set key/value.
+ * <p>
+ * A configuration can be <i>bound</i> to a specific bundle or to a region of
+ * bundles using the <em>location</em>. In its simplest form the location is the
+ * location of the target bundle that registered a Managed Service or a Managed
+ * Service Factory. However, if the location starts with {@code ?} then the
+ * location indicates multiple delivery. In such a case the configuration must
+ * be delivered to all targets.
+ *
+ * If security is on, the Configuration Permission can be used to restrict the
+ * targets that receive updates. The Configuration Admin must only update a
+ * target when the configuration location matches the location of the target's
+ * bundle or the target bundle has a Configuration Permission with the action
+ * {@link ConfigurationPermission#TARGET} and a name that matches the
+ * configuration location. The name in the permission may contain wildcards (
+ * {@code '*'}) to match the location using the same substring matching rules as
+ * {@link Filter}.
+ *
+ * Bundles can always create, manipulate, and be updated from configurations
+ * that have a location that matches their bundle location.
+ *
+ * <p>
+ * If a configuration's location is {@code null}, it is not yet bound to a
+ * location. It will become bound to the location of the first bundle that
+ * registers a {@code ManagedService} or {@code ManagedServiceFactory} object
+ * with the corresponding PID.
+ * <p>
+ * The same {@code Configuration} object is used for configuring both a Managed
+ * Service Factory and a Managed Service. When it is important to differentiate
+ * between these two the term "factory configuration" is used.
+ *
+ * @author $Id$
+ */
+@ProviderType
+public interface Configuration {
+ /**
+ * Get the PID for this {@code Configuration} object.
+ *
+ * @return the PID for this {@code Configuration} object.
+ * @throws IllegalStateException if this configuration has been deleted
+ */
+ public String getPid();
+
+ /**
+ * Return the properties of this {@code Configuration} object.
+ *
+ * The {@code Dictionary} object returned is a private copy for the caller
+ * and may be changed without influencing the stored configuration. The keys
+ * in the returned dictionary are case insensitive and are always of type
+ * {@code String}.
+ *
+ * <p>
+ * If called just after the configuration is created and before update has
+ * been called, this method returns {@code null}.
+ *
+ * @return A private copy of the properties for the caller or {@code null}.
+ * These properties must not contain the "service.bundleLocation"
+ * property. The value of this property may be obtained from the
+ * {@link #getBundleLocation()} method.
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public Dictionary<String, Object> getProperties();
+
+ /**
+ * Update the properties of this {@code Configuration} object.
+ *
+ * Stores the properties in persistent storage after adding or overwriting
+ * the following properties:
+ * <ul>
+ * <li>"service.pid" : is set to be the PID of this configuration.</li>
+ * <li>"service.factoryPid" : if this is a factory configuration it is set
+ * to the factory PID else it is not set.</li>
+ * </ul>
+ * These system properties are all of type {@code String}.
+ *
+ * <p>
+ * If the corresponding Managed Service/Managed Service Factory is
+ * registered, its updated method must be called asynchronously. Else, this
+ * callback is delayed until aforementioned registration occurs.
+ *
+ * <p>
+ * Also initiates an asynchronous call to all {@link ConfigurationListener}s
+ * with a {@link ConfigurationEvent#CM_UPDATED} event.
+ *
+ * @param properties the new set of properties for this configuration
+ * @throws IOException if update cannot be made persistent
+ * @throws IllegalArgumentException if the {@code Dictionary} object
+ * contains invalid configuration types or contains case variants of
+ * the same key name.
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public void update(Dictionary<String, ?> properties) throws IOException;
+
+ /**
+ * Delete this {@code Configuration} object.
+ *
+ * Removes this configuration object from the persistent store. Notify
+ * asynchronously the corresponding Managed Service or Managed Service
+ * Factory. A {@link ManagedService} object is notified by a call to its
+ * {@code updated} method with a {@code null} properties argument. A
+ * {@link ManagedServiceFactory} object is notified by a call to its
+ * {@code deleted} method.
+ *
+ * <p>
+ * Also initiates an asynchronous call to all {@link ConfigurationListener}s
+ * with a {@link ConfigurationEvent#CM_DELETED} event.
+ *
+ * @throws IOException If delete fails.
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public void delete() throws IOException;
+
+ /**
+ * For a factory configuration return the PID of the corresponding Managed
+ * Service Factory, else return {@code null}.
+ *
+ * @return factory PID or {@code null}
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public String getFactoryPid();
+
+ /**
+ * Update the {@code Configuration} object with the current properties.
+ *
+ * Initiate the {@code updated} callback to the Managed Service or Managed
+ * Service Factory with the current properties asynchronously.
+ *
+ * <p>
+ * This is the only way for a bundle that uses a Configuration Plugin
+ * service to initiate a callback. For example, when that bundle detects a
+ * change that requires an update of the Managed Service or Managed Service
+ * Factory via its {@code ConfigurationPlugin} object.
+ *
+ * @see ConfigurationPlugin
+ * @throws IOException if update cannot access the properties in persistent
+ * storage
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public void update() throws IOException;
+
+ /**
+ * Bind this {@code Configuration} object to the specified location.
+ *
+ * If the location parameter is {@code null} then the {@code Configuration}
+ * object will not be bound to a location/region. It will be set to the
+ * bundle's location before the first time a Managed Service/Managed Service
+ * Factory receives this {@code Configuration} object via the updated method
+ * and before any plugins are called. The bundle location or region will be
+ * set persistently.
+ *
+ * <p>
+ * If the location starts with {@code ?} then all targets registered with
+ * the given PID must be updated.
+ *
+ * <p>
+ * If the location is changed then existing targets must be informed. If
+ * they can no longer see this configuration, the configuration must be
+ * deleted or updated with {@code null}. If this configuration becomes
+ * visible then they must be updated with this configuration.
+ *
+ * <p>
+ * Also initiates an asynchronous call to all {@link ConfigurationListener}s
+ * with a {@link ConfigurationEvent#CM_LOCATION_CHANGED} event.
+ *
+ * @param location a location, region, or {@code null}
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @throws SecurityException when the required permissions are not available
+ * @throws SecurityException when the required permissions are not available
+ * @security ConfigurationPermission[this.location,CONFIGURE] if
+ * this.location is not {@code null}
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission["*",CONFIGURE] if this.location is
+ * {@code null} or if location is {@code null}
+ */
+ public void setBundleLocation(String location);
+
+ /**
+ * Get the bundle location.
+ *
+ * Returns the bundle location or region to which this configuration is
+ * bound, or {@code null} if it is not yet bound to a bundle location or
+ * region. If the location starts with {@code ?} then the configuration is
+ * delivered to all targets and not restricted to a single bundle.
+ *
+ * @return location to which this configuration is bound, or {@code null}.
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @throws SecurityException when the required permissions are not available
+ * @security ConfigurationPermission[this.location,CONFIGURE] if
+ * this.location is not {@code null}
+ * @security ConfigurationPermission["*",CONFIGURE] if this.location is
+ * {@code null}
+ *
+ */
+ public String getBundleLocation();
+
+ /**
+ * Get the change count.
+ *
+ * The Configuration must maintain a change counter that every time when
+ * this configuration is updated and its properties are stored is
+ * incremented with a positive value. The counter must be changed after the
+ * properties are persisted but before the targets are updated and events
+ * are sent out.
+ *
+ * @return A monotonously increasing value reflecting changes in this
+ * Configuration
+ *
+ * @since 1.5
+ */
+ public long getChangeCount();
+
+ /**
+ * Equality is defined to have equal PIDs
+ *
+ * Two Configuration objects are equal when their PIDs are equal.
+ *
+ * @param other {@code Configuration} object to compare against
+ * @return {@code true} if equal, {@code false} if not a
+ * {@code Configuration} object or one with a different PID.
+ */
+ public boolean equals(Object other);
+
+ /**
+ * Hash code is based on PID.
+ *
+ * The hash code for two Configuration objects must be the same when the
+ * Configuration PID's are the same.
+ *
+ * @return hash code for this Configuration object
+ */
+ public int hashCode();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationAdmin.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationAdmin.java
new file mode 100644
index 000000000..3c2d838a0
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationAdmin.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.cm;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * Service for administering configuration data.
+ *
+ * <p>
+ * The main purpose of this interface is to store bundle configuration data
+ * persistently. This information is represented in {@code Configuration}
+ * objects. The actual configuration data is a {@code Dictionary} of properties
+ * inside a {@code Configuration} object.
+ *
+ * <p>
+ * There are two principally different ways to manage configurations. First
+ * there is the concept of a Managed Service, where configuration data is
+ * uniquely associated with an object registered with the service registry.
+ *
+ * <p>
+ * Next, there is the concept of a factory where the Configuration Admin service
+ * will maintain 0 or more {@code Configuration} objects for a Managed Service
+ * Factory that is registered with the Framework.
+ *
+ * <p>
+ * The first concept is intended for configuration data about "things/services"
+ * whose existence is defined externally, e.g. a specific printer. Factories are
+ * intended for "things/services" that can be created any number of times, e.g.
+ * a configuration for a DHCP server for different networks.
+ *
+ * <p>
+ * Bundles that require configuration should register a Managed Service or a
+ * Managed Service Factory in the service registry. A registration property
+ * named {@code service.pid} (persistent identifier or PID) must be used to
+ * identify this Managed Service or Managed Service Factory to the Configuration
+ * Admin service.
+ *
+ * <p>
+ * When the ConfigurationAdmin detects the registration of a Managed Service, it
+ * checks its persistent storage for a configuration object whose
+ * {@code service.pid} property matches the PID service property (
+ * {@code service.pid}) of the Managed Service. If found, it calls
+ * {@link ManagedService#updated(Dictionary)} method with the new properties.
+ * The implementation of a Configuration Admin service must run these call-backs
+ * asynchronously to allow proper synchronization.
+ *
+ * <p>
+ * When the Configuration Admin service detects a Managed Service Factory
+ * registration, it checks its storage for configuration objects whose
+ * {@code service.factoryPid} property matches the PID service property of the
+ * Managed Service Factory. For each such {@code Configuration} objects, it
+ * calls the {@code ManagedServiceFactory.updated} method asynchronously with
+ * the new properties. The calls to the {@code updated} method of a
+ * {@code ManagedServiceFactory} must be executed sequentially and not overlap
+ * in time.
+ *
+ * <p>
+ * In general, bundles having permission to use the Configuration Admin service
+ * can only access and modify their own configuration information. Accessing or
+ * modifying the configuration of other bundles requires
+ * {@code ConfigurationPermission[location,CONFIGURE]}, where location is the
+ * configuration location.
+ *
+ * <p>
+ * {@code Configuration} objects can be <i>bound</i> to a specified bundle
+ * location or to a region (configuration location starts with {@code ?}). If a
+ * location is not set, it will be learned the first time a target is
+ * registered. If the location is learned this way, the Configuration Admin
+ * service must detect if the bundle corresponding to the location is
+ * uninstalled. If this occurs, the {@code Configuration} object must be
+ * unbound, that is its location field is set back to {@code null}.
+ *
+ * <p>
+ * If target's bundle location matches the configuration location it is always
+ * updated.
+ *
+ * <p>
+ * If the configuration location starts with {@code ?}, that is, the location is
+ * a region, then the configuration must be delivered to all targets registered
+ * with the given PID. If security is on, the target bundle must have
+ * Configuration Permission[location,TARGET], where location matches given the
+ * configuration location with wildcards as in the Filter substring match. The
+ * security must be verified using the
+ * {@link org.osgi.framework.Bundle#hasPermission(Object)} method on the target
+ * bundle.
+ *
+ * <p>
+ * If a target cannot be updated because the location does not match or it has
+ * no permission and security is active then the Configuration Admin service
+ * must not do the normal callback.
+ *
+ * <p>
+ * The method descriptions of this class refer to a concept of "the calling
+ * bundle". This is a loose way of referring to the bundle which obtained the
+ * Configuration Admin service from the service registry. Implementations of
+ * {@code ConfigurationAdmin} must use a
+ * {@link org.osgi.framework.ServiceFactory} to support this concept.
+ *
+ * @author $Id$
+ */
+@ProviderType
+public interface ConfigurationAdmin {
+ /**
+ * Configuration property naming the Factory PID in the configuration
+ * dictionary. The property's value is of type {@code String}.
+ *
+ * @since 1.1
+ */
+ public final static String SERVICE_FACTORYPID = "service.factoryPid";
+ /**
+ * Configuration property naming the location of the bundle that is
+ * associated with a a {@code Configuration} object. This property can be
+ * searched for but must not appear in the configuration dictionary for
+ * security reason. The property's value is of type {@code String}.
+ *
+ * @since 1.1
+ */
+ public final static String SERVICE_BUNDLELOCATION = "service.bundleLocation";
+
+ /**
+ * Create a new factory {@code Configuration} object with a new PID.
+ *
+ * The properties of the new {@code Configuration} object are {@code null}
+ * until the first time that its {@link Configuration#update(Dictionary)}
+ * method is called.
+ *
+ * <p>
+ * It is not required that the {@code factoryPid} maps to a registered
+ * Managed Service Factory.
+ *
+ * <p>
+ * The {@code Configuration} object is bound to the location of the calling
+ * bundle. It is possible that the same factoryPid has associated
+ * configurations that are bound to different bundles. Bundles should only
+ * see the factory configurations that they are bound to or have the proper
+ * permission.
+ *
+ * @param factoryPid PID of factory (not {@code null}).
+ * @return A new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ */
+ public Configuration createFactoryConfiguration(String factoryPid) throws IOException;
+
+ /**
+ * Create a new factory {@code Configuration} object with a new PID.
+ *
+ * The properties of the new {@code Configuration} object are {@code null}
+ * until the first time that its {@link Configuration#update(Dictionary)}
+ * method is called.
+ *
+ * <p>
+ * It is not required that the {@code factoryPid} maps to a registered
+ * Managed Service Factory.
+ *
+ * <p>
+ * The {@code Configuration} is bound to the location specified. If this
+ * location is {@code null} it will be bound to the location of the first
+ * bundle that registers a Managed Service Factory with a corresponding PID.
+ * It is possible that the same factoryPid has associated configurations
+ * that are bound to different bundles. Bundles should only see the factory
+ * configurations that they are bound to or have the proper permission.
+ *
+ * <p>
+ * If the location starts with {@code ?} then the configuration must be
+ * delivered to all targets with the corresponding PID.
+ *
+ * @param factoryPid PID of factory (not {@code null}).
+ * @param location A bundle location string, or {@code null}.
+ * @return a new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the require permissions are not available
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission["*",CONFIGURE] if location is
+ * {@code null}
+ */
+ public Configuration createFactoryConfiguration(String factoryPid, String location) throws IOException;
+
+ /**
+ * Get an existing {@code Configuration} object from the persistent store,
+ * or create a new {@code Configuration} object.
+ *
+ * <p>
+ * If a {@code Configuration} with this PID already exists in Configuration
+ * Admin service return it. The location parameter is ignored in this case
+ * though it is still used for a security check.
+ *
+ * <p>
+ * Else, return a new {@code Configuration} object. This new object is bound
+ * to the location and the properties are set to {@code null}. If the
+ * location parameter is {@code null}, it will be set when a Managed Service
+ * with the corresponding PID is registered for the first time. If the
+ * location starts with {@code ?} then the configuration is bound to all
+ * targets that are registered with the corresponding PID.
+ *
+ * @param pid Persistent identifier.
+ * @param location The bundle location string, or {@code null}.
+ * @return An existing or new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the require permissions are not available
+ * @security ConfigurationPermission[*,CONFIGURE] if location is
+ * {@code null} or if the returned configuration {@code c} already
+ * exists and c.location is {@code null}
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission[c.location,CONFIGURE] if the returned
+ * configuration {@code c} already exists and c.location is not
+ * {@code null}
+ */
+ public Configuration getConfiguration(String pid, String location) throws IOException;
+
+ /**
+ * Get an existing or new {@code Configuration} object from the persistent
+ * store.
+ *
+ * If the {@code Configuration} object for this PID does not exist, create a
+ * new {@code Configuration} object for that PID, where properties are
+ * {@code null}. Bind its location to the calling bundle's location.
+ *
+ * <p>
+ * Otherwise, if the location of the existing {@code Configuration} object
+ * is {@code null}, set it to the calling bundle's location.
+ *
+ * @param pid persistent identifier.
+ * @return an existing or new {@code Configuration} matching the PID.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the required permission is not available
+ * @security ConfigurationPermission[c.location,CONFIGURE] If the
+ * configuration {@code c} already exists and c.location is not
+ * {@code null}
+ */
+ public Configuration getConfiguration(String pid) throws IOException;
+
+ /**
+ * List the current {@code Configuration} objects which match the filter.
+ *
+ * <p>
+ * Only {@code Configuration} objects with non- {@code null} properties are
+ * considered current. That is, {@code Configuration.getProperties()} is
+ * guaranteed not to return {@code null} for each of the returned
+ * {@code Configuration} objects.
+ *
+ * <p>
+ * When there is no security on then all configurations can be returned. If
+ * security is on, the caller must have
+ * ConfigurationPermission[location,CONFIGURE].
+ *
+ * <p>
+ * The syntax of the filter string is as defined in the {@link Filter}
+ * class. The filter can test any configuration properties including the
+ * following:
+ * <ul>
+ * <li>{@code service.pid} - the persistent identity</li>
+ * <li>{@code service.factoryPid} - the factory PID, if applicable</li>
+ * <li>{@code service.bundleLocation} - the bundle location</li>
+ * </ul>
+ * The filter can also be {@code null}, meaning that all
+ * {@code Configuration} objects should be returned.
+ *
+ * @param filter A filter string, or {@code null} to retrieve all
+ * {@code Configuration} objects.
+ * @return All matching {@code Configuration} objects, or {@code null} if
+ * there aren't any.
+ * @throws IOException if access to persistent storage fails
+ * @throws InvalidSyntaxException if the filter string is invalid
+ * @security ConfigurationPermission[c.location,CONFIGURE] Only
+ * configurations {@code c} are returned for which the caller has
+ * this permission
+ */
+ public Configuration[] listConfigurations(String filter) throws IOException, InvalidSyntaxException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationEvent.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationEvent.java
new file mode 100644
index 000000000..b6e83bbc5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationEvent.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.cm;
+
+import java.util.Dictionary;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A Configuration Event.
+ *
+ * <p>
+ * {@code ConfigurationEvent} objects are delivered to all registered
+ * {@code ConfigurationListener} service objects. ConfigurationEvents must be
+ * asynchronously delivered in chronological order with respect to each
+ * listener.
+ *
+ * <p>
+ * A type code is used to identify the type of event. The following event types
+ * are defined:
+ * <ul>
+ * <li>{@link #CM_UPDATED}</li>
+ * <li>{@link #CM_DELETED}</li>
+ * <li>{@link #CM_LOCATION_CHANGED}</li>
+ * </ul>
+ * Additional event types may be defined in the future.
+ *
+ * <p>
+ * Security Considerations. {@code ConfigurationEvent} objects do not provide
+ * {@code Configuration} objects, so no sensitive configuration information is
+ * available from the event. If the listener wants to locate the
+ * {@code Configuration} object for the specified pid, it must use
+ * {@code ConfigurationAdmin}.
+ *
+ * @see ConfigurationListener
+ * @Immutable
+ * @author $Id$
+ * @since 1.2
+ */
+public class ConfigurationEvent {
+ /**
+ * A {@code Configuration} has been updated.
+ *
+ * <p>
+ * This {@code ConfigurationEvent} type that indicates that a
+ * {@code Configuration} object has been updated with new properties.
+ *
+ * An event is fired when a call to {@link Configuration#update(Dictionary)}
+ * successfully changes a configuration.
+ */
+ public static final int CM_UPDATED = 1;
+ /**
+ * A {@code Configuration} has been deleted.
+ *
+ * <p>
+ * This {@code ConfigurationEvent} type that indicates that a
+ * {@code Configuration} object has been deleted.
+ *
+ * An event is fired when a call to {@link Configuration#delete()}
+ * successfully deletes a configuration.
+ */
+ public static final int CM_DELETED = 2;
+
+ /**
+ * The location of a {@code Configuration} has been changed.
+ *
+ * <p>
+ * This {@code ConfigurationEvent} type that indicates that the location of
+ * a {@code Configuration} object has been changed.
+ *
+ * An event is fired when a call to
+ * {@link Configuration#setBundleLocation(String)} successfully changes the
+ * location.
+ *
+ * @since 1.4
+ */
+ public static final int CM_LOCATION_CHANGED = 3;
+ /**
+ * Type of this event.
+ *
+ * @see #getType()
+ */
+ private final int type;
+ /**
+ * The factory pid associated with this event.
+ */
+ private final String factoryPid;
+ /**
+ * The pid associated with this event.
+ */
+ private final String pid;
+ /**
+ * The ConfigurationAdmin service which created this event.
+ */
+ private final ServiceReference<ConfigurationAdmin> reference;
+
+ /**
+ * Constructs a {@code ConfigurationEvent} object from the given
+ * {@code ServiceReference} object, event type, and pids.
+ *
+ * @param reference The {@code ServiceReference} object of the Configuration
+ * Admin service that created this event.
+ * @param type The event type. See {@link #getType()}.
+ * @param factoryPid The factory pid of the associated configuration if the
+ * target of the configuration is a ManagedServiceFactory. Otherwise
+ * {@code null} if the target of the configuration is a
+ * ManagedService.
+ * @param pid The pid of the associated configuration.
+ */
+ public ConfigurationEvent(ServiceReference<ConfigurationAdmin> reference, int type, String factoryPid, String pid) {
+ this.reference = reference;
+ this.type = type;
+ this.factoryPid = factoryPid;
+ this.pid = pid;
+ if ((reference == null) || (pid == null)) {
+ throw new NullPointerException("reference and pid must not be null");
+ }
+ }
+
+ /**
+ * Returns the factory pid of the associated configuration.
+ *
+ * @return Returns the factory pid of the associated configuration if the
+ * target of the configuration is a ManagedServiceFactory. Otherwise
+ * {@code null} if the target of the configuration is a
+ * ManagedService.
+ */
+ public String getFactoryPid() {
+ return factoryPid;
+ }
+
+ /**
+ * Returns the pid of the associated configuration.
+ *
+ * @return Returns the pid of the associated configuration.
+ */
+ public String getPid() {
+ return pid;
+ }
+
+ /**
+ * Return the type of this event.
+ * <p>
+ * The type values are:
+ * <ul>
+ * <li>{@link #CM_UPDATED}</li>
+ * <li>{@link #CM_DELETED}</li>
+ * <li>{@link #CM_LOCATION_CHANGED}</li>
+ * </ul>
+ *
+ * @return The type of this event.
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Return the {@code ServiceReference} object of the Configuration Admin
+ * service that created this event.
+ *
+ * @return The {@code ServiceReference} object for the Configuration Admin
+ * service that created this event.
+ */
+ public ServiceReference<ConfigurationAdmin> getReference() {
+ return reference;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationException.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationException.java
new file mode 100644
index 000000000..373726d33
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationException.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.cm;
+
+/**
+ * An {@code Exception} class to inform the Configuration Admin service of
+ * problems with configuration data.
+ *
+ * @author $Id$
+ */
+public class ConfigurationException extends Exception {
+ static final long serialVersionUID = -1690090413441769377L;
+
+ private final String property;
+ private final String reason;
+
+ /**
+ * Create a {@code ConfigurationException} object.
+ *
+ * @param property name of the property that caused the problem,
+ * {@code null} if no specific property was the cause
+ * @param reason reason for failure
+ */
+ public ConfigurationException(String property, String reason) {
+ super(property + " : " + reason);
+ this.property = property;
+ this.reason = reason;
+ }
+
+ /**
+ * Create a {@code ConfigurationException} object.
+ *
+ * @param property name of the property that caused the problem,
+ * {@code null} if no specific property was the cause
+ * @param reason reason for failure
+ * @param cause The cause of this exception.
+ * @since 1.2
+ */
+ public ConfigurationException(String property, String reason, Throwable cause) {
+ super(property + " : " + reason, cause);
+ this.property = property;
+ this.reason = reason;
+ }
+
+ /**
+ * Return the property name that caused the failure or null.
+ *
+ * @return name of property or null if no specific property caused the
+ * problem
+ */
+ public String getProperty() {
+ return property;
+ }
+
+ /**
+ * Return the reason for this exception.
+ *
+ * @return reason of the failure
+ */
+ public String getReason() {
+ return reason;
+ }
+
+ /**
+ * Returns the cause of this exception or {@code null} if no cause was set.
+ *
+ * @return The cause of this exception or {@code null} if no cause was set.
+ * @since 1.2
+ */
+ public Throwable getCause() {
+ return super.getCause();
+ }
+
+ /**
+ * Initializes the cause of this exception to the specified value.
+ *
+ * @param cause The cause of this exception.
+ * @return This exception.
+ * @throws IllegalArgumentException If the specified cause is this
+ * exception.
+ * @throws IllegalStateException If the cause of this exception has already
+ * been set.
+ * @since 1.2
+ */
+ public Throwable initCause(Throwable cause) {
+ return super.initCause(cause);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationListener.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationListener.java
new file mode 100644
index 000000000..7b228e523
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationListener.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.cm;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Listener for Configuration Events. When a {@code ConfigurationEvent} is
+ * fired, it is asynchronously delivered to a {@code ConfigurationListener}.
+ *
+ * <p>
+ * {@code ConfigurationListener} objects are registered with the Framework
+ * service registry and are notified with a {@code ConfigurationEvent} object
+ * when an event is fired.
+ * <p>
+ * {@code ConfigurationListener} objects can inspect the received
+ * {@code ConfigurationEvent} object to determine its type, the pid of the
+ * {@code Configuration} object with which it is associated, and the
+ * Configuration Admin service that fired the event.
+ *
+ * <p>
+ * Security Considerations. Bundles wishing to monitor configuration events will
+ * require {@code ServicePermission[ConfigurationListener,REGISTER]} to register
+ * a {@code ConfigurationListener} service.
+ *
+ * @author $Id$
+ * @since 1.2
+ */
+@ConsumerType
+public interface ConfigurationListener {
+ /**
+ * Receives notification of a Configuration that has changed.
+ *
+ * @param event The {@code ConfigurationEvent}.
+ */
+ public void configurationEvent(ConfigurationEvent event);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPermission.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPermission.java
new file mode 100644
index 000000000..ea3f7764e
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPermission.java
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.cm;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.osgi.framework.Filter;
+
+/**
+ * Indicates a bundle's authority to configure bundles or be updated by
+ * Configuration Admin.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ * @since 1.2
+ */
+
+public final class ConfigurationPermission extends BasicPermission {
+ static final long serialVersionUID = 5716868734811965383L;
+ /**
+ * Provides permission to create new configurations for other bundles as
+ * well as manipulate them. The action string {@value #CONFIGURE}.
+ */
+ public final static String CONFIGURE = "configure";
+
+ /**
+ * The permission to be updated, that is, act as a Managed Service or
+ * Managed Service Factory. The action string {@value #TARGET}.
+ *
+ * @since 1.4
+ */
+ public final static String TARGET = "target";
+
+ private final static int ACTION_CONFIGURE = 0x00000001;
+ private final static int ACTION_TARGET = 0x00000002;
+ private final static int ACTION_ALL = ACTION_CONFIGURE | ACTION_TARGET;
+ final static int ACTION_NONE = 0;
+
+ /**
+ * The actions mask.
+ */
+ transient int action_mask;
+
+ /**
+ * The actions in canonical form.
+ *
+ * @serial
+ */
+ private volatile String actions = null;
+
+ /**
+ * Parsed name if it includes wildcards: "*"
+ */
+ private transient List<String> substrings;
+
+ /**
+ * Create a new ConfigurationPermission.
+ *
+ * @param name Name of the permission. Wildcards ({@code '*'}) are allowed
+ * in the name. During {@link #implies(Permission)}, the name is
+ * matched to the requested permission using the substring matching
+ * rules used by {@link Filter}s.
+ * @param actions Comma separated list of {@link #CONFIGURE},
+ * {@link #TARGET} (case insensitive).
+ */
+
+ public ConfigurationPermission(String name, String actions) {
+ this(name, parseActions(actions));
+ }
+
+ /**
+ * Package private constructor used by ConfigurationPermissionCollection.
+ *
+ * @param name location string
+ * @param mask action mask
+ */
+ ConfigurationPermission(String name, int mask) {
+ super(name);
+ setTransients(mask);
+ }
+
+ /**
+ * Called by constructors and when deserialized.
+ *
+ * @param mask action mask
+ */
+ private void setTransients(int mask) {
+ if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+ throw new IllegalArgumentException("invalid action string");
+ }
+ action_mask = mask;
+ substrings = parseSubstring(getName());
+ }
+
+ /**
+ * Parse action string into action mask.
+ *
+ * @param actions Action string.
+ * @return action mask.
+ */
+ private static int parseActions(String actions) {
+ boolean seencomma = false;
+
+ int mask = ACTION_NONE;
+
+ if (actions == null) {
+ return mask;
+ }
+
+ char[] a = actions.toCharArray();
+
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+
+ while (i != -1) {
+ char c;
+
+ // skip whitespace
+ while ((i != -1) && ((c = a[i]) == ' ' || c == '\r' || c == '\n' || c == '\f' || c == '\t'))
+ i--;
+
+ // check for the known strings
+ int matchlen;
+
+ if (i >= 5 && (a[i - 5] == 't' || a[i - 5] == 'T')
+ && (a[i - 4] == 'a' || a[i - 4] == 'A')
+ && (a[i - 3] == 'r' || a[i - 3] == 'R')
+ && (a[i - 2] == 'g' || a[i - 2] == 'G')
+ && (a[i - 1] == 'e' || a[i - 1] == 'E')
+ && (a[i] == 't' || a[i] == 'T')) {
+ matchlen = 6;
+ mask |= ACTION_TARGET;
+
+ } else
+ if (i >= 8 && (a[i - 8] == 'c' || a[i - 8] == 'C')
+ && (a[i - 7] == 'o' || a[i - 7] == 'O')
+ && (a[i - 6] == 'n' || a[i - 6] == 'N')
+ && (a[i - 5] == 'f' || a[i - 5] == 'F')
+ && (a[i - 4] == 'i' || a[i - 4] == 'I')
+ && (a[i - 3] == 'g' || a[i - 3] == 'G')
+ && (a[i - 2] == 'u' || a[i - 2] == 'U')
+ && (a[i - 1] == 'r' || a[i - 1] == 'R')
+ && (a[i] == 'e' || a[i] == 'E')) {
+ matchlen = 9;
+ mask |= ACTION_CONFIGURE;
+
+ } else {
+ // parse error
+ throw new IllegalArgumentException("invalid actions: " + actions);
+ }
+
+ // make sure we didn't just match the tail of a word
+ // like "ackbarftarget". Also, skip to the comma.
+ seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch (a[i - matchlen]) {
+ case ',' :
+ seencomma = true;
+ /* FALLTHROUGH */
+ case ' ' :
+ case '\r' :
+ case '\n' :
+ case '\f' :
+ case '\t' :
+ break;
+ default :
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ i--;
+ }
+
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+
+ if (seencomma) {
+ throw new IllegalArgumentException("invalid actions: " + actions);
+ }
+
+ return mask;
+ }
+
+ /**
+ * Parse the name for wildcard processing.
+ *
+ * @param name The name of the permission.
+ * @return {@code null} is the name has no wildcards or a
+ * {@code List<String>} where element is a substring to match or
+ * null for {@code '*'}.
+ */
+ private static List<String> parseSubstring(String name) {
+ if (name.indexOf('*') < 0) {
+ return null;
+ }
+ char[] chars = name.toCharArray();
+ StringBuffer sb = new StringBuffer(chars.length);
+
+ List<String> sub = new ArrayList<String>(10);
+
+ for (int pos = 0; pos < chars.length; pos++) {
+ char c = chars[pos];
+
+ switch (c) {
+ case '*' : {
+ if (sb.length() > 0) {
+ sub.add(sb.toString());
+ }
+ sb.setLength(0);
+ sub.add(null);
+ break;
+ }
+
+ case '\\' : {
+ pos++;
+ if (pos < chars.length) {
+ c = chars[pos];
+ }
+ /* fall through into default */
+ }
+
+ default : {
+ sb.append(c);
+ break;
+ }
+ }
+ }
+ if (sb.length() > 0) {
+ sub.add(sb.toString());
+ }
+
+ int size = sub.size();
+
+ if (size == 0) {
+ return null;
+ }
+
+ if (size == 1) {
+ if (sub.get(0) != null) {
+ return null;
+ }
+ }
+ return sub;
+ }
+
+ /**
+ * Determines if a {@code ConfigurationPermission} object "implies" the
+ * specified permission.
+ *
+ * @param p The target permission to check.
+ * @return {@code true} if the specified permission is implied by this
+ * object; {@code false} otherwise.
+ */
+
+ @Override
+ public boolean implies(Permission p) {
+ if (!(p instanceof ConfigurationPermission)) {
+ return false;
+ }
+ ConfigurationPermission requested = (ConfigurationPermission) p;
+ return implies0(requested, ACTION_NONE);
+ }
+
+ /**
+ * Internal implies method. Used by the implies and the permission
+ * collection implies methods.
+ *
+ * @param requested The requested ConfigurationPermission which has already
+ * be validated as a proper argument.
+ * @param effective The effective actions with which to start.
+ * @return {@code true} if the specified permission is implied by this
+ * object; {@code false} otherwise.
+ */
+ boolean implies0(ConfigurationPermission requested, int effective) {
+ /* check actions first - much faster */
+ effective |= action_mask;
+ final int desired = requested.action_mask;
+ if ((effective & desired) != desired) {
+ return false;
+ }
+ String requestedName = requested.getName();
+ if (substrings == null) {
+ return getName().equals(requestedName);
+ }
+ for (int i = 0, pos = 0, size = substrings.size(); i < size; i++) {
+ String substr = substrings.get(i);
+
+ if (i + 1 < size) /* if this is not that last substr */{
+ if (substr == null) /* * */{
+ String substr2 = substrings.get(i + 1);
+
+ if (substr2 == null) /* ** */
+ continue; /* ignore first star */
+ /* xxx */
+ int index = requestedName.indexOf(substr2, pos);
+ if (index == -1) {
+ return false;
+ }
+
+ pos = index + substr2.length();
+ if (i + 2 < size) // if there are more
+ // substrings, increment
+ // over the string we just
+ // matched; otherwise need
+ // to do the last substr
+ // check
+ i++;
+ } else /* xxx */{
+ int len = substr.length();
+ if (requestedName.regionMatches(pos, substr, 0, len)) {
+ pos += len;
+ } else {
+ return false;
+ }
+ }
+ } else /* last substr */{
+ if (substr == null) /* * */{
+ return true;
+ }
+ /* xxx */
+ return requestedName.endsWith(substr);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines the equality of two {@code ConfigurationPermission} objects.
+ * <p>
+ * Two {@code ConfigurationPermission} objects are equal.
+ *
+ * @param obj The object being compared for equality with this object.
+ * @return {@code true} if {@code obj} is equivalent to this
+ * {@code ConfigurationPermission}; {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof ConfigurationPermission)) {
+ return false;
+ }
+
+ ConfigurationPermission cp = (ConfigurationPermission) obj;
+
+ return (action_mask == cp.action_mask) && getName().equals(cp.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return Hash code value for this object.
+ */
+
+ @Override
+ public int hashCode() {
+ int h = 31 * 17 + getName().hashCode();
+ h = 31 * h + getActions().hashCode();
+ return h;
+ }
+
+ /**
+ * Returns the canonical string representation of the
+ * {@code ConfigurationPermission} actions.
+ *
+ * <p>
+ * Always returns present {@code ConfigurationPermission} actions in the
+ * following order: {@value #CONFIGURE}, {@value #TARGET}
+ *
+ * @return Canonical string representation of the
+ * {@code ConfigurationPermission} actions.
+ */
+ @Override
+ public String getActions() {
+ String result = actions;
+ if (result == null) {
+ StringBuffer sb = new StringBuffer();
+ boolean comma = false;
+
+ int mask = action_mask;
+ if ((mask & ACTION_CONFIGURE) == ACTION_CONFIGURE) {
+ sb.append(CONFIGURE);
+ comma = true;
+ }
+
+ if ((mask & ACTION_TARGET) == ACTION_TARGET) {
+ if (comma)
+ sb.append(',');
+ sb.append(TARGET);
+ }
+
+ actions = result = sb.toString();
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a new {@code PermissionCollection} object suitable for storing
+ * {@code ConfigurationPermission}s.
+ *
+ * @return A new {@code PermissionCollection} object.
+ */
+ @Override
+ public PermissionCollection newPermissionCollection() {
+ return new ConfigurationPermissionCollection();
+ }
+
+ /**
+ * WriteObject is called to save the state of this permission object to a
+ * stream. The actions are serialized, and the superclass takes care of the
+ * name.
+ */
+ private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ // Write out the actions. The superclass takes care of the name
+ // call getActions to make sure actions field is initialized
+ if (actions == null)
+ getActions();
+ s.defaultWriteObject();
+ }
+
+ /**
+ * readObject is called to restore the state of this permission from a
+ * stream.
+ */
+ private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
+ // Read in the data, then initialize the transients
+ s.defaultReadObject();
+ setTransients(parseActions(actions));
+ }
+}
+
+/**
+ * Stores a set of {@code ConfigurationPermission} permissions.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ */
+final class ConfigurationPermissionCollection extends PermissionCollection {
+ static final long serialVersionUID = -6917638867081695839L;
+ /**
+ * Collection of permissions.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private Map<String, ConfigurationPermission> permissions;
+
+ /**
+ * Boolean saying if "*" is in the collection.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private boolean all_allowed;
+
+ /**
+ * Creates an empty {@code ConfigurationPermissionCollection} object.
+ *
+ */
+ public ConfigurationPermissionCollection() {
+ permissions = new HashMap<String, ConfigurationPermission>();
+ all_allowed = false;
+ }
+
+ /**
+ * Adds the specified permission to the
+ * {@code ConfigurationPermissionCollection}. The key for the hash is the
+ * interface name of the service.
+ *
+ * @param permission The {@code Permission} object to add.
+ *
+ * @exception IllegalArgumentException If the permission is not an
+ * {@code ConfigurationPermission}.
+ *
+ * @exception SecurityException If this ConfigurationPermissionCollection
+ * object has been marked read-only.
+ */
+
+ @Override
+ public void add(Permission permission) {
+ if (!(permission instanceof ConfigurationPermission)) {
+ throw new IllegalArgumentException("invalid permission: " + permission);
+ }
+
+ if (isReadOnly())
+ throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection");
+
+ final ConfigurationPermission cp = (ConfigurationPermission) permission;
+ final String name = cp.getName();
+ synchronized (this) {
+ Map<String, ConfigurationPermission> pc = permissions;
+ final ConfigurationPermission existing = pc.get(name);
+ if (existing != null) {
+ final int oldMask = existing.action_mask;
+ final int newMask = cp.action_mask;
+ if (oldMask != newMask) {
+ pc.put(name, new ConfigurationPermission(name, oldMask | newMask));
+ }
+ } else {
+ pc.put(name, cp);
+ }
+
+ if (!all_allowed) {
+ if (name.equals("*")) {
+ all_allowed = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines if the specified permissions implies the permissions expressed
+ * in {@code permission}.
+ *
+ * @param permission The Permission object to compare with this
+ * {@code ConfigurationPermission} object.
+ * @return {@code true} if {@code permission} is a proper subset of a
+ * permission in the set; {@code false} otherwise.
+ */
+ @Override
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof ConfigurationPermission)) {
+ return false;
+ }
+ final ConfigurationPermission requested = (ConfigurationPermission) permission;
+ int effective = ConfigurationPermission.ACTION_NONE;
+
+ Collection<ConfigurationPermission> perms;
+ synchronized (this) {
+ Map<String, ConfigurationPermission> pc = permissions;
+ /* short circuit if the "*" Permission was added */
+ if (all_allowed) {
+ ConfigurationPermission cp = pc.get("*");
+ if (cp != null) {
+ effective |= cp.action_mask;
+ final int desired = requested.action_mask;
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ }
+ perms = pc.values();
+ }
+ /* iterate one by one over permissions */
+ for (ConfigurationPermission perm : perms) {
+ if (perm.implies0(requested, effective)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all {@code ConfigurationPermission} objects in
+ * the container.
+ *
+ * @return Enumeration of all {@code ConfigurationPermission} objects.
+ */
+ @Override
+ public synchronized Enumeration<Permission> elements() {
+ List<Permission> all = new ArrayList<Permission>(permissions.values());
+ return Collections.enumeration(all);
+ }
+
+ /* serialization logic */
+ private static final ObjectStreamField[] serialPersistentFields = {new ObjectStreamField("hasElement", Boolean.TYPE), new ObjectStreamField("permissions", HashMap.class),
+ new ObjectStreamField("all_allowed", Boolean.TYPE) };
+
+ private synchronized void writeObject(ObjectOutputStream out) throws IOException {
+ ObjectOutputStream.PutField pfields = out.putFields();
+ pfields.put("hasElement", false);
+ pfields.put("permissions", permissions);
+ pfields.put("all_allowed", all_allowed);
+ out.writeFields();
+ }
+
+ private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+ ObjectInputStream.GetField gfields = in.readFields();
+ boolean hasElement = gfields.get("hasElement", false);
+ if (hasElement) { // old format
+ permissions = new HashMap<String, ConfigurationPermission>();
+ permissions.put("*", new ConfigurationPermission("*", ConfigurationPermission.CONFIGURE));
+ all_allowed = true;
+ } else {
+ @SuppressWarnings("unchecked")
+ HashMap<String, ConfigurationPermission> p = (HashMap<String, ConfigurationPermission>) gfields.get("permissions", new HashMap<String, ConfigurationPermission>());
+ permissions = p;
+ all_allowed = gfields.get("all_allowed", false);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPlugin.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPlugin.java
new file mode 100644
index 000000000..97d5ee807
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ConfigurationPlugin.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.cm;
+
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A service interface for processing configuration dictionary before the
+ * update.
+ *
+ * <p>
+ * A bundle registers a {@code ConfigurationPlugin} object in order to process
+ * configuration updates before they reach the Managed Service or Managed
+ * Service Factory. The Configuration Admin service will detect registrations of
+ * Configuration Plugin services and must call these services every time before
+ * it calls the {@code ManagedService} or {@code ManagedServiceFactory}
+ * {@code updated} method. The Configuration Plugin service thus has the
+ * opportunity to view and modify the properties before they are passed to the
+ * Managed Service or Managed Service Factory.
+ *
+ * <p>
+ * Configuration Plugin (plugin) services have full read/write access to all
+ * configuration information that passes through them.
+ *
+ * <p>
+ * The {@code Integer} {@code service.cmRanking} registration property may be
+ * specified. Not specifying this registration property, or setting it to
+ * something other than an {@code Integer}, is the same as setting it to the
+ * {@code Integer} zero. The {@code service.cmRanking} property determines the
+ * order in which plugins are invoked. Lower ranked plugins are called before
+ * higher ranked ones. In the event of more than one plugin having the same
+ * value of {@code service.cmRanking}, then the Configuration Admin service
+ * arbitrarily chooses the order in which they are called.
+ *
+ * <p>
+ * By convention, plugins with {@code service.cmRanking < 0} or
+ * {@code service.cmRanking > 1000} should not make modifications to the
+ * properties.
+ *
+ * <p>
+ * The Configuration Admin service has the right to hide properties from
+ * plugins, or to ignore some or all the changes that they make. This might be
+ * done for security reasons. Any such behavior is entirely implementation
+ * defined.
+ *
+ * <p>
+ * A plugin may optionally specify a {@code cm.target} registration property
+ * whose value is the PID of the Managed Service or Managed Service Factory
+ * whose configuration updates the plugin is intended to intercept. The plugin
+ * will then only be called with configuration updates that are targeted at the
+ * Managed Service or Managed Service Factory with the specified PID. Omitting
+ * the {@code cm.target} registration property means that the plugin is called
+ * for all configuration updates.
+ *
+ * @author $Id$
+ */
+@ConsumerType
+public interface ConfigurationPlugin {
+ /**
+ * A service property to limit the Managed Service or Managed Service
+ * Factory configuration dictionaries a Configuration Plugin service
+ * receives.
+ *
+ * This property contains a {@code String[]} of PIDs. A Configuration Admin
+ * service must call a Configuration Plugin service only when this property
+ * is not set, or the target service's PID is listed in this property.
+ */
+ public static final String CM_TARGET = "cm.target";
+ /**
+ * A service property to specify the order in which plugins are invoked.
+ *
+ * This property contains an {@code Integer} ranking of the plugin. Not
+ * specifying this registration property, or setting it to something other
+ * than an {@code Integer}, is the same as setting it to the {@code Integer}
+ * zero. This property determines the order in which plugins are invoked.
+ * Lower ranked plugins are called before higher ranked ones.
+ *
+ * @since 1.2
+ */
+ public static final String CM_RANKING = "service.cmRanking";
+
+ /**
+ * View and possibly modify the a set of configuration properties before
+ * they are sent to the Managed Service or the Managed Service Factory. The
+ * Configuration Plugin services are called in increasing order of their
+ * {@code service.cmRanking} property. If this property is undefined or is a
+ * non- {@code Integer} type, 0 is used.
+ *
+ * <p>
+ * This method should not modify the properties unless the
+ * {@code service.cmRanking} of this plugin is in the range
+ * {@code 0 <= service.cmRanking <= 1000}.
+ * <p>
+ * If this method throws any {@code Exception}, the Configuration Admin
+ * service must catch it and should log it.
+ *
+ * <p>
+ * A Configuration Plugin will only be called for properties from
+ * configurations that have a location for which the Configuration Plugin
+ * has permission when security is active. When security is not active, no
+ * filtering is done.
+ *
+ * @param reference reference to the Managed Service or Managed Service
+ * Factory
+ * @param properties The configuration properties. This argument must not
+ * contain the "service.bundleLocation" property. The value of this
+ * property may be obtained from the
+ * {@code Configuration.getBundleLocation} method.
+ */
+ public void modifyConfiguration(ServiceReference<?> reference, Dictionary<String, Object> properties);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedService.java
new file mode 100644
index 000000000..a4905c472
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedService.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.cm;
+
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * A service that can receive configuration data from a Configuration Admin
+ * service.
+ *
+ * <p>
+ * A Managed Service is a service that needs configuration data. Such an object
+ * should be registered with the Framework registry with the {@code service.pid}
+ * property set to some unique identifier called a PID.
+ *
+ * <p>
+ * If the Configuration Admin service has a {@code Configuration} object
+ * corresponding to this PID, it will callback the {@code updated()} method of
+ * the {@code ManagedService} object, passing the properties of that
+ * {@code Configuration} object.
+ *
+ * <p>
+ * If it has no such {@code Configuration} object, then it calls back with a
+ * {@code null} properties argument. Registering a Managed Service will always
+ * result in a callback to the {@code updated()} method provided the
+ * Configuration Admin service is, or becomes active. This callback must always
+ * be done asynchronously.
+ *
+ * <p>
+ * Else, every time that either of the {@code updated()} methods is called on
+ * that {@code Configuration} object, the {@code ManagedService.updated()}
+ * method with the new properties is called. If the {@code delete()} method is
+ * called on that {@code Configuration} object, {@code ManagedService.updated()}
+ * is called with a {@code null} for the properties parameter. All these
+ * callbacks must be done asynchronously.
+ *
+ * <p>
+ * The following example shows the code of a serial port that will create a port
+ * depending on configuration information.
+ *
+ * <pre>
+ *
+ * class SerialPort implements ManagedService {
+ *
+ * ServiceRegistration registration;
+ * Hashtable configuration;
+ * CommPortIdentifier id;
+ *
+ * synchronized void open(CommPortIdentifier id,
+ * BundleContext context) {
+ * this.id = id;
+ * registration = context.registerService(
+ * ManagedService.class.getName(),
+ * this,
+ * getDefaults()
+ * );
+ * }
+ *
+ * Hashtable getDefaults() {
+ * Hashtable defaults = new Hashtable();
+ * defaults.put( &quot;port&quot;, id.getName() );
+ * defaults.put( &quot;product&quot;, &quot;unknown&quot; );
+ * defaults.put( &quot;baud&quot;, &quot;9600&quot; );
+ * defaults.put( Constants.SERVICE_PID,
+ * &quot;com.acme.serialport.&quot; + id.getName() );
+ * return defaults;
+ * }
+ *
+ * public synchronized void updated(
+ * Dictionary configuration ) {
+ * if ( configuration == null )
+ * registration.setProperties( getDefaults() );
+ * else {
+ * setSpeed( configuration.get(&quot;baud&quot;) );
+ * registration.setProperties( configuration );
+ * }
+ * }
+ * ...
+ * }
+ *
+ * </pre>
+ *
+ * <p>
+ * As a convention, it is recommended that when a Managed Service is updated, it
+ * should copy all the properties it does not recognize into the service
+ * registration properties. This will allow the Configuration Admin service to
+ * set properties on services which can then be used by other applications.
+ *
+ * <p>
+ * Normally, a single Managed Service for a given PID is given the configuration
+ * dictionary, this is the configuration that is bound to the location of the
+ * registering bundle. However, when security is on, a Managed Service can have
+ * Configuration Permission to also be updated for other locations.
+ *
+ * @author $Id$
+ */
+@ConsumerType
+public interface ManagedService {
+ /**
+ * Update the configuration for a Managed Service.
+ *
+ * <p>
+ * When the implementation of {@code updated(Dictionary)} detects any kind
+ * of error in the configuration properties, it should create a new
+ * {@code ConfigurationException} which describes the problem. This can
+ * allow a management system to provide useful information to a human
+ * administrator.
+ *
+ * <p>
+ * If this method throws any other {@code Exception}, the Configuration
+ * Admin service must catch it and should log it.
+ * <p>
+ * The Configuration Admin service must call this method asynchronously with
+ * the method that initiated the callback. This implies that implementors of
+ * Managed Service can be assured that the callback will not take place
+ * during registration when they execute the registration in a synchronized
+ * method.
+ *
+ * <p>
+ * If the the location allows multiple managed services to be called back
+ * for a single configuration then the callbacks must occur in service
+ * ranking order. Changes in the location must be reflected by deleting the
+ * configuration if the configuration is no longer visible and updating when
+ * it becomes visible.
+ *
+ * <p>
+ * If no configuration exists for the corresponding PID, or the bundle has
+ * no access to the configuration, then the bundle must be called back with
+ * a {@code null} to signal that CM is active but there is no data.
+ *
+ * @param properties A copy of the Configuration properties, or {@code null}
+ * . This argument must not contain the "service.bundleLocation"
+ * property. The value of this property may be obtained from the
+ * {@code Configuration.getBundleLocation} method.
+ * @throws ConfigurationException when the update fails
+ * @security ConfigurationPermission[c.location,TARGET] Required by the
+ * bundle that registered this service
+ */
+ public void updated(Dictionary<String, ?> properties) throws ConfigurationException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedServiceFactory.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedServiceFactory.java
new file mode 100644
index 000000000..e1d53892f
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/ManagedServiceFactory.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.cm;
+
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Manage multiple service instances.
+ *
+ * Bundles registering this interface are giving the Configuration Admin service
+ * the ability to create and configure a number of instances of a service that
+ * the implementing bundle can provide. For example, a bundle implementing a
+ * DHCP server could be instantiated multiple times for different interfaces
+ * using a factory.
+ *
+ * <p>
+ * Each of these <i>service instances </i> is represented, in the persistent
+ * storage of the Configuration Admin service, by a factory
+ * {@code Configuration} object that has a PID. When such a
+ * {@code Configuration} is updated, the Configuration Admin service calls the
+ * {@code ManagedServiceFactory} updated method with the new properties. When
+ * {@code updated} is called with a new PID, the Managed Service Factory should
+ * create a new factory instance based on these configuration properties. When
+ * called with a PID that it has seen before, it should update that existing
+ * service instance with the new configuration information.
+ *
+ * <p>
+ * In general it is expected that the implementation of this interface will
+ * maintain a data structure that maps PIDs to the factory instances that it has
+ * created. The semantics of a factory instance are defined by the Managed
+ * Service Factory. However, if the factory instance is registered as a service
+ * object with the service registry, its PID should match the PID of the
+ * corresponding {@code Configuration} object (but it should <b>not </b> be
+ * registered as a Managed Service!).
+ *
+ * <p>
+ * An example that demonstrates the use of a factory. It will create serial
+ * ports under command of the Configuration Admin service.
+ *
+ * <pre>
+ *
+ * class SerialPortFactory
+ * implements ManagedServiceFactory {
+ * ServiceRegistration registration;
+ * Hashtable ports;
+ * void start(BundleContext context) {
+ * Hashtable properties = new Hashtable();
+ * properties.put( Constants.SERVICE_PID,
+ * &quot;com.acme.serialportfactory&quot; );
+ * registration = context.registerService(
+ * ManagedServiceFactory.class.getName(),
+ * this,
+ * properties
+ * );
+ * }
+ * public void updated( String pid,
+ * Dictionary properties ) {
+ * String portName = (String) properties.get(&quot;port&quot;);
+ * SerialPortService port =
+ * (SerialPort) ports.get( pid );
+ * if ( port == null ) {
+ * port = new SerialPortService();
+ * ports.put( pid, port );
+ * port.open();
+ * }
+ * if ( port.getPortName().equals(portName) )
+ * return;
+ * port.setPortName( portName );
+ * }
+ * public void deleted( String pid ) {
+ * SerialPortService port =
+ * (SerialPort) ports.get( pid );
+ * port.close();
+ * ports.remove( pid );
+ * }
+ * ...
+ * }
+ *
+ * </pre>
+ *
+ * @author $Id$
+ */
+@ConsumerType
+public interface ManagedServiceFactory {
+ /**
+ * Return a descriptive name of this factory.
+ *
+ * @return the name for the factory, which might be localized
+ */
+ public String getName();
+
+ /**
+ * Create a new instance, or update the configuration of an existing
+ * instance.
+ *
+ * If the PID of the {@code Configuration} object is new for the Managed
+ * Service Factory, then create a new factory instance, using the
+ * configuration {@code properties} provided. Else, update the service
+ * instance with the provided {@code properties}.
+ *
+ * <p>
+ * If the factory instance is registered with the Framework, then the
+ * configuration {@code properties} should be copied to its registry
+ * properties. This is not mandatory and security sensitive properties
+ * should obviously not be copied.
+ *
+ * <p>
+ * If this method throws any {@code Exception}, the Configuration Admin
+ * service must catch it and should log it.
+ *
+ * <p>
+ * When the implementation of updated detects any kind of error in the
+ * configuration properties, it should create a new
+ * {@link ConfigurationException} which describes the problem.
+ *
+ * <p>
+ * The Configuration Admin service must call this method asynchronously.
+ * This implies that implementors of the {@code ManagedServiceFactory} class
+ * can be assured that the callback will not take place during registration
+ * when they execute the registration in a synchronized method.
+ *
+ * <p>
+ * If the security allows multiple managed service factories to be called
+ * back for a single configuration then the callbacks must occur in service
+ * ranking order.
+ *
+ * <p>
+ * It is valid to create multiple factory instances that are bound to
+ * different locations. Managed Service Factory services must only be
+ * updated with configurations that are bound to their location or that
+ * start with the {@code ?} prefix and for which they have permission.
+ * Changes in the location must be reflected by deleting the corresponding
+ * configuration if the configuration is no longer visible or updating when
+ * it becomes visible.
+ *
+ * @param pid The PID for this configuration.
+ * @param properties A copy of the configuration properties. This argument
+ * must not contain the service.bundleLocation" property. The value
+ * of this property may be obtained from the
+ * {@code Configuration.getBundleLocation} method.
+ * @throws ConfigurationException when the configuration properties are
+ * invalid.
+ * @security ConfigurationPermission[c.location,TARGET] Required by the
+ * bundle that registered this service
+ */
+ public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException;
+
+ /**
+ * Remove a factory instance.
+ *
+ * Remove the factory instance associated with the PID. If the instance was
+ * registered with the service registry, it should be unregistered. The
+ * Configuration Admin must call deleted for each instance it received in
+ * {@link #updated(String, Dictionary)}.
+ *
+ * <p>
+ * If this method throws any {@code Exception}, the Configuration Admin
+ * service must catch it and should log it.
+ * <p>
+ * The Configuration Admin service must call this method asynchronously.
+ *
+ * @param pid the PID of the service to be removed
+ */
+ public void deleted(String pid);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/SynchronousConfigurationListener.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/SynchronousConfigurationListener.java
new file mode 100644
index 000000000..bcd2b68aa
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/SynchronousConfigurationListener.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2013). 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.cm;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Synchronous Listener for Configuration Events. When a
+ * {@code ConfigurationEvent} is fired, it is synchronously delivered to a
+ * {@code SynchronousConfigurationListener}.
+ *
+ * <p>
+ * {@code SynchronousConfigurationListener} objects are registered with the
+ * Framework service registry and are synchronously notified with a
+ * {@code ConfigurationEvent} object when an event is fired.
+ * <p>
+ * {@code SynchronousConfigurationListener} objects can inspect the received
+ * {@code ConfigurationEvent} object to determine its type, the PID of the
+ * {@code Configuration} object with which it is associated, and the
+ * Configuration Admin service that fired the event.
+ *
+ * <p>
+ * Security Considerations. Bundles wishing to synchronously monitor
+ * configuration events will require
+ * {@code ServicePermission[SynchronousConfigurationListener,REGISTER]} to
+ * register a {@code SynchronousConfigurationListener} service.
+ *
+ * @author $Id$
+ * @since 1.5
+ */
+@ConsumerType
+public interface SynchronousConfigurationListener extends ConfigurationListener {
+ // Marker interface
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/package-info.java
new file mode 100644
index 000000000..f83587772
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Configuration Admin Package Version 1.5.
+ *
+ * <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.cm; version="[1.5,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.cm; version="[1.5,1.6)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.5")
+package org.osgi.service.cm;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/packageinfo
new file mode 100644
index 000000000..ccee95e92
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/cm/packageinfo
@@ -0,0 +1 @@
+version 1.5
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java
new file mode 100644
index 000000000..ac753054f
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.component;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Defines standard names for Service Component constants.
+ *
+ * @author $Id$
+ */
+@ProviderType
+public interface ComponentConstants {
+ /**
+ * Manifest header specifying the XML documents within a bundle that contain
+ * the bundle's Service Component descriptions.
+ * <p>
+ * The attribute value may be retrieved from the {@code Dictionary} object
+ * returned by the {@code Bundle.getHeaders} method.
+ */
+ public static final String SERVICE_COMPONENT = "Service-Component";
+
+ /**
+ * A component property for a component configuration that contains the name
+ * of the component as specified in the {@code name} attribute of the
+ * {@code component} element. The value of this property must be of type
+ * {@code String}.
+ */
+ public final static String COMPONENT_NAME = "component.name";
+
+ /**
+ * A component property that contains the generated id for a component
+ * configuration. The value of this property must be of type {@code Long}.
+ *
+ * <p>
+ * The value of this property is assigned by the Service Component Runtime
+ * when a component configuration is created. The Service Component Runtime
+ * assigns a unique value that is larger than all previously assigned values
+ * since the Service Component Runtime was started. These values are NOT
+ * persistent across restarts of the Service Component Runtime.
+ */
+ public final static String COMPONENT_ID = "component.id";
+
+ /**
+ * A service registration property for a Component Factory that contains the
+ * value of the {@code factory} attribute. The value of this property must
+ * be of type {@code String}.
+ */
+ public final static String COMPONENT_FACTORY = "component.factory";
+
+ /**
+ * The suffix for reference target properties. These properties contain the
+ * filter to select the target services for a reference. The value of this
+ * property must be of type {@code String}.
+ */
+ public final static String REFERENCE_TARGET_SUFFIX = ".target";
+
+ /**
+ * The reason the component configuration was deactivated is unspecified.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_UNSPECIFIED = 0;
+
+ /**
+ * The component configuration was deactivated because the component was
+ * disabled.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_DISABLED = 1;
+
+ /**
+ * The component configuration was deactivated because a reference became
+ * unsatisfied.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_REFERENCE = 2;
+
+ /**
+ * The component configuration was deactivated because its configuration was
+ * changed.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_CONFIGURATION_MODIFIED = 3;
+
+ /**
+ * The component configuration was deactivated because its configuration was
+ * deleted.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_CONFIGURATION_DELETED = 4;
+
+ /**
+ * The component configuration was deactivated because the component was
+ * disposed.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_DISPOSED = 5;
+
+ /**
+ * The component configuration was deactivated because the bundle was
+ * stopped.
+ *
+ * @since 1.1
+ */
+ public static final int DEACTIVATION_REASON_BUNDLE_STOPPED = 6;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java
new file mode 100644
index 000000000..9855c2af8
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.component;
+
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A Component Context object is used by a component instance to interact with
+ * its execution context including locating services by reference name. Each
+ * component instance has a unique Component Context.
+ *
+ * <p>
+ * A component instance may have an activate method. If a component instance has
+ * a suitable and accessible activate method, this method will be called when a
+ * component configuration is activated. If the activate method takes a
+ * {@code ComponentContext} argument, it will be passed the component instance's
+ * Component Context object. If the activate method takes a
+ * {@code BundleContext} argument, it will be passed the component instance's
+ * Bundle Context object. If the activate method takes a {@code Map} argument,
+ * it will be passed an unmodifiable Map containing the component properties.
+ *
+ * <p>
+ * A component instance may have a deactivate method. If a component instance
+ * has a suitable and accessible deactivate method, this method will be called
+ * when the component configuration is deactivated. If the deactivate method
+ * takes a {@code ComponentContext} argument, it will be passed the component
+ * instance's Component Context object. If the deactivate method takes a
+ * {@code BundleContext} argument, it will be passed the component instance's
+ * Bundle Context object. If the deactivate method takes a {@code Map} argument,
+ * it will be passed an unmodifiable Map containing the component properties. If
+ * the deactivate method takes an {@code int} or {@code Integer} argument, it
+ * will be passed the reason code for the component instance's deactivation.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface ComponentContext {
+ /**
+ * Returns the component properties for this Component Context.
+ *
+ * @return The properties for this Component Context. The Dictionary is read
+ * only and cannot be modified.
+ */
+ public Dictionary<String, Object> getProperties();
+
+ /**
+ * Returns the service object for the specified reference name.
+ *
+ * <p>
+ * If the cardinality of the reference is {@code 0..n} or {@code 1..n} and
+ * multiple services are bound to the reference, the service with the
+ * highest ranking (as specified in its {@code Constants.SERVICE_RANKING}
+ * property) is returned. If there is a tie in ranking, the service with the
+ * lowest service ID (as specified in its {@code Constants.SERVICE_ID}
+ * property); that is, the service that was registered first is returned.
+ *
+ * @param name The name of a reference as specified in a {@code reference}
+ * element in this component's description.
+ * @return A service object for the referenced service or {@code null} if
+ * the reference cardinality is {@code 0..1} or {@code 0..n} and no
+ * bound service is available.
+ * @throws ComponentException If the Service Component Runtime catches an
+ * exception while activating the bound service.
+ */
+ public Object locateService(String name);
+
+ /**
+ * Returns the service object for the specified reference name and
+ * {@code ServiceReference}.
+ *
+ * @param name The name of a reference as specified in a {@code reference}
+ * element in this component's description.
+ * @param reference The {@code ServiceReference} to a bound service. This
+ * must be a {@code ServiceReference} provided to the component via
+ * the bind or unbind method for the specified reference name.
+ * @return A service object for the referenced service or {@code null} if
+ * the specified {@code ServiceReference} is not a bound service for
+ * the specified reference name.
+ * @throws ComponentException If the Service Component Runtime catches an
+ * exception while activating the bound service.
+ */
+ public Object locateService(String name, ServiceReference<?> reference);
+
+ /**
+ * Returns the service objects for the specified reference name.
+ *
+ * @param name The name of a reference as specified in a {@code reference}
+ * element in this component's description.
+ * @return An array of service objects for the referenced service or
+ * {@code null} if the reference cardinality is {@code 0..1} or
+ * {@code 0..n} and no bound service is available. If the reference
+ * cardinality is {@code 0..1} or {@code 1..1} and a bound service
+ * is available, the array will have exactly one element.
+ * @throws ComponentException If the Service Component Runtime catches an
+ * exception while activating a bound service.
+ */
+ public Object[] locateServices(String name);
+
+ /**
+ * Returns the {@code BundleContext} of the bundle which contains this
+ * component.
+ *
+ * @return The {@code BundleContext} of the bundle containing this
+ * component.
+ */
+ public BundleContext getBundleContext();
+
+ /**
+ * If the component instance is registered as a service using the
+ * {@code servicefactory="true"} attribute, then this method returns the
+ * bundle using the service provided by the component instance.
+ * <p>
+ * This method will return {@code null} if:
+ * <ul>
+ * <li>The component instance is not a service, then no bundle can be using
+ * it as a service.</li>
+ * <li>The component instance is a service but did not specify the
+ * {@code servicefactory="true"} attribute, then all bundles using the
+ * service provided by the component instance will share the same component
+ * instance.</li>
+ * <li>The service provided by the component instance is not currently being
+ * used by any bundle.</li>
+ * </ul>
+ *
+ * @return The bundle using the component instance as a service or
+ * {@code null}.
+ */
+ public Bundle getUsingBundle();
+
+ /**
+ * Returns the Component Instance object for the component instance
+ * associated with this Component Context.
+ *
+ * @return The Component Instance object for the component instance.
+ */
+ public ComponentInstance getComponentInstance();
+
+ /**
+ * Enables the specified component name. The specified component name must
+ * be in the same bundle as this component.
+ *
+ * @param name The name of a component or {@code null} to indicate all
+ * components in the bundle.
+ */
+ public void enableComponent(String name);
+
+ /**
+ * Disables the specified component name. The specified component name must
+ * be in the same bundle as this component.
+ *
+ * @param name The name of a component.
+ */
+ public void disableComponent(String name);
+
+ /**
+ * If the component instance is registered as a service using the
+ * {@code service} element, then this method returns the service reference
+ * of the service provided by this component instance.
+ * <p>
+ * This method will return {@code null} if the component instance is not
+ * registered as a service.
+ *
+ * @return The {@code ServiceReference} object for the component instance or
+ * {@code null} if the component instance is not registered as a
+ * service.
+ */
+ public ServiceReference<?> getServiceReference();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java
new file mode 100644
index 000000000..9ec6a42f2
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.component;
+
+/**
+ * Unchecked exception which may be thrown by the Service Component Runtime.
+ *
+ * @author $Id$
+ */
+public class ComponentException extends RuntimeException {
+ static final long serialVersionUID = -7438212656298726924L;
+
+ /**
+ * Construct a new ComponentException with the specified message and cause.
+ *
+ * @param message The message for the exception.
+ * @param cause The cause of the exception. May be {@code null}.
+ */
+ public ComponentException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Construct a new ComponentException with the specified message.
+ *
+ * @param message The message for the exception.
+ */
+ public ComponentException(String message) {
+ super(message);
+ }
+
+ /**
+ * Construct a new ComponentException with the specified cause.
+ *
+ * @param cause The cause of the exception. May be {@code null}.
+ */
+ public ComponentException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Returns the cause of this exception or {@code null} if no cause was set.
+ *
+ * @return The cause of this exception or {@code null} if no cause was set.
+ */
+ @Override
+ public Throwable getCause() {
+ return super.getCause();
+ }
+
+ /**
+ * Initializes the cause of this exception to the specified value.
+ *
+ * @param cause The cause of this exception.
+ * @return This exception.
+ * @throws IllegalArgumentException If the specified cause is this
+ * exception.
+ * @throws IllegalStateException If the cause of this exception has already
+ * been set.
+ */
+ @Override
+ public Throwable initCause(Throwable cause) {
+ return super.initCause(cause);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java
new file mode 100644
index 000000000..efb1e1695
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.component;
+
+import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * When a component is declared with the {@code factory} attribute on its
+ * {@code component} element, the Service Component Runtime will register a
+ * Component Factory service to allow new component configurations to be created
+ * and activated rather than automatically creating and activating component
+ * configuration as necessary.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface ComponentFactory {
+ /**
+ * Create and activate a new component configuration. Additional properties
+ * may be provided for the component configuration.
+ *
+ * @param properties Additional properties for the component configuration
+ * or {@code null} if there are no additional properties.
+ * @return A {@code ComponentInstance} object encapsulating the component
+ * instance of the component configuration. The component
+ * configuration has been activated and, if the component specifies
+ * a {@code service} element, the component instance has been
+ * registered as a service.
+ * @throws ComponentException If the Service Component Runtime is unable to
+ * activate the component configuration.
+ */
+ public ComponentInstance newInstance(Dictionary<String, ?> properties);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentInstance.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentInstance.java
new file mode 100644
index 000000000..8078babdd
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentInstance.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2013). 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.component;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * A ComponentInstance encapsulates a component instance of an activated
+ * component configuration. ComponentInstances are created whenever a component
+ * configuration is activated.
+ *
+ * <p>
+ * ComponentInstances are never reused. A new ComponentInstance object will be
+ * created when the component configuration is activated again.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface ComponentInstance {
+ /**
+ * Dispose of the component configuration for this component instance. The
+ * component configuration will be deactivated. If the component
+ * configuration has already been deactivated, this method does nothing.
+ */
+ public void dispose();
+
+ /**
+ * Returns the component instance of the activated component configuration.
+ *
+ * @return The component instance or {@code null} if the component
+ * configuration has been deactivated.
+ */
+ public Object getInstance();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java
new file mode 100644
index 000000000..e24a899f7
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identify the annotated method as the {@code activate} method of a Service
+ * Component.
+ *
+ * <p>
+ * The annotated method is the activate method of the Component.
+ *
+ * <p>
+ * This annotation is not processed at runtime by a Service Component Runtime
+ * implementation. It must be processed by tools and used to add a Component
+ * Description to the bundle.
+ *
+ * @see "The activate attribute of the component element of a Component Description."
+ * @author $Id$
+ * @since 1.1
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface Activate {
+ // marker annotation
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java
new file mode 100644
index 000000000..e7f072364
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identify the annotated class as a Service Component.
+ *
+ * <p>
+ * The annotated class is the implementation class of the Component.
+ *
+ * <p>
+ * This annotation is not processed at runtime by a Service Component Runtime
+ * implementation. It must be processed by tools and used to add a Component
+ * Description to the bundle.
+ *
+ * @see "The component element of a Component Description."
+ * @author $Id$
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface Component {
+ /**
+ * The name of this Component.
+ *
+ * <p>
+ * If not specified, the name of this Component is the fully qualified type
+ * name of the class being annotated.
+ *
+ * @see "The name attribute of the component element of a Component Description."
+ */
+ String name() default "";
+
+ /**
+ * The types under which to register this Component as a service.
+ *
+ * <p>
+ * If no service should be registered, the empty value
+ * <code>&#x7B;&#x7D;</code> must be specified.
+ *
+ * <p>
+ * If not specified, the service types for this Component are all the
+ * <i>directly</i> implemented interfaces of the class being annotated.
+ *
+ * @see "The service element of a Component Description."
+ */
+ Class<?>[] service() default {};
+
+ /**
+ * The factory identifier of this Component. Specifying a factory identifier
+ * makes this Component a Factory Component.
+ *
+ * <p>
+ * If not specified, the default is that this Component is not a Factory
+ * Component.
+ *
+ * @see "The factory attribute of the component element of a Component Description."
+ */
+ String factory() default "";
+
+ /**
+ * Declares whether this Component uses the OSGi ServiceFactory concept and
+ * each bundle using this Component's service will receive a different
+ * component instance.
+ *
+ * <p>
+ * If {@code true}, this Component uses the OSGi ServiceFactory concept. If
+ * {@code false} or not specified, this Component does not use the OSGi
+ * ServiceFactory concept.
+ *
+ * @see "The servicefactory attribute of the service element of a Component Description."
+ */
+ boolean servicefactory() default false;
+
+ /**
+ * Declares whether this Component is enabled when the bundle containing it
+ * is started.
+ *
+ * <p>
+ * If {@code true}, this Component is enabled. If {@code false} or not
+ * specified, this Component is disabled.
+ *
+ * @see "The enabled attribute of the component element of a Component Description."
+ */
+ boolean enabled() default true;
+
+ /**
+ * Declares whether this Component must be immediately activated upon
+ * becoming satisfied or whether activation should be delayed.
+ *
+ * <p>
+ * If {@code true}, this Component must be immediately activated upon
+ * becoming satisfied. If {@code false}, activation of this Component is
+ * delayed. If this property is specified, its value must be {@code false}
+ * if the {@link #factory} property is also specified or must be
+ * {@code true} if the {@link #service} property is specified with an empty
+ * value.
+ *
+ * <p>
+ * If not specified, the default is {@code false} if the {@link #factory}
+ * property is specified or the {@link #service} property is not specified
+ * or specified with a non-empty value and {@code true} otherwise.
+ *
+ * @see "The immediate attribute of the component element of a Component Description."
+ */
+ boolean immediate() default false;
+
+ /**
+ * Properties for this Component.
+ *
+ * <p>
+ * Each property string is specified as {@code "key=value"}. The type of the
+ * property value can be specified in the key as {@code key:type=value}. The
+ * type must be one of the property types supported by the type attribute of
+ * the property element of a Component Description.
+ *
+ * <p>
+ * To specify a property with multiple values, use multiple key, value
+ * pairs. For example, {@code "foo=bar", "foo=baz"}.
+ *
+ * @see "The property element of a Component Description."
+ */
+ String[] property() default {};
+
+ /**
+ * Property entries for this Component.
+ *
+ * <p>
+ * Specifies the name of an entry in the bundle whose contents conform to a
+ * standard Java Properties File. The entry is read and processed to obtain
+ * the properties and their values.
+ *
+ * @see "The properties element of a Component Description."
+ */
+ String[] properties() default {};
+
+ /**
+ * The XML name space of the Component Description for this Component.
+ *
+ * <p>
+ * If not specified, the XML name space of the Component Description for
+ * this Component should be the lowest Declarative Services XML name space
+ * which supports all the specification features used by this Component.
+ *
+ * @see "The XML name space specified for a Component Description."
+ */
+ String xmlns() default "";
+
+ /**
+ * The configuration policy of this Component.
+ *
+ * <p>
+ * Controls whether component configurations must be satisfied depending on
+ * the presence of a corresponding Configuration object in the OSGi
+ * Configuration Admin service. A corresponding configuration is a
+ * Configuration object where the PID equals the name of the component.
+ *
+ * <p>
+ * If not specified, the {@link ConfigurationPolicy#OPTIONAL OPTIONAL}
+ * configuration policy is used.
+ *
+ * @see "The configuration-policy attribute of the component element of a Component Description."
+ * @since 1.1
+ */
+ ConfigurationPolicy configurationPolicy() default ConfigurationPolicy.OPTIONAL;
+
+ /**
+ * The configuration PID for the configuration of this Component.
+ *
+ * <p>
+ * Allows the configuration PID for this Component to be different than the
+ * name of this Component.
+ *
+ * <p>
+ * If not specified, the name of this Component is used as the configuration
+ * PID of this Component.
+ *
+ * @see "The configuration-pid attribute of the component element of a Component Description."
+ * @since 1.2
+ */
+ String configurationPid() default "";
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ConfigurationPolicy.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ConfigurationPolicy.java
new file mode 100644
index 000000000..2bb2640ae
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ConfigurationPolicy.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+/**
+ * Configuration Policy for the {@link Component} annotation.
+ *
+ * <p>
+ * Controls whether component configurations must be satisfied depending on the
+ * presence of a corresponding Configuration object in the OSGi Configuration
+ * Admin service. A corresponding configuration is a Configuration object where
+ * the PID is the name of the component.
+ *
+ * @author $Id$
+ * @since 1.1
+ */
+public enum ConfigurationPolicy {
+ /**
+ * Use the corresponding Configuration object if present but allow the
+ * component to be satisfied even if the corresponding Configuration object
+ * is not present.
+ */
+ OPTIONAL("optional"),
+
+ /**
+ * There must be a corresponding Configuration object for the component
+ * configuration to become satisfied.
+ */
+ REQUIRE("require"),
+
+ /**
+ * Always allow the component configuration to be satisfied and do not use
+ * the corresponding Configuration object even if it is present.
+ */
+ IGNORE("ignore");
+
+ private final String value;
+
+ ConfigurationPolicy(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java
new file mode 100644
index 000000000..1809c70eb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identify the annotated method as the {@code deactivate} method of a Service
+ * Component.
+ *
+ * <p>
+ * The annotated method is the deactivate method of the Component.
+ *
+ * <p>
+ * This annotation is not processed at runtime by a Service Component Runtime
+ * implementation. It must be processed by tools and used to add a Component
+ * Description to the bundle.
+ *
+ * @see "The deactivate attribute of the component element of a Component Description."
+ * @author $Id$
+ * @since 1.1
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface Deactivate {
+ // marker annotation
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java
new file mode 100644
index 000000000..fd9f97d2f
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identify the annotated method as the {@code modified} method of a Service
+ * Component.
+ *
+ * <p>
+ * The annotated method is the modified method of the Component.
+ *
+ * <p>
+ * This annotation is not processed at runtime by a Service Component Runtime
+ * implementation. It must be processed by tools and used to add a Component
+ * Description to the bundle.
+ *
+ * @see "The modified attribute of the component element of a Component Description."
+ * @author $Id$
+ * @since 1.1
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface Modified {
+ // marker annotation
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java
new file mode 100644
index 000000000..9887c51c7
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identify the annotated method as a {@code bind} method of a Service
+ * Component.
+ *
+ * <p>
+ * The annotated method is a bind method of the Component.
+ *
+ * <p>
+ * This annotation is not processed at runtime by a Service Component Runtime
+ * implementation. It must be processed by tools and used to add a Component
+ * Description to the bundle.
+ *
+ * <p>
+ * In the generated Component Description for a component, the references must
+ * be ordered in ascending lexicographical order (using {@code String.compareTo}
+ * ) of the reference {@link #name() name}s.
+ *
+ * @see "The reference element of a Component Description."
+ * @author $Id$
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface Reference {
+ /**
+ * The name of this reference.
+ *
+ * <p>
+ * If not specified, the name of this reference is based upon the name of
+ * the method being annotated. If the method name begins with {@code bind},
+ * {@code set} or {@code add}, that is removed.
+ *
+ * @see "The name attribute of the reference element of a Component Description."
+ */
+ String name() default "";
+
+ /**
+ * The type of the service to bind to this reference.
+ *
+ * <p>
+ * If not specified, the type of the service to bind is based upon the type
+ * of the first argument of the method being annotated.
+ *
+ * @see "The interface attribute of the reference element of a Component Description."
+ */
+ Class<?> service() default Object.class;
+
+ /**
+ * The cardinality of the reference.
+ *
+ * <p>
+ * If not specified, the reference has a
+ * {@link ReferenceCardinality#MANDATORY 1..1} cardinality.
+ *
+ * @see "The cardinality attribute of the reference element of a Component Description."
+ */
+ ReferenceCardinality cardinality() default ReferenceCardinality.MANDATORY;
+
+ /**
+ * The policy for the reference.
+ *
+ * <p>
+ * If not specified, the {@link ReferencePolicy#STATIC STATIC} reference
+ * policy is used.
+ *
+ * @see "The policy attribute of the reference element of a Component Description."
+ */
+ ReferencePolicy policy() default ReferencePolicy.STATIC;
+
+ /**
+ * The target filter for the reference.
+ *
+ * @see "The target attribute of the reference element of a Component Description."
+ */
+ String target() default "";
+
+ /**
+ * The name of the unbind method which is associated with the annotated bind
+ * method.
+ *
+ * <p>
+ * To declare no unbind method, the value {@code "-"} must be used.
+ *
+ * <p>
+ * If not specified, the name of the unbind method is derived from the name
+ * of the annotated bind method. If the annotated method name begins with
+ * {@code bind}, {@code set} or {@code add}, that is replaced with
+ * {@code unbind}, {@code unset} or {@code remove}, respectively, to derive
+ * the unbind method name. Otherwise, {@code un} is prefixed to the
+ * annotated method name to derive the unbind method name. The unbind method
+ * is only set if the component type contains a method with the derived
+ * name.
+ *
+ * @see "The unbind attribute of the reference element of a Component Description."
+ */
+ String unbind() default "";
+
+ /**
+ * The policy option for the reference.
+ *
+ * <p>
+ * If not specified, the {@link ReferencePolicyOption#RELUCTANT RELUCTANT}
+ * reference policy option is used.
+ *
+ * @see "The policy-option attribute of the reference element of a Component Description."
+ * @since 1.2
+ */
+ ReferencePolicyOption policyOption() default ReferencePolicyOption.RELUCTANT;
+
+ /**
+ * The name of the updated method which is associated with the annotated
+ * bind method.
+ *
+ * <p>
+ * To declare no updated method, the value {@code "-"} must be used.
+ *
+ * <p>
+ * If not specified, the name of the updated method is derived from the name
+ * of the annotated bind method. If the annotated method name begins with
+ * {@code bind}, {@code set} or {@code add}, that is replaced with
+ * {@code updated} to derive the updated method name. Otherwise,
+ * {@code updated} is prefixed to the annotated method name to derive the
+ * updated method name. The updated method is only set if the component type
+ * contains a method with the derived name.
+ *
+ * @see "The updated attribute of the reference element of a Component Description."
+ * @since 1.2
+ */
+ String updated() default "";
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceCardinality.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceCardinality.java
new file mode 100644
index 000000000..f01a55c3e
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceCardinality.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+/**
+ * Cardinality for the {@link Reference} annotation.
+ *
+ * <p>
+ * Specifies if the reference is optional and if the component implementation
+ * support a single bound service or multiple bound services.
+ *
+ * @author $Id$
+ */
+public enum ReferenceCardinality {
+ /**
+ * The reference is optional and unary. That is, the reference has a
+ * cardinality of {@code 0..1}.
+ */
+ OPTIONAL("0..1"),
+
+ /**
+ * The reference is mandatory and unary. That is, the reference has a
+ * cardinality of {@code 1..1}.
+ */
+ MANDATORY("1..1"),
+
+ /**
+ * The reference is optional and multiple. That is, the reference has a
+ * cardinality of {@code 0..n}.
+ */
+ MULTIPLE("0..n"),
+
+ /**
+ * The reference is mandatory and multiple. That is, the reference has a
+ * cardinality of {@code 1..n}.
+ */
+ AT_LEAST_ONE("1..n");
+
+ private final String value;
+
+ ReferenceCardinality(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicy.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicy.java
new file mode 100644
index 000000000..835125670
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicy.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+/**
+ * Policy for the {@link Reference} annotation.
+ *
+ * @author $Id$
+ */
+public enum ReferencePolicy {
+ /**
+ * The static policy is the most simple policy and is the default policy. A
+ * component instance never sees any of the dynamics. Component
+ * configurations are deactivated before any bound service for a reference
+ * having a static policy becomes unavailable. If a target service is
+ * available to replace the bound service which became unavailable, the
+ * component configuration must be reactivated and bound to the replacement
+ * service.
+ */
+ STATIC("static"),
+
+ /**
+ * The dynamic policy is slightly more complex since the component
+ * implementation must properly handle changes in the set of bound services.
+ * With the dynamic policy, SCR can change the set of bound services without
+ * deactivating a component configuration. If the component uses the event
+ * strategy to access services, then the component instance will be notified
+ * of changes in the set of bound services by calls to the bind and unbind
+ * methods.
+ */
+ DYNAMIC("dynamic");
+
+ private final String value;
+
+ ReferencePolicy(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicyOption.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicyOption.java
new file mode 100644
index 000000000..1023cb41a
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferencePolicyOption.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.component.annotations;
+
+/**
+ * Policy option for the {@link Reference} annotation.
+ *
+ * @author $Id$
+ * @since 1.2
+ */
+public enum ReferencePolicyOption {
+ /**
+ * The reluctant policy option is the default policy option for both
+ * {@link ReferencePolicy#STATIC static} and {@link ReferencePolicy#DYNAMIC
+ * dynamic} reference policies. When a new target service for a reference
+ * becomes available, references having the reluctant policy option for the
+ * static policy or the dynamic policy with a unary cardinality will ignore
+ * the new target service. References having the dynamic policy with a
+ * multiple cardinality will bind the new target service.
+ */
+ RELUCTANT("reluctant"),
+
+ /**
+ * The greedy policy option is a valid policy option for both
+ * {@link ReferencePolicy#STATIC static} and {@link ReferencePolicy#DYNAMIC
+ * dynamic} reference policies. When a new target service for a reference
+ * becomes available, references having the greedy policy option will bind
+ * the new target service.
+ */
+ GREEDY("greedy");
+
+ private final String value;
+
+ ReferencePolicyOption(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java
new file mode 100644
index 000000000..dbfa48a1b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.
+ */
+
+/**
+ * Service Component Annotations Package Version 1.2.
+ *
+ * <p>
+ * This package is not used at runtime. Annotated classes are processed by
+ * tools to generate Component Descriptions which are used at runtime.
+ *
+ * @author $Id$
+ */
+
+@Version("1.2")
+package org.osgi.service.component.annotations;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo
new file mode 100644
index 000000000..ef7df68cb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java
new file mode 100644
index 000000000..4b472f45b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Service Component Package Version 1.2.
+ *
+ * <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.component; version="[1.2,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component; version="[1.2,1.3)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.2.2")
+package org.osgi.service.component;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo
new file mode 100644
index 000000000..19727573b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo
@@ -0,0 +1 @@
+version 1.2.2
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Constants.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Constants.java
new file mode 100644
index 000000000..967b949d6
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Constants.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.device;
+
+/**
+ * This interface defines standard names for property keys associated with
+ * {@link Device} and {@link Driver} services.
+ *
+ * <p>
+ * The values associated with these keys are of type {@code java.lang.String},
+ * unless otherwise stated.
+ *
+ * @noimplement
+ * @author $Id$
+ * @since 1.1
+ * @see Device
+ * @see Driver
+ */
+public interface Constants {
+ /**
+ * Property (named &quot;DRIVER_ID&quot;) identifying a driver.
+ *
+ * <p>
+ * A {@code DRIVER_ID} should start with the reversed domain name of the
+ * company that implemented the driver (e.g., {@code com.acme}), and must
+ * meet the following requirements:
+ *
+ * <ul>
+ * <li>It must be independent of the location from where it is obtained.</li>
+ * <li>It must be independent of the {@link DriverLocator} service that
+ * downloaded it.</li>
+ * <li>It must be unique.</li>
+ * <li>It must be different for different revisions of the same driver.</li>
+ * </ul>
+ *
+ * <p>
+ * This property is mandatory, i.e., every {@code Driver} service must be
+ * registered with it.
+ */
+ public static final String DRIVER_ID = "DRIVER_ID";
+ /**
+ * Property (named &quot;DEVICE_CATEGORY&quot;) containing a human readable
+ * description of the device categories implemented by a device. This
+ * property is of type {@code String[]}
+ *
+ * <p>
+ * Services registered with this property will be treated as devices and
+ * discovered by the device manager
+ */
+ public static final String DEVICE_CATEGORY = "DEVICE_CATEGORY";
+ /**
+ * Property (named &quot;DEVICE_SERIAL&quot;) specifying a device's serial
+ * number.
+ */
+ public static final String DEVICE_SERIAL = "DEVICE_SERIAL";
+ /**
+ * Property (named &quot;DEVICE_DESCRIPTION&quot;) containing a human
+ * readable string describing the actual hardware device.
+ */
+ public static final String DEVICE_DESCRIPTION = "DEVICE_DESCRIPTION";
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Device.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Device.java
new file mode 100644
index 000000000..a3f26e7ec
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Device.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.device;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * <p>
+ * Interface for identifying device services.
+ *
+ * <p>
+ * A service must implement this interface or use the
+ * {@link Constants#DEVICE_CATEGORY} registration property to indicate that it
+ * is a device. Any services implementing this interface or registered with the
+ * {@code DEVICE_CATEGORY} property will be discovered by the device manager.
+ *
+ * <p>
+ * Device services implementing this interface give the device manager the
+ * opportunity to indicate to the device that no drivers were found that could
+ * (further) refine it. In this case, the device manager calls the
+ * {@link #noDriverFound()} method on the {@code Device} object.
+ *
+ * <p>
+ * Specialized device implementations will extend this interface by adding
+ * methods appropriate to their device category to it.
+ *
+ * @author $Id$
+ * @see Driver
+ * @ThreadSafe
+ */
+public interface Device {
+ /**
+ * Return value from {@link Driver#match(ServiceReference)} indicating that
+ * the driver cannot refine the device presented to it by the device
+ * manager.
+ *
+ * The value is zero.
+ */
+ public static final int MATCH_NONE = 0;
+
+ /**
+ * Indicates to this {@code Device} object that the device manager has
+ * failed to attach any drivers to it.
+ *
+ * <p>
+ * If this {@code Device} object can be configured differently, the driver
+ * that registered this {@code Device} object may unregister it and register
+ * a different Device service instead.
+ */
+ public void noDriverFound();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Driver.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Driver.java
new file mode 100644
index 000000000..db46dfadf
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Driver.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.device;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A {@code Driver} service object must be registered by each Driver bundle
+ * wishing to attach to Device services provided by other drivers. For each
+ * newly discovered {@link Device} object, the device manager enters a bidding
+ * phase. The {@code Driver} object whose {@link #match(ServiceReference)}
+ * method bids the highest for a particular {@code Device} object will be
+ * instructed by the device manager to attach to the {@code Device} object.
+ *
+ * @author $Id$
+ * @see Device
+ * @see DriverLocator
+ * @ThreadSafe
+ */
+public interface Driver {
+ /**
+ * Checks whether this Driver service can be attached to the Device service.
+ *
+ * The Device service is represented by the given {@link ServiceReference}
+ * and returns a value indicating how well this driver can support the given
+ * Device service, or {@link Device#MATCH_NONE} if it cannot support the
+ * given Device service at all.
+ *
+ * <p>
+ * The return value must be one of the possible match values defined in the
+ * device category definition for the given Device service, or
+ * {@code Device.MATCH_NONE} if the category of the Device service is not
+ * recognized.
+ *
+ * <p>
+ * In order to make its decision, this Driver service may examine the
+ * properties associated with the given Device service, or may get the
+ * referenced service object (representing the actual physical device) to
+ * talk to it, as long as it ungets the service and returns the physical
+ * device to a normal state before this method returns.
+ *
+ * <p>
+ * A Driver service must always return the same match code whenever it is
+ * presented with the same Device service.
+ *
+ * <p>
+ * The match function is called by the device manager during the matching
+ * process.
+ *
+ * @param reference the {@code ServiceReference} object of the device to
+ * match
+ *
+ * @return value indicating how well this driver can support the given
+ * Device service, or {@code Device.MATCH_NONE} if it cannot support
+ * the Device service at all
+ *
+ * @throws java.lang.Exception if this Driver service cannot examine the
+ * Device service
+ */
+ public int match(ServiceReference reference) throws Exception;
+
+ /**
+ * Attaches this Driver service to the Device service represented by the
+ * given {@code ServiceReference} object.
+ *
+ * <p>
+ * A return value of {@code null} indicates that this Driver service has
+ * successfully attached to the given Device service. If this Driver service
+ * is unable to attach to the given Device service, but knows of a more
+ * suitable Driver service, it must return the {@code DRIVER_ID} of that
+ * Driver service. This allows for the implementation of referring drivers
+ * whose only purpose is to refer to other drivers capable of handling a
+ * given Device service.
+ *
+ * <p>
+ * After having attached to the Device service, this driver may register the
+ * underlying device as a new service exposing driver-specific
+ * functionality.
+ *
+ * <p>
+ * This method is called by the device manager.
+ *
+ * @param reference the {@code ServiceReference} object of the device to
+ * attach to
+ *
+ * @return {@code null} if this Driver service has successfully attached to
+ * the given Device service, or the {@code DRIVER_ID} of a more
+ * suitable driver
+ *
+ * @throws java.lang.Exception if the driver cannot attach to the given
+ * device and does not know of a more suitable driver
+ */
+ public String attach(ServiceReference reference) throws Exception;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverLocator.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverLocator.java
new file mode 100644
index 000000000..fdbe1a5d8
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverLocator.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.device;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Dictionary;
+
+/**
+ * A Driver Locator service can find and load device driver bundles given a
+ * property set. Each driver is represented by a unique {@code DRIVER_ID}.
+ * <p>
+ * Driver Locator services provide the mechanism for dynamically downloading new
+ * device driver bundles into an OSGi environment. They are supplied by
+ * providers and encapsulate all provider-specific details related to the
+ * location and acquisition of driver bundles.
+ *
+ * @author $Id$
+ * @see Driver
+ * @ThreadSafe
+ */
+public interface DriverLocator {
+ /**
+ * Returns an array of {@code DRIVER_ID} strings of drivers capable of
+ * attaching to a device with the given properties.
+ *
+ * <p>
+ * The property keys in the specified {@code Dictionary} objects are
+ * case-insensitive.
+ *
+ * @param props the properties of the device for which a driver is sought
+ * @return array of driver {@code DRIVER_ID} strings of drivers capable of
+ * attaching to a Device service with the given properties, or
+ * {@code null} if this Driver Locator service does not know of any
+ * such drivers
+ */
+ public String[] findDrivers(Dictionary props);
+
+ /**
+ * Get an {@code InputStream} from which the driver bundle providing a
+ * driver with the giving {@code DRIVER_ID} can be installed.
+ *
+ * @param id the {@code DRIVER_ID} of the driver that needs to be installed.
+ * @return An {@code InputStream} object from which the driver bundle can be
+ * installed or {@code null} if the driver with the given ID cannot
+ * be located
+ * @throws java.io.IOException the input stream for the bundle cannot be
+ * created
+ */
+ public InputStream loadDriver(String id) throws IOException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverSelector.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverSelector.java
new file mode 100644
index 000000000..179ecc7fc
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/DriverSelector.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.device;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * When the device manager detects a new Device service, it calls all registered
+ * Driver services to determine if anyone matches the Device service. If at
+ * least one Driver service matches, the device manager must choose one. If
+ * there is a Driver Selector service registered with the Framework, the device
+ * manager will ask it to make the selection. If there is no Driver Selector
+ * service, or if it returns an invalid result, or throws an {@code Exception},
+ * the device manager uses the default selection strategy.
+ *
+ * @author $Id$
+ * @since 1.1
+ * @ThreadSafe
+ */
+public interface DriverSelector {
+ /**
+ * Return value from {@code DriverSelector.select}, if no Driver service
+ * should be attached to the Device service. The value is -1.
+ */
+ public static final int SELECT_NONE = -1;
+
+ /**
+ * Select one of the matching Driver services. The device manager calls this
+ * method if there is at least one driver bidding for a device. Only Driver
+ * services that have responded with nonzero (not {@link Device#MATCH_NONE})
+ * {@code } match values will be included in the list.
+ *
+ * @param reference the {@code ServiceReference} object of the Device
+ * service.
+ * @param matches the array of all non-zero matches.
+ * @return index into the array of {@code Match} objects, or
+ * {@code SELECT_NONE} if no Driver service should be attached
+ */
+ public int select(ServiceReference reference, Match[] matches);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Match.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Match.java
new file mode 100644
index 000000000..d16251848
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/Match.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.device;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Instances of {@code Match} are used in the
+ * {@link DriverSelector#select(ServiceReference, Match[])} method to identify
+ * Driver services matching a Device service.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @author $Id$
+ * @since 1.1
+ * @see DriverSelector
+ */
+public interface Match {
+ /**
+ * Return the reference to a Driver service.
+ *
+ * @return {@code ServiceReference} object to a Driver service.
+ */
+ public ServiceReference getDriver();
+
+ /**
+ * Return the match value of this object.
+ *
+ * @return the match value returned by this Driver service.
+ */
+ public int getMatchValue();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/package-info.java
new file mode 100644
index 000000000..92de050fb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * Device Access Package Version 1.1.
+ *
+ * <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.device; version="[1.1,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.device; version="[1.1,1.2)"}
+ *
+ * @version 1.1
+ * @author $Id$
+ */
+
+package org.osgi.service.device;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/packageinfo
new file mode 100644
index 000000000..3987f9c4e
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/device/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/Event.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/Event.java
new file mode 100644
index 000000000..6fc64b4e9
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/Event.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.event;
+
+import static org.osgi.service.event.EventConstants.EVENT_TOPIC;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import org.osgi.framework.Filter;
+
+/**
+ * An event.
+ *
+ * {@code Event} objects are delivered to {@code EventHandler} services which
+ * subscribe to the topic of the event.
+ *
+ * @Immutable
+ * @author $Id$
+ */
+public class Event {
+ /**
+ * The topic of this event.
+ */
+ private final String topic;
+ /**
+ * The properties carried by this event. Keys are strings and values are
+ * objects
+ */
+ private final EventProperties properties;
+
+ /**
+ * Constructs an event.
+ *
+ * @param topic The topic of the event.
+ * @param properties The event's properties (may be {@code null}). A
+ * property whose key is not of type {@code String} will be ignored.
+ * @throws IllegalArgumentException If topic is not a valid topic name.
+ * @since 1.2
+ */
+ public Event(String topic, Map<String, ?> properties) {
+ validateTopicName(topic);
+ this.topic = topic;
+ // safely publish the event properties
+ this.properties = (properties instanceof EventProperties) ? (EventProperties) properties : new EventProperties(properties);
+ }
+
+ /**
+ * Constructs an event.
+ *
+ * @param topic The topic of the event.
+ * @param properties The event's properties (may be {@code null}). A
+ * property whose key is not of type {@code String} will be ignored.
+ * @throws IllegalArgumentException If topic is not a valid topic name.
+ */
+ public Event(String topic, Dictionary<String, ?> properties) {
+ validateTopicName(topic);
+ this.topic = topic;
+ // safely publish the event properties
+ this.properties = new EventProperties(properties);
+ }
+
+ /**
+ * Retrieve the value of an event property. The event topic may be retrieved
+ * with the property name &quot;event.topics&quot;.
+ *
+ * @param name The name of the property to retrieve.
+ * @return The value of the property, or {@code null} if not found.
+ */
+ public final Object getProperty(String name) {
+ if (EVENT_TOPIC.equals(name)) {
+ return topic;
+ }
+ return properties.get(name);
+ }
+
+ /**
+ * Indicate the presence of an event property. The event topic is present
+ * using the property name &quot;event.topics&quot;.
+ *
+ * @param name The name of the property.
+ * @return {@code true} if a property with the specified name is in the
+ * event. This property may have a {@code null} value. {@code false}
+ * otherwise.
+ * @since 1.3
+ */
+ public final boolean containsProperty(String name) {
+ if (EVENT_TOPIC.equals(name)) {
+ return true;
+ }
+ return properties.containsKey(name);
+ }
+
+ /**
+ * Returns a list of this event's property names. The list will include the
+ * event topic property name &quot;event.topics&quot;.
+ *
+ * @return A non-empty array with one element per property.
+ */
+ public final String[] getPropertyNames() {
+ int size = properties.size();
+ String[] result = new String[size + 1];
+ properties.keySet().toArray(result);
+ result[size] = EVENT_TOPIC;
+ return result;
+ }
+
+ /**
+ * Returns the topic of this event.
+ *
+ * @return The topic of this event.
+ */
+ public final String getTopic() {
+ return topic;
+ }
+
+ /**
+ * Tests this event's properties against the given filter using a case
+ * sensitive match.
+ *
+ * @param filter The filter to test.
+ * @return true If this event's properties match the filter, false
+ * otherwise.
+ */
+ public final boolean matches(Filter filter) {
+ return filter.matchCase(new FilterProperties(topic, properties));
+ }
+
+ /**
+ * Compares this {@code Event} object to another object.
+ *
+ * <p>
+ * An event is considered to be <b>equal to</b> another event if the topic
+ * is equal and the properties are equal. The properties are compared using
+ * the {@code java.util.Map.equals()} rules which includes identity
+ * comparison for array values.
+ *
+ * @param object The {@code Event} object to be compared.
+ * @return {@code true} if {@code object} is a {@code Event} and is equal to
+ * this object; {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) { // quick test
+ return true;
+ }
+
+ if (!(object instanceof Event)) {
+ return false;
+ }
+
+ Event event = (Event) object;
+ return topic.equals(event.topic) && properties.equals(event.properties);
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ *
+ * @return An integer which is a hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ int h = 31 * 17 + topic.hashCode();
+ h = 31 * h + properties.hashCode();
+ return h;
+ }
+
+ /**
+ * Returns the string representation of this event.
+ *
+ * @return The string representation of this event.
+ */
+ @Override
+ public String toString() {
+ return getClass().getName() + " [topic=" + topic + "]";
+ }
+
+ /**
+ * Called by the constructor to validate the topic name.
+ *
+ * @param topic The topic name to validate.
+ * @throws IllegalArgumentException If the topic name is invalid.
+ */
+ private static void validateTopicName(String topic) {
+ char[] chars = topic.toCharArray();
+ int length = chars.length;
+ if (length == 0) {
+ throw new IllegalArgumentException("empty topic");
+ }
+ for (int i = 0; i < length; i++) {
+ char ch = chars[i];
+ if (ch == '/') {
+ // Can't start or end with a '/' but anywhere else is okay
+ if (i == 0 || (i == length - 1)) {
+ throw new IllegalArgumentException("invalid topic: " + topic);
+ }
+ // Can't have "//" as that implies empty token
+ if (chars[i - 1] == '/') {
+ throw new IllegalArgumentException("invalid topic: " + topic);
+ }
+ continue;
+ }
+ if (('A' <= ch) && (ch <= 'Z')) {
+ continue;
+ }
+ if (('a' <= ch) && (ch <= 'z')) {
+ continue;
+ }
+ if (('0' <= ch) && (ch <= '9')) {
+ continue;
+ }
+ if ((ch == '_') || (ch == '-')) {
+ continue;
+ }
+ throw new IllegalArgumentException("invalid topic: " + topic);
+ }
+ }
+
+ /**
+ * Dictionary to use for Filter matching.
+ */
+ static private final class FilterProperties extends Dictionary<String, Object> {
+ private final String topic;
+ private final EventProperties properties;
+
+ FilterProperties(String topic, EventProperties properties) {
+ this.topic = topic;
+ this.properties = properties;
+ }
+
+ @Override
+ public Enumeration<Object> elements() {
+ Collection<Object> values = properties.values();
+ List<Object> result = new ArrayList<Object>(values.size() + 1);
+ result.add(topic);
+ result.addAll(values);
+ return Collections.enumeration(result);
+ }
+
+ @Override
+ public Object get(Object key) {
+ if (EVENT_TOPIC.equals(key)) {
+ return topic;
+ }
+ return properties.get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public Enumeration<String> keys() {
+ Collection<String> keys = properties.keySet();
+ List<String> result = new ArrayList<String>(keys.size() + 1);
+ result.add(EVENT_TOPIC);
+ result.addAll(keys);
+ return Collections.enumeration(result);
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return properties.size() + 1;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventAdmin.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventAdmin.java
new file mode 100644
index 000000000..529f0431b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventAdmin.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.event;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * The Event Admin service. Bundles wishing to publish events must obtain the
+ * Event Admin service and call one of the event delivery methods.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface EventAdmin {
+ /**
+ * Initiate asynchronous, ordered delivery of an event. This method returns
+ * to the caller before delivery of the event is completed. Events are
+ * delivered in the order that they are received by this method.
+ *
+ * @param event The event to send to all listeners which subscribe to the
+ * topic of the event.
+ *
+ * @throws SecurityException If the caller does not have
+ * {@code TopicPermission[topic,PUBLISH]} for the topic specified in
+ * the event.
+ */
+ void postEvent(Event event);
+
+ /**
+ * Initiate synchronous delivery of an event. This method does not return to
+ * the caller until delivery of the event is completed.
+ *
+ * @param event The event to send to all listeners which subscribe to the
+ * topic of the event.
+ *
+ * @throws SecurityException If the caller does not have
+ * {@code TopicPermission[topic,PUBLISH]} for the topic specified in
+ * the event.
+ */
+ void sendEvent(Event event);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventConstants.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventConstants.java
new file mode 100644
index 000000000..d002775d3
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventConstants.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.event;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+
+/**
+ * Defines standard names for {@code EventHandler} properties.
+ *
+ * @author $Id$
+ */
+@ProviderType
+public interface EventConstants {
+
+ /**
+ * Service registration property specifying the {@code Event} topics of
+ * interest to an Event Handler service.
+ * <p>
+ * Event handlers SHOULD be registered with this property. Each value of
+ * this property is a string that describe the topics in which the handler
+ * is interested. An asterisk ('*') may be used as a trailing wildcard.
+ * Event Handlers which do not have a value for this property must not
+ * receive events. More precisely, the value of each string must conform to
+ * the following grammar:
+ *
+ * <pre>
+ * topic-description := '*' | topic ( '/*' )?
+ * topic := token ( '/' token )*
+ * </pre>
+ *
+ * <p>
+ * The value of this property must be of type {@code String},
+ * {@code String[]}, or {@code Collection<String>}.
+ *
+ * @see Event
+ */
+ public static final String EVENT_TOPIC = "event.topics";
+
+ /**
+ * Service Registration property specifying a filter to further select
+ * {@code Event} s of interest to an Event Handler service.
+ * <p>
+ * Event handlers MAY be registered with this property. The value of this
+ * property is a string containing an LDAP-style filter specification. Any
+ * of the event's properties may be used in the filter expression. Each
+ * event handler is notified for any event which belongs to the topics in
+ * which the handler has expressed an interest. If the event handler is also
+ * registered with this service property, then the properties of the event
+ * must also match the filter for the event to be delivered to the event
+ * handler.
+ * <p>
+ * If the filter syntax is invalid, then the Event Handler must be ignored
+ * and a warning should be logged.
+ *
+ * <p>
+ * The value of this property must be of type {@code String}.
+ *
+ * @see Event
+ * @see Filter
+ */
+ public static final String EVENT_FILTER = "event.filter";
+
+ /**
+ * Service Registration property specifying the delivery qualities requested
+ * by an Event Handler service.
+ * <p>
+ * Event handlers MAY be registered with this property. Each value of this
+ * property is a string specifying a delivery quality for the Event handler.
+ *
+ * <p>
+ * The value of this property must be of type {@code String},
+ * {@code String[]}, or {@code Collection<String>}.
+ *
+ * @see #DELIVERY_ASYNC_ORDERED
+ * @see #DELIVERY_ASYNC_UNORDERED
+ * @since 1.3
+ */
+ public static final String EVENT_DELIVERY = "event.delivery";
+
+ /**
+ * Event Handler delivery quality value specifying the Event Handler
+ * requires asynchronously delivered events be delivered in order. Ordered
+ * delivery is the default for asynchronously delivered events.
+ *
+ * <p>
+ * This delivery quality value is mutually exclusive with
+ * {@link #DELIVERY_ASYNC_UNORDERED}. However, if both this value and
+ * {@link #DELIVERY_ASYNC_UNORDERED} are specified for an event handler,
+ * this value takes precedence.
+ *
+ * @see #EVENT_DELIVERY
+ * @since 1.3
+ */
+ public static final String DELIVERY_ASYNC_ORDERED = "async.ordered";
+
+ /**
+ * Event Handler delivery quality value specifying the Event Handler does
+ * not require asynchronously delivered events be delivered in order. This
+ * may allow an Event Admin implementation to optimize asynchronous event
+ * delivery by relaxing ordering requirements.
+ *
+ * <p>
+ * This delivery quality value is mutually exclusive with
+ * {@link #DELIVERY_ASYNC_ORDERED}. However, if both this value and
+ * {@link #DELIVERY_ASYNC_ORDERED} are specified for an event handler,
+ * {@link #DELIVERY_ASYNC_ORDERED} takes precedence.
+ *
+ * @see #EVENT_DELIVERY
+ * @since 1.3
+ */
+ public static final String DELIVERY_ASYNC_UNORDERED = "async.unordered";
+
+ /**
+ * The Distinguished Names of the signers of the bundle relevant to the
+ * event. The type of the value for this event property is {@code String} or
+ * {@code Collection} of {@code String}.
+ */
+ public static final String BUNDLE_SIGNER = "bundle.signer";
+
+ /**
+ * The Bundle Symbolic Name of the bundle relevant to the event. The type of
+ * the value for this event property is {@code String}.
+ */
+ public static final String BUNDLE_SYMBOLICNAME = "bundle.symbolicName";
+
+ /**
+ * The Bundle id of the bundle relevant to the event. The type of the value
+ * for this event property is {@code Long}.
+ *
+ * @since 1.1
+ */
+ public static final String BUNDLE_ID = "bundle.id";
+
+ /**
+ * The Bundle object of the bundle relevant to the event. The type of the
+ * value for this event property is {@link Bundle}.
+ *
+ * @since 1.1
+ */
+ public static final String BUNDLE = "bundle";
+
+ /**
+ * The version of the bundle relevant to the event. The type of the value
+ * for this event property is {@link Version}.
+ *
+ * @since 1.2
+ */
+ public static final String BUNDLE_VERSION = "bundle.version";
+
+ /**
+ * The forwarded event object. Used when rebroadcasting an event that was
+ * sent via some other event mechanism. The type of the value for this event
+ * property is {@code Object}.
+ */
+ public static final String EVENT = "event";
+
+ /**
+ * An exception or error. The type of the value for this event property is
+ * {@code Throwable}.
+ */
+ public static final String EXCEPTION = "exception";
+
+ /**
+ * The name of the exception type. Must be equal to the name of the class of
+ * the exception in the event property {@link #EXCEPTION}. The type of the
+ * value for this event property is {@code String}.
+ *
+ * @since 1.1
+ */
+ public static final String EXCEPTION_CLASS = "exception.class";
+
+ /**
+ * The exception message. Must be equal to the result of calling
+ * {@code getMessage()} on the exception in the event property
+ * {@link #EXCEPTION}. The type of the value for this event property is
+ * {@code String}.
+ */
+ public static final String EXCEPTION_MESSAGE = "exception.message";
+
+ /**
+ * A human-readable message that is usually not localized. The type of the
+ * value for this event property is {@code String}.
+ */
+ public static final String MESSAGE = "message";
+
+ /**
+ * A service reference. The type of the value for this event property is
+ * {@link ServiceReference}.
+ */
+ public static final String SERVICE = "service";
+
+ /**
+ * A service's id. The type of the value for this event property is
+ * {@code Long}.
+ */
+ public static final String SERVICE_ID = Constants.SERVICE_ID;
+
+ /**
+ * A service's objectClass. The type of the value for this event property is
+ * {@code String[]}.
+ */
+ public static final String SERVICE_OBJECTCLASS = "service.objectClass";
+
+ /**
+ * A service's persistent identity. The type of the value for this event
+ * property is {@code String} or {@code Collection} of {@code String}.
+ */
+ public static final String SERVICE_PID = Constants.SERVICE_PID;
+
+ /**
+ * The time when the event occurred, as reported by
+ * {@code System.currentTimeMillis()}. The type of the value for this event
+ * property is {@code Long}.
+ */
+ public static final String TIMESTAMP = "timestamp";
+
+ /**
+ * This constant was released with an incorrectly spelled name. It has been
+ * replaced by {@link #EXCEPTION_CLASS}
+ *
+ * @deprecated As of 1.1, replaced by EXCEPTION_CLASS
+ */
+ public static final String EXECPTION_CLASS = "exception.class";
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventHandler.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventHandler.java
new file mode 100644
index 000000000..996c63cec
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventHandler.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.event;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Listener for Events.
+ *
+ * <p>
+ * {@code EventHandler} objects are registered with the Framework service
+ * registry and are notified with an {@code Event} object when an event is sent
+ * or posted.
+ * <p>
+ * {@code EventHandler} objects can inspect the received {@code Event} object to
+ * determine its topic and properties.
+ *
+ * <p>
+ * {@code EventHandler} objects must be registered with a service property
+ * {@link EventConstants#EVENT_TOPIC} whose value is the list of topics in which
+ * the event handler is interested.
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * String[] topics = new String[] {&quot;com/isv/*&quot;};
+ * Hashtable ht = new Hashtable();
+ * ht.put(EventConstants.EVENT_TOPIC, topics);
+ * context.registerService(EventHandler.class.getName(), this, ht);
+ * </pre>
+ *
+ * Event Handler services can also be registered with an
+ * {@link EventConstants#EVENT_FILTER} service property to further filter the
+ * events. If the syntax of this filter is invalid, then the Event Handler must
+ * be ignored by the Event Admin service. The Event Admin service should log a
+ * warning.
+ * <p>
+ * Security Considerations. Bundles wishing to monitor {@code Event} objects
+ * will require {@code ServicePermission[EventHandler,REGISTER]} to register an
+ * {@code EventHandler} service. The bundle must also have
+ * {@code TopicPermission[topic,SUBSCRIBE]} for the topic specified in the event
+ * in order to receive the event.
+ *
+ * @see Event
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface EventHandler {
+ /**
+ * Called by the {@link EventAdmin} service to notify the listener of an
+ * event.
+ *
+ * @param event The event that occurred.
+ */
+ void handleEvent(Event event);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventProperties.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventProperties.java
new file mode 100644
index 000000000..548895a00
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/EventProperties.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.event;
+
+import static org.osgi.service.event.EventConstants.EVENT_TOPIC;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The properties for an {@link Event}. An event source can create an
+ * EventProperties object if it needs to reuse the same event properties for
+ * multiple events.
+ *
+ * <p>
+ * The keys are all of type {@code String}. The values are of type
+ * {@code Object}. The key &quot;event.topics&quot; is ignored as event topics
+ * can only be set when an {@link Event} is constructed.
+ *
+ * <p>
+ * Once constructed, an EventProperties object is unmodifiable. However, the
+ * values of the map used to construct an EventProperties object are still
+ * subject to modification as they are not deeply copied.
+ *
+ * @Immutable
+ * @since 1.3
+ * @author $Id$
+ */
+public class EventProperties implements Map<String, Object> {
+ /**
+ * The properties for an event. Keys are strings and values are objects. The
+ * object is unmodifiable.
+ */
+ private final Map<String, Object> properties;
+
+ /**
+ * Create an EventProperties from the specified properties.
+ *
+ * <p>
+ * The specified properties will be copied into this EventProperties.
+ * Properties whose key is not of type {@code String} will be ignored. A
+ * property with the key &quot;event.topics&quot; will be ignored.
+ *
+ * @param properties The properties to use for this EventProperties object
+ * (may be {@code null}).
+ */
+ public EventProperties(Map<String, ?> properties) {
+ int size = (properties == null) ? 0 : properties.size();
+ Map<String, Object> p = new HashMap<String, Object>(size);
+ if (size > 0) {
+ for (Object key : (Set<?>) properties.keySet()) {
+ if ((key instanceof String) && !EVENT_TOPIC.equals(key)) {
+ Object value = properties.get(key);
+ p.put((String) key, value);
+ }
+ }
+ }
+ // safely publish the map
+ this.properties = Collections.unmodifiableMap(p);
+ }
+
+ /**
+ * Create an EventProperties from the specified dictionary.
+ *
+ * <p>
+ * The specified properties will be copied into this EventProperties.
+ * Properties whose key is not of type {@code String} will be ignored. A
+ * property with the key &quot;event.topics&quot; will be ignored.
+ *
+ * @param properties The properties to use for this EventProperties object
+ * (may be {@code null}).
+ */
+ EventProperties(Dictionary<String, ?> properties) {
+ int size = (properties == null) ? 0 : properties.size();
+ Map<String, Object> p = new HashMap<String, Object>(size);
+ if (size > 0) {
+ for (Enumeration<?> e = properties.keys(); e.hasMoreElements();) {
+ Object key = e.nextElement();
+ if ((key instanceof String) && !EVENT_TOPIC.equals(key)) {
+ Object value = properties.get(key);
+ p.put((String) key, value);
+ }
+ }
+ }
+ // safely publish the map
+ this.properties = Collections.unmodifiableMap(p);
+ }
+
+ /**
+ * This method throws {@link UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException if called.
+ */
+ public void clear() {
+ properties.clear();
+ }
+
+ /**
+ * Indicates if the specified property is present.
+ *
+ * @param name The property name.
+ * @return {@code true} If the property is present, {@code false} otherwise.
+ */
+ public boolean containsKey(Object name) {
+ return properties.containsKey(name);
+ }
+
+ /**
+ * Indicates if the specified value is present.
+ *
+ * @param value The property value.
+ * @return {@code true} If the value is present, {@code false} otherwise.
+ */
+ public boolean containsValue(Object value) {
+ return properties.containsValue(value);
+ }
+
+ /**
+ * Return the property entries.
+ *
+ * @return A set containing the property name/value pairs.
+ */
+ public Set<java.util.Map.Entry<String, Object>> entrySet() {
+ return properties.entrySet();
+ }
+
+ /**
+ * Return the value of the specified property.
+ *
+ * @param name The name of the specified property.
+ * @return The value of the specified property.
+ */
+ public Object get(Object name) {
+ return properties.get(name);
+ }
+
+ /**
+ * Indicate if this properties is empty.
+ *
+ * @return {@code true} If this properties is empty, {@code false}
+ * otherwise.
+ */
+ public boolean isEmpty() {
+ return properties.isEmpty();
+ }
+
+ /**
+ * Return the names of the properties.
+ *
+ * @return The names of the properties.
+ */
+ public Set<String> keySet() {
+ return properties.keySet();
+ }
+
+ /**
+ * This method throws {@link UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException if called.
+ */
+ public Object put(String key, Object value) {
+ return properties.put(key, value);
+ }
+
+ /**
+ * This method throws {@link UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException if called.
+ */
+ public void putAll(Map<? extends String, ? extends Object> map) {
+ properties.putAll(map);
+ }
+
+ /**
+ * This method throws {@link UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException if called.
+ */
+ public Object remove(Object key) {
+ return properties.remove(key);
+ }
+
+ /**
+ * Return the number of properties.
+ *
+ * @return The number of properties.
+ */
+ public int size() {
+ return properties.size();
+ }
+
+ /**
+ * Return the properties values.
+ *
+ * @return The values of the properties.
+ */
+ public Collection<Object> values() {
+ return properties.values();
+ }
+
+ /**
+ * Compares this {@code EventProperties} object to another object.
+ *
+ * <p>
+ * The properties are compared using the {@code java.util.Map.equals()}
+ * rules which includes identity comparison for array values.
+ *
+ * @param object The {@code EventProperties} object to be compared.
+ * @return {@code true} if {@code object} is a {@code EventProperties} and
+ * is equal to this object; {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (!(object instanceof EventProperties)) {
+ return false;
+ }
+ EventProperties other = (EventProperties) object;
+ return properties.equals(other.properties);
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ *
+ * @return An integer which is a hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ return properties.hashCode();
+ }
+
+ /**
+ * Returns the string representation of this object.
+ *
+ * @return The string representation of this object.
+ */
+ @Override
+ public String toString() {
+ return properties.toString();
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/TopicPermission.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/TopicPermission.java
new file mode 100644
index 000000000..ad379bde2
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/TopicPermission.java
@@ -0,0 +1,548 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.event;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A bundle's authority to publish or subscribe to event on a topic.
+ *
+ * <p>
+ * A topic is a slash-separated string that defines a topic.
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * org/osgi/service/foo/FooEvent/ACTION
+ * </pre>
+ *
+ * <p>
+ * {@code TopicPermission} has two actions: {@code publish} and
+ * {@code subscribe}.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public final class TopicPermission extends Permission {
+ static final long serialVersionUID = -5855563886961618300L;
+ /**
+ * The action string {@code publish}.
+ */
+ public final static String PUBLISH = "publish";
+ /**
+ * The action string {@code subscribe}.
+ */
+ public final static String SUBSCRIBE = "subscribe";
+ private final static int ACTION_PUBLISH = 0x00000001;
+ private final static int ACTION_SUBSCRIBE = 0x00000002;
+ private final static int ACTION_ALL = ACTION_PUBLISH | ACTION_SUBSCRIBE;
+ private final static int ACTION_NONE = 0;
+ /**
+ * The actions mask.
+ */
+ private transient int action_mask;
+
+ /**
+ * prefix if the name is wildcarded.
+ */
+ private transient volatile String prefix;
+
+ /**
+ * The actions in canonical form.
+ *
+ * @serial
+ */
+ private volatile String actions = null;
+
+ /**
+ * Defines the authority to publich and/or subscribe to a topic within the
+ * EventAdmin service.
+ * <p>
+ * The name is specified as a slash-separated string. Wildcards may be used.
+ * For example:
+ *
+ * <pre>
+ * org/osgi/service/fooFooEvent/ACTION
+ * com/isv/*
+ * *
+ * </pre>
+ *
+ * <p>
+ * A bundle that needs to publish events on a topic must have the
+ * appropriate {@code TopicPermission} for that topic; similarly, a bundle
+ * that needs to subscribe to events on a topic must have the appropriate
+ * {@code TopicPermssion} for that topic.
+ * <p>
+ *
+ * @param name Topic name.
+ * @param actions {@code publish},{@code subscribe} (canonical order).
+ */
+ public TopicPermission(String name, String actions) {
+ this(name, parseActions(actions));
+ }
+
+ /**
+ * Package private constructor used by TopicPermissionCollection.
+ *
+ * @param name class name
+ * @param mask action mask
+ */
+ TopicPermission(String name, int mask) {
+ super(name);
+ setTransients(mask);
+ }
+
+ /**
+ * Called by constructors and when deserialized.
+ *
+ * @param name topic name
+ * @param mask action mask
+ */
+ private synchronized void setTransients(final int mask) {
+ final String name = getName();
+ if ((name == null) || name.length() == 0) {
+ throw new IllegalArgumentException("invalid name");
+ }
+
+ if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+ throw new IllegalArgumentException("invalid action string");
+ }
+ action_mask = mask;
+
+ if (name.equals("*")) {
+ prefix = "";
+ } else {
+ if (name.endsWith("/*")) {
+ prefix = name.substring(0, name.length() - 1);
+ } else {
+ prefix = null;
+ }
+ }
+ }
+
+ /**
+ * Returns the current action mask.
+ * <p>
+ * Used by the TopicPermissionCollection class.
+ *
+ * @return Current action mask.
+ */
+ synchronized int getActionsMask() {
+ return action_mask;
+ }
+
+ /**
+ * Parse action string into action mask.
+ *
+ * @param actions Action string.
+ * @return action mask.
+ */
+ private static int parseActions(final String actions) {
+ boolean seencomma = false;
+ int mask = ACTION_NONE;
+ if (actions == null) {
+ return mask;
+ }
+ char[] a = actions.toCharArray();
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+ while (i != -1) {
+ char c;
+ // skip whitespace
+ while ((i != -1) && ((c = a[i]) == ' ' || c == '\r' || c == '\n' || c == '\f' || c == '\t'))
+ i--;
+ // check for the known strings
+ int matchlen;
+ if (i >= 8 && (a[i - 8] == 's' || a[i - 8] == 'S')
+ && (a[i - 7] == 'u' || a[i - 7] == 'U')
+ && (a[i - 6] == 'b' || a[i - 6] == 'B')
+ && (a[i - 5] == 's' || a[i - 5] == 'S')
+ && (a[i - 4] == 'c' || a[i - 4] == 'C')
+ && (a[i - 3] == 'r' || a[i - 3] == 'R')
+ && (a[i - 2] == 'i' || a[i - 2] == 'I')
+ && (a[i - 1] == 'b' || a[i - 1] == 'B')
+ && (a[i] == 'e' || a[i] == 'E')) {
+ matchlen = 9;
+ mask |= ACTION_SUBSCRIBE;
+ }
+ else
+ if (i >= 6 && (a[i - 6] == 'p' || a[i - 6] == 'P')
+ && (a[i - 5] == 'u' || a[i - 5] == 'U')
+ && (a[i - 4] == 'b' || a[i - 4] == 'B')
+ && (a[i - 3] == 'l' || a[i - 3] == 'L')
+ && (a[i - 2] == 'i' || a[i - 2] == 'I')
+ && (a[i - 1] == 's' || a[i - 1] == 'S')
+ && (a[i] == 'h' || a[i] == 'H')) {
+ matchlen = 7;
+ mask |= ACTION_PUBLISH;
+ }
+ else {
+ // parse error
+ throw new IllegalArgumentException("invalid permission: "
+ + actions);
+ }
+ // make sure we didn't just match the tail of a word
+ // like "ackbarfpublish". Also, skip to the comma.
+ seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch (a[i - matchlen]) {
+ case ',' :
+ seencomma = true;
+ /* FALLTHROUGH */
+ case ' ' :
+ case '\r' :
+ case '\n' :
+ case '\f' :
+ case '\t' :
+ break;
+ default :
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ i--;
+ }
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+ if (seencomma) {
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ return mask;
+ }
+
+ /**
+ * Determines if the specified permission is implied by this object.
+ *
+ * <p>
+ * This method checks that the topic name of the target is implied by the
+ * topic name of this object. The list of {@code TopicPermission} actions
+ * must either match or allow for the list of the target object to imply the
+ * target {@code TopicPermission} action.
+ *
+ * <pre>
+ * x/y/*,&quot;publish&quot; -&gt; x/y/z,&quot;publish&quot; is true
+ * *,&quot;subscribe&quot; -&gt; x/y,&quot;subscribe&quot; is true
+ * *,&quot;publish&quot; -&gt; x/y,&quot;subscribe&quot; is false
+ * x/y,&quot;publish&quot; -&gt; x/y/z,&quot;publish&quot; is false
+ * </pre>
+ *
+ * @param p The target permission to interrogate.
+ * @return {@code true} if the specified {@code TopicPermission} action is
+ * implied by this object; {@code false} otherwise.
+ */
+ @Override
+ public boolean implies(Permission p) {
+ if (p instanceof TopicPermission) {
+ TopicPermission requested = (TopicPermission) p;
+ int requestedMask = requested.getActionsMask();
+ if ((getActionsMask() & requestedMask) == requestedMask) {
+ String requestedName = requested.getName();
+ String pre = prefix;
+ if (pre != null) {
+ return requestedName.startsWith(pre);
+ }
+
+ return requestedName.equals(getName());
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the canonical string representation of the
+ * {@code TopicPermission} actions.
+ *
+ * <p>
+ * Always returns present {@code TopicPermission} actions in the following
+ * order: {@code publish},{@code subscribe}.
+ *
+ * @return Canonical string representation of the {@code TopicPermission}
+ * actions.
+ */
+ @Override
+ public String getActions() {
+ String result = actions;
+ if (result == null) {
+ StringBuffer sb = new StringBuffer();
+ boolean comma = false;
+ int mask = getActionsMask();
+ if ((mask & ACTION_PUBLISH) == ACTION_PUBLISH) {
+ sb.append(PUBLISH);
+ comma = true;
+ }
+ if ((mask & ACTION_SUBSCRIBE) == ACTION_SUBSCRIBE) {
+ if (comma)
+ sb.append(',');
+ sb.append(SUBSCRIBE);
+ }
+ actions = result = sb.toString();
+ }
+ return result;
+ }
+
+ /**
+ * Returns a new {@code PermissionCollection} object suitable for storing
+ * {@code TopicPermission} objects.
+ *
+ * @return A new {@code PermissionCollection} object.
+ */
+ @Override
+ public PermissionCollection newPermissionCollection() {
+ return new TopicPermissionCollection();
+ }
+
+ /**
+ * Determines the equality of two {@code TopicPermission} objects.
+ *
+ * This method checks that specified {@code TopicPermission} has the same
+ * topic name and actions as this {@code TopicPermission} object.
+ *
+ * @param obj The object to test for equality with this
+ * {@code TopicPermission} object.
+ * @return {@code true} if {@code obj} is a {@code TopicPermission}, and has
+ * the same topic name and actions as this {@code TopicPermission}
+ * object; {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof TopicPermission)) {
+ return false;
+ }
+ TopicPermission tp = (TopicPermission) obj;
+ return (getActionsMask() == tp.getActionsMask()) && getName().equals(tp.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ int h = 31 * 17 + getName().hashCode();
+ h = 31 * h + getActions().hashCode();
+ return h;
+ }
+
+ /**
+ * WriteObject is called to save the state of this permission object to a
+ * stream. The actions are serialized, and the superclass takes care of the
+ * name.
+ */
+ private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ // Write out the actions. The superclass takes care of the name
+ // call getActions to make sure actions field is initialized
+ if (actions == null)
+ getActions();
+ s.defaultWriteObject();
+ }
+
+ /**
+ * readObject is called to restore the state of this permission from a
+ * stream.
+ */
+ private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
+ // Read in the action, then initialize the rest
+ s.defaultReadObject();
+ setTransients(parseActions(actions));
+ }
+}
+
+/**
+ * Stores a set of {@code TopicPermission} permissions.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ */
+final class TopicPermissionCollection extends PermissionCollection {
+ static final long serialVersionUID = -614647783533924048L;
+ /**
+ * Table of permissions.
+ *
+ * @GuardedBy this
+ */
+ private transient Map<String, TopicPermission> permissions;
+ /**
+ * Boolean saying if "*" is in the collection.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private boolean all_allowed;
+
+ /**
+ * Create an empty TopicPermissions object.
+ *
+ */
+ public TopicPermissionCollection() {
+ permissions = new HashMap<String, TopicPermission>();
+ all_allowed = false;
+ }
+
+ /**
+ * Adds a permission to the {@code TopicPermission} objects. The key for the
+ * hash is the name.
+ *
+ * @param permission The {@code TopicPermission} object to add.
+ *
+ * @throws IllegalArgumentException If the permission is not a
+ * {@code TopicPermission} instance.
+ *
+ * @throws SecurityException If this {@code TopicPermissionCollection}
+ * object has been marked read-only.
+ */
+ @Override
+ public void add(final Permission permission) {
+ if (!(permission instanceof TopicPermission)) {
+ throw new IllegalArgumentException("invalid permission: " + permission);
+ }
+ if (isReadOnly()) {
+ throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection");
+ }
+ final TopicPermission tp = (TopicPermission) permission;
+ final String name = tp.getName();
+ final int newMask = tp.getActionsMask();
+
+ synchronized (this) {
+ final TopicPermission existing = permissions.get(name);
+ if (existing != null) {
+ final int oldMask = existing.getActionsMask();
+ if (oldMask != newMask) {
+ permissions.put(name, new TopicPermission(name, oldMask | newMask));
+ }
+ } else {
+ permissions.put(name, tp);
+ }
+ if (!all_allowed) {
+ if (name.equals("*"))
+ all_allowed = true;
+ }
+ }
+ }
+
+ /**
+ * Determines if the specified permissions implies the permissions expressed
+ * in {@code permission}.
+ *
+ * @param permission The Permission object to compare with this
+ * {@code TopicPermission} object.
+ *
+ * @return {@code true} if {@code permission} is a proper subset of a
+ * permission in the set; {@code false} otherwise.
+ */
+ @Override
+ public boolean implies(final Permission permission) {
+ if (!(permission instanceof TopicPermission)) {
+ return false;
+ }
+ final TopicPermission requested = (TopicPermission) permission;
+ String name = requested.getName();
+ final int desired = requested.getActionsMask();
+ int effective = 0;
+
+ TopicPermission x;
+ // short circuit if the "*" Permission was added
+ synchronized (this) {
+ if (all_allowed) {
+ x = permissions.get("*");
+ if (x != null) {
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ }
+ x = permissions.get(name);
+ }
+ // strategy:
+ // Check for full match first. Then work our way up the
+ // name looking for matches on a/b/*
+ if (x != null) {
+ // we have a direct hit!
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ // work our way up the tree...
+ int last;
+ int offset = name.length() - 1;
+ while ((last = name.lastIndexOf("/", offset)) != -1) {
+ name = name.substring(0, last + 1) + "*";
+ synchronized (this) {
+ x = permissions.get(name);
+ }
+ if (x != null) {
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ offset = last - 1;
+ }
+ // we don't have to check for "*" as it was already checked
+ // at the top (all_allowed), so we just return false
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all {@code TopicPermission} objects in the
+ * container.
+ *
+ * @return Enumeration of all {@code TopicPermission} objects.
+ */
+ @Override
+ public synchronized Enumeration<Permission> elements() {
+ List<Permission> all = new ArrayList<Permission>(permissions.values());
+ return Collections.enumeration(all);
+ }
+
+ /* serialization logic */
+ private static final ObjectStreamField[] serialPersistentFields = {new ObjectStreamField("permissions", Hashtable.class), new ObjectStreamField("all_allowed", Boolean.TYPE)};
+
+ private synchronized void writeObject(ObjectOutputStream out) throws IOException {
+ Hashtable<String, TopicPermission> hashtable = new Hashtable<String, TopicPermission>(permissions);
+ ObjectOutputStream.PutField pfields = out.putFields();
+ pfields.put("permissions", hashtable);
+ pfields.put("all_allowed", all_allowed);
+ out.writeFields();
+ }
+
+ private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+ ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
+ Hashtable<String, TopicPermission> hashtable = (Hashtable<String, TopicPermission>) gfields.get("permissions", null);
+ permissions = new HashMap<String, TopicPermission>(hashtable);
+ all_allowed = gfields.get("all_allowed", false);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/package-info.java
new file mode 100644
index 000000000..7fe07b461
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Event Admin Package Version 1.3.
+ *
+ * <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.event; version="[1.3,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.event; version="[1.3,1.4)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.3")
+package org.osgi.service.event;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/packageinfo
new file mode 100644
index 000000000..0117a56c1
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/event/packageinfo
@@ -0,0 +1 @@
+version 1.3
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpContext.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpContext.java
new file mode 100644
index 000000000..d8c0c4b76
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpContext.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.http;
+
+import java.io.IOException;
+import java.net.URL;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This interface defines methods that the Http Service may call to get
+ * information about a registration.
+ *
+ * <p>
+ * Servlets and resources may be registered with an {@code HttpContext} object;
+ * if no {@code HttpContext} object is specified, a default {@code HttpContext}
+ * object is used. Servlets that are registered using the same
+ * {@code HttpContext} object will share the same {@code ServletContext} object.
+ *
+ * <p>
+ * This interface is implemented by users of the {@code HttpService}.
+ *
+ * @author $Id$
+ */
+public interface HttpContext {
+ /**
+ * {@code HttpServletRequest} attribute specifying the name of the
+ * authenticated user. The value of the attribute can be retrieved by
+ * {@code HttpServletRequest.getRemoteUser}. This attribute name is
+ * {@code org.osgi.service.http.authentication.remote.user}.
+ *
+ * @since 1.1
+ */
+ public static final String REMOTE_USER = "org.osgi.service.http.authentication.remote.user";
+ /**
+ * {@code HttpServletRequest} attribute specifying the scheme used in
+ * authentication. The value of the attribute can be retrieved by
+ * {@code HttpServletRequest.getAuthType}. This attribute name is
+ * {@code org.osgi.service.http.authentication.type}.
+ *
+ * @since 1.1
+ */
+ public static final String AUTHENTICATION_TYPE = "org.osgi.service.http.authentication.type";
+ /**
+ * {@code HttpServletRequest} attribute specifying the {@code Authorization}
+ * object obtained from the {@code org.osgi.service.useradmin.UserAdmin}
+ * service. The value of the attribute can be retrieved by
+ * {@code HttpServletRequest.getAttribute(HttpContext.AUTHORIZATION)}. This
+ * attribute name is {@code org.osgi.service.useradmin.authorization}.
+ *
+ * @since 1.1
+ */
+ public static final String AUTHORIZATION = "org.osgi.service.useradmin.authorization";
+
+ /**
+ * Handles security for the specified request.
+ *
+ * <p>
+ * The Http Service calls this method prior to servicing the specified
+ * request. This method controls whether the request is processed in the
+ * normal manner or an error is returned.
+ *
+ * <p>
+ * If the request requires authentication and the Authorization header in
+ * the request is missing or not acceptable, then this method should set the
+ * WWW-Authenticate header in the response object, set the status in the
+ * response object to Unauthorized(401) and return {@code false}. See also
+ * RFC 2617: <i>HTTP Authentication: Basic and Digest Access Authentication
+ * </i> (available at http://www.ietf.org/rfc/rfc2617.txt).
+ *
+ * <p>
+ * If the request requires a secure connection and the {@code getScheme}
+ * method in the request does not return 'https' or some other acceptable
+ * secure protocol, then this method should set the status in the response
+ * object to Forbidden(403) and return {@code false}.
+ *
+ * <p>
+ * When this method returns {@code false}, the Http Service will send the
+ * response back to the client, thereby completing the request. When this
+ * method returns {@code true}, the Http Service will proceed with servicing
+ * the request.
+ *
+ * <p>
+ * If the specified request has been authenticated, this method must set the
+ * {@link #AUTHENTICATION_TYPE} request attribute to the type of
+ * authentication used, and the {@link #REMOTE_USER} request attribute to
+ * the remote user (request attributes are set using the
+ * {@code setAttribute} method on the request). If this method does not
+ * perform any authentication, it must not set these attributes.
+ *
+ * <p>
+ * If the authenticated user is also authorized to access certain resources,
+ * this method must set the {@link #AUTHORIZATION} request attribute to the
+ * {@code Authorization} object obtained from the
+ * {@code org.osgi.service.useradmin.UserAdmin} service.
+ *
+ * <p>
+ * The servlet responsible for servicing the specified request determines
+ * the authentication type and remote user by calling the
+ * {@code getAuthType} and {@code getRemoteUser} methods, respectively, on
+ * the request.
+ *
+ * @param request the HTTP request
+ * @param response the HTTP response
+ * @return {@code true} if the request should be serviced, {@code false} if
+ * the request should not be serviced and Http Service will send the
+ * response back to the client.
+ * @throws java.io.IOException may be thrown by this method. If this occurs,
+ * the Http Service will terminate the request and close the socket.
+ */
+ public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException;
+
+ /**
+ * Maps a resource name to a URL.
+ *
+ * <p>
+ * Called by the Http Service to map a resource name to a URL. For servlet
+ * registrations, Http Service will call this method to support the
+ * {@code ServletContext} methods {@code getResource} and
+ * {@code getResourceAsStream}. For resource registrations, Http Service
+ * will call this method to locate the named resource. The context can
+ * control from where resources come. For example, the resource can be
+ * mapped to a file in the bundle's persistent storage area via
+ * {@code bundleContext.getDataFile(name).toURL()} or to a resource in the
+ * context's bundle via {@code getClass().getResource(name)}
+ *
+ * @param name the name of the requested resource
+ * @return URL that Http Service can use to read the resource or
+ * {@code null} if the resource does not exist.
+ */
+ public URL getResource(String name);
+
+ /**
+ * Maps a name to a MIME type.
+ *
+ * Called by the Http Service to determine the MIME type for the name. For
+ * servlet registrations, the Http Service will call this method to support
+ * the {@code ServletContext} method {@code getMimeType}. For resource
+ * registrations, the Http Service will call this method to determine the
+ * MIME type for the Content-Type header in the response.
+ *
+ * @param name determine the MIME type for this name.
+ * @return MIME type (e.g. text/html) of the name or {@code null} to
+ * indicate that the Http Service should determine the MIME type
+ * itself.
+ */
+ public String getMimeType(String name);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpService.java
new file mode 100644
index 000000000..c7dcd5824
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/HttpService.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.http;
+
+import java.util.Dictionary;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+/**
+ * The Http Service allows other bundles in the OSGi environment to dynamically
+ * register resources and servlets into the URI namespace of Http Service. A
+ * bundle may later unregister its resources or servlets.
+ *
+ * @noimplement
+ * @author $Id$
+ * @see HttpContext
+ */
+public interface HttpService {
+ /**
+ * Registers a servlet into the URI namespace.
+ *
+ * <p>
+ * The alias is the name in the URI namespace of the Http Service at which
+ * the registration will be mapped.
+ *
+ * <p>
+ * An alias must begin with slash ('/') and must not end with slash ('/'),
+ * with the exception that an alias of the form &quot;/&quot; is used to
+ * denote the root alias. See the specification text for details on how HTTP
+ * requests are mapped to servlet and resource registrations.
+ *
+ * <p>
+ * The Http Service will call the servlet's {@code init} method before
+ * returning.
+ *
+ * <pre>
+ * httpService.registerServlet(&quot;/myservlet&quot;, servlet, initparams, context);
+ * </pre>
+ *
+ * <p>
+ * Servlets registered with the same {@code HttpContext} object will share
+ * the same {@code ServletContext}. The Http Service will call the
+ * {@code context} argument to support the {@code ServletContext} methods
+ * {@code getResource},{@code getResourceAsStream} and {@code getMimeType},
+ * and to handle security for requests. If the {@code context} argument is
+ * {@code null}, a default {@code HttpContext} object is used (see
+ * {@link #createDefaultHttpContext()}).
+ *
+ * @param alias name in the URI namespace at which the servlet is registered
+ * @param servlet the servlet object to register
+ * @param initparams initialization arguments for the servlet or
+ * {@code null} if there are none. This argument is used by the
+ * servlet's {@code ServletConfig} object.
+ * @param context the {@code HttpContext} object for the registered servlet,
+ * or {@code null} if a default {@code HttpContext} is to be created
+ * and used.
+ * @throws NamespaceException if the registration fails because the alias is
+ * already in use.
+ * @throws javax.servlet.ServletException if the servlet's {@code init}
+ * method throws an exception, or the given servlet object has
+ * already been registered at a different alias.
+ * @throws java.lang.IllegalArgumentException if any of the arguments are
+ * invalid
+ */
+ public void registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext context) throws ServletException, NamespaceException;
+
+ /**
+ * Registers resources into the URI namespace.
+ *
+ * <p>
+ * The alias is the name in the URI namespace of the Http Service at which
+ * the registration will be mapped. An alias must begin with slash ('/') and
+ * must not end with slash ('/'), with the exception that an alias of the
+ * form &quot;/&quot; is used to denote the root alias. The name parameter
+ * must also not end with slash ('/') with the exception that a name of the
+ * form &quot;/&quot; is used to denote the root of the bundle. See the
+ * specification text for details on how HTTP requests are mapped to servlet
+ * and resource registrations.
+ * <p>
+ * For example, suppose the resource name /tmp is registered to the alias
+ * /files. A request for /files/foo.txt will map to the resource name
+ * /tmp/foo.txt.
+ *
+ * <pre>
+ * httpservice.registerResources(&quot;/files&quot;, &quot;/tmp&quot;, context);
+ * </pre>
+ *
+ * The Http Service will call the {@code HttpContext} argument to map
+ * resource names to URLs and MIME types and to handle security for
+ * requests. If the {@code HttpContext} argument is {@code null}, a default
+ * {@code HttpContext} is used (see {@link #createDefaultHttpContext()}).
+ *
+ * @param alias name in the URI namespace at which the resources are
+ * registered
+ * @param name the base name of the resources that will be registered
+ * @param context the {@code HttpContext} object for the registered
+ * resources, or {@code null} if a default {@code HttpContext} is to
+ * be created and used.
+ * @throws NamespaceException if the registration fails because the alias is
+ * already in use.
+ * @throws java.lang.IllegalArgumentException if any of the parameters are
+ * invalid
+ */
+ public void registerResources(String alias, String name, HttpContext context) throws NamespaceException;
+
+ /**
+ * Unregisters a previous registration done by {@code registerServlet} or
+ * {@code registerResources} methods.
+ *
+ * <p>
+ * After this call, the registered alias in the URI name-space will no
+ * longer be available. If the registration was for a servlet, the Http
+ * Service must call the {@code destroy} method of the servlet before
+ * returning.
+ * <p>
+ * If the bundle which performed the registration is stopped or otherwise
+ * "unget"s the Http Service without calling {@link #unregister(String)}
+ * then Http Service must automatically unregister the registration.
+ * However, if the registration was for a servlet, the {@code destroy}
+ * method of the servlet will not be called in this case since the bundle
+ * may be stopped. {@link #unregister(String)} must be explicitly called to
+ * cause the {@code destroy} method of the servlet to be called. This can be
+ * done in the {@code BundleActivator.stop} method of the bundle registering
+ * the servlet.
+ *
+ * @param alias name in the URI name-space of the registration to unregister
+ * @throws java.lang.IllegalArgumentException if there is no registration
+ * for the alias or the calling bundle was not the bundle which
+ * registered the alias.
+ */
+ public void unregister(String alias);
+
+ /**
+ * Creates a default {@code HttpContext} for registering servlets or
+ * resources with the HttpService, a new {@code HttpContext} object is
+ * created each time this method is called.
+ *
+ * <p>
+ * The behavior of the methods on the default {@code HttpContext} is defined
+ * as follows:
+ * <ul>
+ * <li>{@code getMimeType} - Does not define any customized MIME types for
+ * the Content-Type header in the response, and always returns {@code null}.
+ * </li>
+ * <li>{@code handleSecurity} - Performs implementation-defined
+ * authentication on the request.</li>
+ * <li>{@code getResource} - Assumes the named resource is in the context
+ * bundle; this method calls the context bundle's {@code Bundle.getResource}
+ * method, and returns the appropriate URL to access the resource. On a Java
+ * runtime environment that supports permissions, the Http Service needs to
+ * be granted {@code org.osgi.framework.AdminPermission[*,RESOURCE]}.</li>
+ * </ul>
+ *
+ * @return a default {@code HttpContext} object.
+ * @since 1.1
+ */
+ public HttpContext createDefaultHttpContext();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/NamespaceException.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/NamespaceException.java
new file mode 100644
index 000000000..6e4d8f6f5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/NamespaceException.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.http;
+
+/**
+ * A NamespaceException is thrown to indicate an error with the caller's request
+ * to register a servlet or resources into the URI namespace of the Http
+ * Service. This exception indicates that the requested alias already is in use.
+ *
+ * @author $Id$
+ */
+public class NamespaceException extends Exception {
+ static final long serialVersionUID = 7235606031147877747L;
+
+ /**
+ * Construct a {@code NamespaceException} object with a detail message.
+ *
+ * @param message the detail message
+ */
+ public NamespaceException(String message) {
+ super(message);
+ }
+
+ /**
+ * Construct a {@code NamespaceException} object with a detail message and a
+ * nested exception.
+ *
+ * @param message The detail message.
+ * @param cause The nested exception.
+ */
+ public NamespaceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Returns the nested exception.
+ *
+ * <p>
+ * This method predates the general purpose exception chaining mechanism.
+ * The {@code getCause()} method is now the preferred means of obtaining
+ * this information.
+ *
+ * @return The result of calling {@code getCause()}.
+ */
+ public Throwable getException() {
+ return getCause();
+ }
+
+ /**
+ * Returns the cause of this exception or {@code null} if no cause was set.
+ *
+ * @return The cause of this exception or {@code null} if no cause was set.
+ * @since 1.2
+ */
+ public Throwable getCause() {
+ return super.getCause();
+ }
+
+ /**
+ * Initializes the cause of this exception to the specified value.
+ *
+ * @param cause The cause of this exception.
+ * @return This exception.
+ * @throws IllegalArgumentException If the specified cause is this
+ * exception.
+ * @throws IllegalStateException If the cause of this exception has already
+ * been set.
+ * @since 1.2
+ */
+ public Throwable initCause(Throwable cause) {
+ return super.initCause(cause);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/package-info.java
new file mode 100644
index 000000000..349de707c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Http Service Package Version 1.2.
+ *
+ * <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.http; version="[1.2,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.http; version="[1.2,1.3)"}
+ *
+ * @version 1.2.1
+ * @author $Id$
+ */
+
+package org.osgi.service.http;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/packageinfo
new file mode 100644
index 000000000..6ebb891f1
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/http/packageinfo
@@ -0,0 +1 @@
+version 1.2.1
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogEntry.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogEntry.java
new file mode 100644
index 000000000..1a6c322e6
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogEntry.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.log;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Provides methods to access the information contained in an individual Log
+ * Service log entry.
+ *
+ * <p>
+ * A {@code LogEntry} object may be acquired from the
+ * {@code LogReaderService.getLog} method or by registering a
+ * {@code LogListener} object.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @author $Id$
+ * @see LogReaderService#getLog
+ * @see LogListener
+ */
+public interface LogEntry {
+ /**
+ * Returns the bundle that created this {@code LogEntry} object.
+ *
+ * @return The bundle that created this {@code LogEntry} object;
+ * {@code null} if no bundle is associated with this
+ * {@code LogEntry} object.
+ */
+ public Bundle getBundle();
+
+ /**
+ * Returns the {@code ServiceReference} object for the service associated
+ * with this {@code LogEntry} object.
+ *
+ * @return {@code ServiceReference} object for the service associated with
+ * this {@code LogEntry} object; {@code null} if no
+ * {@code ServiceReference} object was provided.
+ */
+ public ServiceReference getServiceReference();
+
+ /**
+ * Returns the severity level of this {@code LogEntry} object.
+ *
+ * <p>
+ * This is one of the severity levels defined by the {@code LogService}
+ * interface.
+ *
+ * @return Severity level of this {@code LogEntry} object.
+ *
+ * @see LogService#LOG_ERROR
+ * @see LogService#LOG_WARNING
+ * @see LogService#LOG_INFO
+ * @see LogService#LOG_DEBUG
+ */
+ public int getLevel();
+
+ /**
+ * Returns the human readable message associated with this {@code LogEntry}
+ * object.
+ *
+ * @return {@code String} containing the message associated with this
+ * {@code LogEntry} object.
+ */
+ public String getMessage();
+
+ /**
+ * Returns the exception object associated with this {@code LogEntry}
+ * object.
+ *
+ * <p>
+ * In some implementations, the returned exception may not be the original
+ * exception. To avoid references to a bundle defined exception class, thus
+ * preventing an uninstalled bundle from being garbage collected, the Log
+ * Service may return an exception object of an implementation defined
+ * Throwable subclass. The returned object will attempt to provide as much
+ * information as possible from the original exception object such as the
+ * message and stack trace.
+ *
+ * @return {@code Throwable} object of the exception associated with this
+ * {@code LogEntry};{@code null} if no exception is associated with
+ * this {@code LogEntry} object.
+ */
+ public Throwable getException();
+
+ /**
+ * Returns the value of {@code currentTimeMillis()} at the time this
+ * {@code LogEntry} object was created.
+ *
+ * @return The system time in milliseconds when this {@code LogEntry} object
+ * was created.
+ * @see "System.currentTimeMillis()"
+ */
+ public long getTime();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogListener.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogListener.java
new file mode 100644
index 000000000..4e27a9415
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogListener.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.log;
+
+import java.util.EventListener;
+
+/**
+ * Subscribes to {@code LogEntry} objects from the {@code LogReaderService}.
+ *
+ * <p>
+ * A {@code LogListener} object may be registered with the Log Reader Service
+ * using the {@code LogReaderService.addLogListener} method. After the listener
+ * is registered, the {@code logged} method will be called for each
+ * {@code LogEntry} object created. The {@code LogListener} object may be
+ * unregistered by calling the {@code LogReaderService.removeLogListener}
+ * method.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ * @see LogReaderService
+ * @see LogEntry
+ * @see LogReaderService#addLogListener(LogListener)
+ * @see LogReaderService#removeLogListener(LogListener)
+ */
+public interface LogListener extends EventListener {
+ /**
+ * Listener method called for each LogEntry object created.
+ *
+ * <p>
+ * As with all event listeners, this method should return to its caller as
+ * soon as possible.
+ *
+ * @param entry A {@code LogEntry} object containing log information.
+ * @see LogEntry
+ */
+ public void logged(LogEntry entry);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogReaderService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogReaderService.java
new file mode 100644
index 000000000..ecc3958bd
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogReaderService.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.log;
+
+import java.util.Enumeration;
+
+/**
+ * Provides methods to retrieve {@code LogEntry} objects from the log.
+ * <p>
+ * There are two ways to retrieve {@code LogEntry} objects:
+ * <ul>
+ * <li>The primary way to retrieve {@code LogEntry} objects is to register a
+ * {@code LogListener} object whose {@code LogListener.logged} method will be
+ * called for each entry added to the log.</li>
+ * <li>To retrieve past {@code LogEntry} objects, the {@code getLog} method can
+ * be called which will return an {@code Enumeration} of all {@code LogEntry}
+ * objects in the log.</li>
+ * </ul>
+ *
+ * @ThreadSafe
+ * @author $Id$
+ * @see LogEntry
+ * @see LogListener
+ * @see LogListener#logged(LogEntry)
+ */
+public interface LogReaderService {
+ /**
+ * Subscribes to {@code LogEntry} objects.
+ *
+ * <p>
+ * This method registers a {@code LogListener} object with the Log Reader
+ * Service. The {@code LogListener.logged(LogEntry)} method will be called
+ * for each {@code LogEntry} object placed into the log.
+ *
+ * <p>
+ * When a bundle which registers a {@code LogListener} object is stopped or
+ * otherwise releases the Log Reader Service, the Log Reader Service must
+ * remove all of the bundle's listeners.
+ *
+ * <p>
+ * If this Log Reader Service's list of listeners already contains a
+ * listener {@code l} such that {@code (l==listener)}, this method does
+ * nothing.
+ *
+ * @param listener A {@code LogListener} object to register; the
+ * {@code LogListener} object is used to receive {@code LogEntry}
+ * objects.
+ * @see LogListener
+ * @see LogEntry
+ * @see LogListener#logged(LogEntry)
+ */
+ public void addLogListener(LogListener listener);
+
+ /**
+ * Unsubscribes to {@code LogEntry} objects.
+ *
+ * <p>
+ * This method unregisters a {@code LogListener} object from the Log Reader
+ * Service.
+ *
+ * <p>
+ * If {@code listener} is not contained in this Log Reader Service's list of
+ * listeners, this method does nothing.
+ *
+ * @param listener A {@code LogListener} object to unregister.
+ * @see LogListener
+ */
+ public void removeLogListener(LogListener listener);
+
+ /**
+ * Returns an {@code Enumeration} of all {@code LogEntry} objects in the
+ * log.
+ *
+ * <p>
+ * Each element of the enumeration is a {@code LogEntry} object, ordered
+ * with the most recent entry first. Whether the enumeration is of all
+ * {@code LogEntry} objects since the Log Service was started or some recent
+ * past is implementation-specific. Also implementation-specific is whether
+ * informational and debug {@code LogEntry} objects are included in the
+ * enumeration.
+ *
+ * @return An {@code Enumeration} of all {@code LogEntry} objects in the
+ * log.
+ */
+ public Enumeration getLog();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java
new file mode 100644
index 000000000..dc7a9f634
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.log;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Provides methods for bundles to write messages to the log.
+ *
+ * <p>
+ * {@code LogService} methods are provided to log messages; optionally with a
+ * {@code ServiceReference} object or an exception.
+ *
+ * <p>
+ * Bundles must log messages in the OSGi environment with a severity level
+ * according to the following hierarchy:
+ * <ol>
+ * <li>{@link #LOG_ERROR}</li>
+ * <li>{@link #LOG_WARNING}</li>
+ * <li>{@link #LOG_INFO}</li>
+ * <li>{@link #LOG_DEBUG}</li>
+ * </ol>
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @author $Id$
+ */
+public interface LogService {
+ /**
+ * An error message (Value 1).
+ *
+ * <p>
+ * This log entry indicates the bundle or service may not be functional.
+ */
+ public static final int LOG_ERROR = 1;
+ /**
+ * A warning message (Value 2).
+ *
+ * <p>
+ * This log entry indicates a bundle or service is still functioning but may
+ * experience problems in the future because of the warning condition.
+ */
+ public static final int LOG_WARNING = 2;
+ /**
+ * An informational message (Value 3).
+ *
+ * <p>
+ * This log entry may be the result of any change in the bundle or service
+ * and does not indicate a problem.
+ */
+ public static final int LOG_INFO = 3;
+ /**
+ * A debugging message (Value 4).
+ *
+ * <p>
+ * This log entry is used for problem determination and may be irrelevant to
+ * anyone but the bundle developer.
+ */
+ public static final int LOG_DEBUG = 4;
+
+ /**
+ * Logs a message.
+ *
+ * <p>
+ * The {@code ServiceReference} field and the {@code Throwable} field of the
+ * {@code LogEntry} object will be set to {@code null}.
+ *
+ * @param level The severity of the message. This should be one of the
+ * defined log levels but may be any integer that is interpreted in a
+ * user defined way.
+ * @param message Human readable string describing the condition or
+ * {@code null}.
+ * @see #LOG_ERROR
+ * @see #LOG_WARNING
+ * @see #LOG_INFO
+ * @see #LOG_DEBUG
+ */
+ public void log(int level, String message);
+
+ /**
+ * Logs a message with an exception.
+ *
+ * <p>
+ * The {@code ServiceReference} field of the {@code LogEntry} object will be
+ * set to {@code null}.
+ *
+ * @param level The severity of the message. This should be one of the
+ * defined log levels but may be any integer that is interpreted in a
+ * user defined way.
+ * @param message The human readable string describing the condition or
+ * {@code null}.
+ * @param exception The exception that reflects the condition or
+ * {@code null}.
+ * @see #LOG_ERROR
+ * @see #LOG_WARNING
+ * @see #LOG_INFO
+ * @see #LOG_DEBUG
+ */
+ public void log(int level, String message, Throwable exception);
+
+ /**
+ * Logs a message associated with a specific {@code ServiceReference}
+ * object.
+ *
+ * <p>
+ * The {@code Throwable} field of the {@code LogEntry} will be set to
+ * {@code null}.
+ *
+ * @param sr The {@code ServiceReference} object of the service that this
+ * message is associated with or {@code null}.
+ * @param level The severity of the message. This should be one of the
+ * defined log levels but may be any integer that is interpreted in a
+ * user defined way.
+ * @param message Human readable string describing the condition or
+ * {@code null}.
+ * @see #LOG_ERROR
+ * @see #LOG_WARNING
+ * @see #LOG_INFO
+ * @see #LOG_DEBUG
+ */
+ public void log(ServiceReference sr, int level, String message);
+
+ /**
+ * Logs a message with an exception associated and a
+ * {@code ServiceReference} object.
+ *
+ * @param sr The {@code ServiceReference} object of the service that this
+ * message is associated with.
+ * @param level The severity of the message. This should be one of the
+ * defined log levels but may be any integer that is interpreted in a
+ * user defined way.
+ * @param message Human readable string describing the condition or
+ * {@code null}.
+ * @param exception The exception that reflects the condition or
+ * {@code null}.
+ * @see #LOG_ERROR
+ * @see #LOG_WARNING
+ * @see #LOG_INFO
+ * @see #LOG_DEBUG
+ */
+ public void log(ServiceReference sr, int level, String message, Throwable exception);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java
new file mode 100644
index 000000000..928099019
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * Log Service Package Version 1.3.
+ *
+ * <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.log; version="[1.3,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.log; version="[1.3,1.4)"}
+ *
+ * @version 1.3
+ * @author $Id$
+ */
+
+package org.osgi.service.log;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/packageinfo
new file mode 100644
index 000000000..0117a56c1
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/packageinfo
@@ -0,0 +1 @@
+version 1.3
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/AttributeDefinition.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/AttributeDefinition.java
new file mode 100644
index 000000000..f2aa9ead0
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/AttributeDefinition.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.metatype;
+
+/**
+ * An interface to describe an attribute.
+ *
+ * <p>
+ * An {@code AttributeDefinition} object defines a description of the data type
+ * of a property/attribute.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public interface AttributeDefinition {
+ /**
+ * The {@code STRING} (1) type.
+ *
+ * <p>
+ * Attributes of this type should be stored as {@code String},
+ * {@code Vector} with {@code String} or {@code String[]} objects, depending
+ * on the {@code getCardinality()} value.
+ */
+ int STRING = 1;
+ /**
+ * The {@code LONG} (2) type.
+ *
+ * Attributes of this type should be stored as {@code Long}, {@code Vector}
+ * with {@code Long} or {@code long[]} objects, depending on the
+ * {@code getCardinality()} value.
+ */
+ int LONG = 2;
+ /**
+ * The {@code INTEGER} (3) type.
+ *
+ * Attributes of this type should be stored as {@code Integer},
+ * {@code Vector} with {@code Integer} or {@code int[]} objects, depending
+ * on the {@code getCardinality()} value.
+ */
+ int INTEGER = 3;
+ /**
+ * The {@code SHORT} (4) type.
+ *
+ * Attributes of this type should be stored as {@code Short}, {@code Vector}
+ * with {@code Short} or {@code short[]} objects, depending on the
+ * {@code getCardinality()} value.
+ */
+ int SHORT = 4;
+ /**
+ * The {@code CHARACTER} (5) type.
+ *
+ * Attributes of this type should be stored as {@code Character},
+ * {@code Vector} with {@code Character} or {@code char[]} objects,
+ * depending on the {@code getCardinality()} value.
+ */
+ int CHARACTER = 5;
+ /**
+ * The {@code BYTE} (6) type.
+ *
+ * Attributes of this type should be stored as {@code Byte}, {@code Vector}
+ * with {@code Byte} or {@code byte[]} objects, depending on the
+ * {@code getCardinality()} value.
+ */
+ int BYTE = 6;
+ /**
+ * The {@code DOUBLE} (7) type.
+ *
+ * Attributes of this type should be stored as {@code Double},
+ * {@code Vector} with {@code Double} or {@code double[]} objects, depending
+ * on the {@code getCardinality()} value.
+ */
+ int DOUBLE = 7;
+ /**
+ * The {@code FLOAT} (8) type.
+ *
+ * Attributes of this type should be stored as {@code Float}, {@code Vector}
+ * with {@code Float} or {@code float[]} objects, depending on the
+ * {@code getCardinality()} value.
+ */
+ int FLOAT = 8;
+ /**
+ * The {@code BIGINTEGER} (9) type.
+ *
+ * Attributes of this type should be stored as {@code BigInteger},
+ * {@code Vector} with {@code BigInteger} or {@code BigInteger[]} objects,
+ * depending on the {@code getCardinality()} value.
+ *
+ * @deprecated As of 1.1.
+ */
+ int BIGINTEGER = 9;
+ /**
+ * The {@code BIGDECIMAL} (10) type.
+ *
+ * Attributes of this type should be stored as {@code BigDecimal},
+ * {@code Vector} with {@code BigDecimal} or {@code BigDecimal[]} objects
+ * depending on {@code getCardinality()}.
+ *
+ * @deprecated As of 1.1.
+ */
+ int BIGDECIMAL = 10;
+ /**
+ * The {@code BOOLEAN} (11) type.
+ *
+ * Attributes of this type should be stored as {@code Boolean},
+ * {@code Vector} with {@code Boolean} or {@code boolean[]} objects
+ * depending on {@code getCardinality()}.
+ */
+ int BOOLEAN = 11;
+
+ /**
+ * The {@code PASSWORD} (12) type.
+ *
+ * Attributes of this type must be stored as {@code String}, {@code Vector}
+ * with {@code String} or {@code String[]} objects depending on {link
+ * getCardinality()}. A {@code PASSWORD} must be treated as a string but the
+ * type can be used to disguise the information when displayed to a user to
+ * prevent others from seeing it.
+ *
+ * @since 1.2
+ */
+ int PASSWORD = 12;
+
+ /**
+ * Get the name of the attribute. This name may be localized.
+ *
+ * @return The localized name of the definition.
+ */
+ String getName();
+
+ /**
+ * Unique identity for this attribute.
+ *
+ * Attributes share a global namespace in the registry. E.g. an attribute
+ * {@code cn} or {@code commonName} must always be a {@code String} and the
+ * semantics are always a name of some object. They share this aspect with
+ * LDAP/X.500 attributes. In these standards the OSI Object Identifier (OID)
+ * is used to uniquely identify an attribute. If such an OID exists, (which
+ * can be requested at several standard organisations and many companies
+ * already have a node in the tree) it can be returned here. Otherwise, a
+ * unique id should be returned which can be a Java class name (reverse
+ * domain name) or generated with a GUID algorithm. Note that all LDAP
+ * defined attributes already have an OID. It is strongly advised to define
+ * the attributes from existing LDAP schemes which will give the OID. Many
+ * such schemes exist ranging from postal addresses to DHCP parameters.
+ *
+ * @return The id or oid
+ */
+ String getID();
+
+ /**
+ * Return a description of this attribute.
+ *
+ * The description may be localized and must describe the semantics of this
+ * type and any constraints.
+ *
+ * @return The localized description of the definition.
+ */
+ String getDescription();
+
+ /**
+ * Return the cardinality of this attribute.
+ *
+ * The OSGi environment handles multi valued attributes in arrays ([]) or in
+ * {@code Vector} objects. The return value is defined as follows:
+ *
+ * <pre>
+ *
+ * x = Integer.MIN_VALUE no limit, but use Vector
+ * x &lt; 0 -x = max occurrences, store in Vector
+ * x &gt; 0 x = max occurrences, store in array []
+ * x = Integer.MAX_VALUE no limit, but use array []
+ * x = 0 1 occurrence required
+ *
+ * </pre>
+ *
+ * @return The cardinality of this attribute.
+ */
+ int getCardinality();
+
+ /**
+ * Return the type for this attribute.
+ *
+ * <p>
+ * Defined in the following constants which map to the appropriate Java
+ * type. {@code STRING},{@code LONG},{@code INTEGER}, {@code CHAR},
+ * {@code BYTE},{@code DOUBLE},{@code FLOAT}, {@code BOOLEAN}.
+ *
+ * @return The type for this attribute.
+ */
+ int getType();
+
+ /**
+ * Return a list of option values that this attribute can take.
+ *
+ * <p>
+ * If the function returns {@code null}, there are no option values
+ * available.
+ *
+ * <p>
+ * Each value must be acceptable to validate() (return "") and must be a
+ * {@code String} object that can be converted to the data type defined by
+ * getType() for this attribute.
+ *
+ * <p>
+ * This list must be in the same sequence as {@code getOptionLabels()}. I.e.
+ * for each index i in {@code getOptionValues}, i in
+ * {@code getOptionLabels()} should be the label.
+ *
+ * <p>
+ * For example, if an attribute can have the value male, female, unknown,
+ * this list can return
+ * <code>new String[] { "male", "female", "unknown" }</code>.
+ *
+ * @return A list values
+ */
+ String[] getOptionValues();
+
+ /**
+ * Return a list of labels of option values.
+ *
+ * <p>
+ * The purpose of this method is to allow menus with localized labels. It is
+ * associated with {@code getOptionValues}. The labels returned here are
+ * ordered in the same way as the values in that method.
+ *
+ * <p>
+ * If the function returns {@code null}, there are no option labels
+ * available.
+ * <p>
+ * This list must be in the same sequence as the {@code getOptionValues()}
+ * method. I.e. for each index i in {@code getOptionLabels}, i in
+ * {@code getOptionValues()} should be the associated value.
+ *
+ * <p>
+ * For example, if an attribute can have the value male, female, unknown,
+ * this list can return (for dutch)
+ * <code>new String[] { "Man", "Vrouw", "Onbekend" }</code>.
+ *
+ * @return A list values
+ */
+ String[] getOptionLabels();
+
+ /**
+ * Validate an attribute in {@code String} form.
+ *
+ * An attribute might be further constrained in value. This method will
+ * attempt to validate the attribute according to these constraints. It can
+ * return three different values:
+ *
+ * <pre>
+ * null No validation present
+ * "" No problems detected
+ * "..." A localized description of why the value is wrong
+ * </pre>
+ *
+ * If the cardinality of this attribute is multi-valued then this string
+ * must be interpreted as a comma delimited string. The complete value must
+ * be trimmed from white space as well as spaces around commas. Commas (
+ * {@code ','} &#92;u002C) and spaces ({@code ' '} &#92;u0020) and
+ * backslashes ({@code '\'} &#92;u005C) can be escaped with another
+ * backslash. Escaped spaces must not be trimmed. For example:
+ *
+ * <pre>
+ * value=" a\,b,b\,c,\ c\\,d " => [ "a,b", "b,c", " c\", "d" ]
+ * </pre>
+ *
+ * @param value The value before turning it into the basic data type. If the
+ * cardinality indicates a multi-valued attribute then the given
+ * string must be escaped.
+ * @return {@code null}, "", or another string
+ */
+ String validate(String value);
+
+ /**
+ * Return a default for this attribute.
+ *
+ * The object must be of the appropriate type as defined by the cardinality
+ * and {@code getType()}. The return type is a list of {@code String}
+ * objects that can be converted to the appropriate type. The cardinality of
+ * the return array must follow the absolute cardinality of this type. E.g.
+ * if the cardinality = 0, the array must contain 1 element. If the
+ * cardinality is 1, it must contain 0 or 1 elements. If it is -5, it must
+ * contain from 0 to max 5 elements. Note that the special case of a 0
+ * cardinality, meaning a single value, does not allow arrays or vectors of
+ * 0 elements.
+ *
+ * @return Return a default value or {@code null} if no default exists.
+ */
+ String[] getDefaultValue();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeInformation.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeInformation.java
new file mode 100644
index 000000000..5d7956910
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeInformation.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.metatype;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * A MetaType Information object is created by the MetaTypeService to return
+ * meta type information for a specific bundle.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @author $Id$
+ * @since 1.1
+ */
+public interface MetaTypeInformation extends MetaTypeProvider {
+ /**
+ * Return the PIDs (for ManagedServices) for which ObjectClassDefinition
+ * information is available.
+ *
+ * @return Array of PIDs.
+ */
+ public String[] getPids();
+
+ /**
+ * Return the Factory PIDs (for ManagedServiceFactories) for which
+ * ObjectClassDefinition information is available.
+ *
+ * @return Array of Factory PIDs.
+ */
+ public String[] getFactoryPids();
+
+ /**
+ * Return the bundle for which this object provides meta type information.
+ *
+ * @return Bundle for which this object provides meta type information.
+ */
+ public Bundle getBundle();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeProvider.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeProvider.java
new file mode 100644
index 000000000..44778640e
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeProvider.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.metatype;
+
+/**
+ * Provides access to metatypes. This interface can be implemented on a Managed
+ * Service or Managed Service Factory as well as registered as a service. When
+ * registered as a service, it must be registered with a
+ * {@link #METATYPE_FACTORY_PID} or {@link #METATYPE_PID} service property (or
+ * both). Any PID mentioned in either of these factories must be a valid
+ * argument to the {@link #getObjectClassDefinition(String, String)} method.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public interface MetaTypeProvider {
+
+ /**
+ * Service property to signal that this service has
+ * {@link ObjectClassDefinition} objects for the given PIDs. The type of
+ * this service property is {@code String+}.
+ *
+ * @since 1.2
+ */
+ String METATYPE_PID = "metatype.pid";
+
+ /**
+ * Service property to signal that this service has
+ * {@link ObjectClassDefinition} objects for the given factory PIDs. The
+ * type of this service property is {@code String+}.
+ *
+ * @since 1.2
+ */
+ String METATYPE_FACTORY_PID = "metatype.factory.pid";
+
+ /**
+ * Returns an object class definition for the specified id localized to the
+ * specified locale.
+ *
+ * <p>
+ * The locale parameter must be a name that consists of {@code language}[
+ * "_" {@code country}[ "_" {@code variation}] ] as is customary in the
+ * {@code Locale} class. This {@code Locale} class is not used because
+ * certain profiles do not contain it.
+ *
+ * @param id The ID of the requested object class. This can be a pid or
+ * factory pid returned by getPids or getFactoryPids.
+ * @param locale The locale of the definition or {@code null} for default
+ * locale.
+ * @return A {@code ObjectClassDefinition} object.
+ * @throws IllegalArgumentException If the id or locale arguments are not
+ * valid
+ */
+ public ObjectClassDefinition getObjectClassDefinition(String id, String locale);
+
+ /**
+ * Return a list of available locales.
+ *
+ * The results must be names that consists of language [ _ country [ _
+ * variation ]] as is customary in the {@code Locale} class.
+ *
+ * @return An array of locale strings or {@code null} if there is no locale
+ * specific localization can be found.
+ *
+ */
+ public String[] getLocales();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeService.java
new file mode 100644
index 000000000..e4733d8f8
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/MetaTypeService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.metatype;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * The MetaType Service can be used to obtain meta type information for a
+ * bundle. The MetaType Service will examine the specified bundle for meta type
+ * documents to create the returned {@code MetaTypeInformation} object.
+ *
+ * <p>
+ * If the specified bundle does not contain any meta type documents, then a
+ * {@code MetaTypeInformation} object will be returned that wrappers any
+ * {@code ManagedService} or {@code ManagedServiceFactory} services registered
+ * by the specified bundle that implement {@code MetaTypeProvider}. Thus the
+ * MetaType Service can be used to retrieve meta type information for bundles
+ * which contain a meta type documents or which provide their own
+ * {@code MetaTypeProvider} objects.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @author $Id$
+ * @since 1.1
+ */
+public interface MetaTypeService {
+ /**
+ * Return the MetaType information for the specified bundle.
+ *
+ * @param bundle The bundle for which meta type information is requested.
+ * @return A MetaTypeInformation object for the specified bundle.
+ */
+ public MetaTypeInformation getMetaTypeInformation(Bundle bundle);
+
+ /**
+ * Location of meta type documents. The MetaType Service will process each
+ * entry in the meta type documents directory.
+ */
+ public final static String METATYPE_DOCUMENTS_LOCATION = "OSGI-INF/metatype";
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/ObjectClassDefinition.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/ObjectClassDefinition.java
new file mode 100644
index 000000000..f65f64dbc
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/ObjectClassDefinition.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.metatype;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Description for the data type information of an objectclass.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public interface ObjectClassDefinition {
+ /**
+ * Argument for {@code getAttributeDefinitions(int)}.
+ * <p>
+ * {@code REQUIRED} indicates that only the required definitions are
+ * returned. The value is 1.
+ */
+ public static final int REQUIRED = 1;
+ /**
+ * Argument for {@code getAttributeDefinitions(int)}.
+ * <p>
+ * {@code OPTIONAL} indicates that only the optional definitions are
+ * returned. The value is 2.
+ */
+ public static final int OPTIONAL = 2;
+ /**
+ * Argument for {@code getAttributeDefinitions(int)}.
+ * <p>
+ * {@code ALL} indicates that all the definitions are returned. The value is
+ * -1.
+ */
+ public static final int ALL = 0xFFFFFFFF;
+
+ /**
+ * Return the name of this object class.
+ *
+ * The name may be localized.
+ *
+ * @return The name of this object class.
+ */
+ public String getName();
+
+ /**
+ * Return the id of this object class.
+ *
+ * <p>
+ * {@code ObjectDefintion} objects share a global namespace in the registry.
+ * They share this aspect with LDAP/X.500 attributes. In these standards the
+ * OSI Object Identifier (OID) is used to uniquely identify object classes.
+ * If such an OID exists, (which can be requested at several standard
+ * organisations and many companies already have a node in the tree) it can
+ * be returned here. Otherwise, a unique id should be returned which can be
+ * a java class name (reverse domain name) or generated with a GUID
+ * algorithm. Note that all LDAP defined object classes already have an OID
+ * associated. It is strongly advised to define the object classes from
+ * existing LDAP schemes which will give the OID for free. Many such schemes
+ * exist ranging from postal addresses to DHCP parameters.
+ *
+ * @return The id of this object class.
+ */
+ public String getID();
+
+ /**
+ * Return a description of this object class.
+ *
+ * The description may be localized.
+ *
+ * @return The description of this object class.
+ */
+ public String getDescription();
+
+ /**
+ * Return the attribute definitions for this object class.
+ *
+ * <p>
+ * Return a set of attributes. The filter parameter can distinguish between
+ * {@code ALL},{@code REQUIRED} or the {@code OPTIONAL} attributes.
+ *
+ * @param filter {@code ALL},{@code REQUIRED},{@code OPTIONAL}
+ * @return An array of attribute definitions or {@code null} if no
+ * attributes are selected
+ */
+ public AttributeDefinition[] getAttributeDefinitions(int filter);
+
+ /**
+ * Return an {@code InputStream} object that can be used to create an icon
+ * from.
+ *
+ * <p>
+ * Indicate the size and return an {@code InputStream} object containing an
+ * icon. The returned icon maybe larger or smaller than the indicated size.
+ *
+ * <p>
+ * The icon may depend on the localization.
+ *
+ * @param size Requested size of an icon, e.g. a 16x16 pixels icon then size
+ * = 16
+ * @return An InputStream representing an icon or {@code null}
+ * @throws IOException If the {@code InputStream} cannot be returned.
+ */
+ public InputStream getIcon(int size) throws IOException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/package-info.java
new file mode 100644
index 000000000..3be55f7d3
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * Metatype Package Version 1.2.
+ *
+ * <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.metatype; version="[1.2,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.metatype; version="[1.2,1.3)"}
+ *
+ * @version 1.2
+ * @author $Id$
+ */
+
+package org.osgi.service.metatype;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/packageinfo
new file mode 100644
index 000000000..ef7df68cb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/metatype/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/ProvisioningService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/ProvisioningService.java
new file mode 100644
index 000000000..50e49f069
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/ProvisioningService.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.provisioning;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.zip.ZipInputStream;
+
+/**
+ * Service for managing the initial provisioning information.
+ * <p>
+ * Initial provisioning of an OSGi device is a multi step process that
+ * culminates with the installation and execution of the initial management
+ * agent. At each step of the process, information is collected for the next
+ * step. Multiple bundles may be involved and this service provides a means for
+ * these bundles to exchange information. It also provides a means for the
+ * initial Management Bundle to get its initial configuration information.
+ * <p>
+ * The provisioning information is collected in a {@code Dictionary} object,
+ * called the Provisioning Dictionary. Any bundle that can access the service
+ * can get a reference to this object and read and update provisioning
+ * information. The key of the dictionary is a {@code String} object and the
+ * value is a {@code String} or {@code byte[]} object. The single exception is
+ * the PROVISIONING_UPDATE_COUNT value which is an Integer. The
+ * {@code provisioning} prefix is reserved for keys defined by OSGi, other key
+ * names may be used for implementation dependent provisioning systems.
+ * <p>
+ * Any changes to the provisioning information will be reflected immediately in
+ * all the dictionary objects obtained from the Provisioning Service.
+ * <p>
+ * Because of the specific application of the Provisioning Service, there should
+ * be only one Provisioning Service registered. This restriction will not be
+ * enforced by the Framework. Gateway operators or manufactures should ensure
+ * that a Provisioning Service bundle is not installed on a device that already
+ * has a bundle providing the Provisioning Service.
+ * <p>
+ * The provisioning information has the potential to contain sensitive
+ * information. Also, the ability to modify provisioning information can have
+ * drastic consequences. Thus, only trusted bundles should be allowed to
+ * register and get the Provisioning Service. The {@code ServicePermission} is
+ * used to limit the bundles that can gain access to the Provisioning Service.
+ * There is no check of {@code Permission} objects to read or modify the
+ * provisioning information, so care must be taken not to leak the Provisioning
+ * Dictionary received from {@code getInformation} method.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface ProvisioningService {
+ /**
+ * The key to the provisioning information that uniquely identifies the
+ * Service Platform. The value must be of type {@code String}.
+ */
+ public final static String PROVISIONING_SPID = "provisioning.spid";
+
+ /**
+ * The key to the provisioning information that contains the location of the
+ * provision data provider. The value must be of type {@code String}.
+ */
+ public final static String PROVISIONING_REFERENCE = "provisioning.reference";
+
+ /**
+ * The key to the provisioning information that contains the initial
+ * configuration information of the initial Management Agent. The value will
+ * be of type {@code byte[]}.
+ */
+ public final static String PROVISIONING_AGENT_CONFIG = "provisioning.agent.config";
+
+ /**
+ * The key to the provisioning information that contains the update count of
+ * the info data. Each set of changes to the provisioning information must
+ * end with this value being incremented. The value must be of type
+ * {@code Integer}. This key/value pair is also reflected in the properties
+ * of the ProvisioningService in the service registry.
+ */
+ public final static String PROVISIONING_UPDATE_COUNT = "provisioning.update.count";
+
+ /**
+ * The key to the provisioning information that contains the location of the
+ * bundle to start with {@code AllPermission}. The bundle must have be
+ * previously installed for this entry to have any effect.
+ */
+ public final static String PROVISIONING_START_BUNDLE = "provisioning.start.bundle";
+
+ /**
+ * The key to the provisioning information that contains the root X509
+ * certificate used to establish trust with operator when using HTTPS.
+ */
+ public final static String PROVISIONING_ROOTX509 = "provisioning.rootx509";
+
+ /**
+ * The key to the provisioning information that contains the shared secret
+ * used in conjunction with the RSH protocol.
+ */
+ public final static String PROVISIONING_RSH_SECRET = "provisioning.rsh.secret";
+
+ /**
+ * MIME type to be stored in the extra field of a {@code ZipEntry} object
+ * for String data.
+ */
+ public final static String MIME_STRING = "text/plain;charset=utf-8";
+
+ /**
+ * MIME type to be stored stored in the extra field of a {@code ZipEntry}
+ * object for {@code byte[]} data.
+ */
+ public final static String MIME_BYTE_ARRAY = "application/octet-stream";
+
+ /**
+ * MIME type to be stored in the extra field of a {@code ZipEntry} object
+ * for an installable bundle file. Zip entries of this type will be
+ * installed in the framework, but not started. The entry will also not be
+ * put into the information dictionary.
+ */
+ public final static String MIME_BUNDLE = "application/vnd.osgi.bundle";
+
+ /**
+ * Alternative MIME type to be stored in the extra field of a
+ * {@code ZipEntry} object for an installable bundle file. Zip entries of
+ * this type will be installed in the framework, but not started. The entry
+ * will also not be put into the information dictionary. This alternative
+ * entry is only for backward compatibility, new applications are
+ * recommended to use {@code MIME_BUNDLE}, which is an official IANA MIME
+ * type.
+ *
+ * @since 1.2
+ */
+ public final static String MIME_BUNDLE_ALT = "application/x-osgi-bundle";
+
+ /**
+ * MIME type to be stored in the extra field of a ZipEntry for a String that
+ * represents a URL for a bundle. Zip entries of this type will be used to
+ * install (but not start) a bundle from the URL. The entry will not be put
+ * into the information dictionary.
+ */
+ public final static String MIME_BUNDLE_URL = "text/x-osgi-bundle-url";
+
+ /**
+ * Name of the header that specifies the type information for the ZIP file
+ * entries.
+ *
+ * @since 1.2
+ */
+ public final static String INITIALPROVISIONING_ENTRIES = "InitialProvisioning-Entries";
+
+ /**
+ * Returns a reference to the Provisioning Dictionary. Any change operations
+ * (put and remove) to the dictionary will cause an
+ * {@code UnsupportedOperationException} to be thrown. Changes must be done
+ * using the {@code setInformation} and {@code addInformation} methods of
+ * this service.
+ *
+ * @return A reference to the Provisioning Dictionary.
+ */
+ public Dictionary getInformation();
+
+ /**
+ * Replaces the Provisioning Information dictionary with the key/value pairs
+ * contained in {@code info}. Any key/value pairs not in {@code info} will
+ * be removed from the Provisioning Information dictionary. This method
+ * causes the {@code PROVISIONING_UPDATE_COUNT} to be incremented.
+ *
+ * @param info the new set of Provisioning Information key/value pairs. Any
+ * keys are values that are of an invalid type will be silently
+ * ignored.
+ */
+ public void setInformation(Dictionary info);
+
+ /**
+ * Adds the key/value pairs contained in {@code info} to the Provisioning
+ * Information dictionary. This method causes the
+ * {@code PROVISIONING_UPDATE_COUNT} to be incremented.
+ *
+ * @param info the set of Provisioning Information key/value pairs to add to
+ * the Provisioning Information dictionary. Any keys are values that
+ * are of an invalid type will be silently ignored.
+ */
+ public void addInformation(Dictionary info);
+
+ /**
+ * Processes the {@code ZipInputStream} and extracts information to add to
+ * the Provisioning Information dictionary, as well as, install/update and
+ * start bundles. This method causes the {@code PROVISIONING_UPDATE_COUNT}
+ * to be incremented.
+ *
+ * @param zis the {@code ZipInputStream} that will be used to add key/value
+ * pairs to the Provisioning Information dictionary and install and
+ * start bundles. If a {@code ZipEntry} does not have an
+ * {@code Extra} field that corresponds to one of the four defined
+ * MIME types ({@code MIME_STRING}, {@code MIME_BYTE_ARRAY},
+ * {@code MIME_BUNDLE}, and {@code MIME_BUNDLE_URL}) in will be
+ * silently ignored.
+ * @throws IOException if an error occurs while processing the
+ * ZipInputStream. No additions will be made to the Provisioning
+ * Information dictionary and no bundles must be started or
+ * installed.
+ */
+ public void addInformation(ZipInputStream zis) throws IOException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/package-info.java
new file mode 100644
index 000000000..d47e07a89
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provisioning Package Version 1.2.
+ *
+ * <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.provisioning; version="[1.2,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.provisioning; version="[1.2,1.3)"}
+ *
+ * @version 1.2
+ * @author $Id$
+ */
+
+package org.osgi.service.provisioning;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/packageinfo
new file mode 100644
index 000000000..ef7df68cb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/provisioning/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPAction.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPAction.java
new file mode 100644
index 000000000..f1ba100ae
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPAction.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.upnp;
+
+import java.util.Dictionary;
+
+/**
+ * A UPnP action.
+ *
+ * Each UPnP service contains zero or more actions. Each action may have zero or
+ * more UPnP state variables as arguments.
+ *
+ * @author $Id$
+ */
+public interface UPnPAction {
+ /**
+ * Returns the action name.
+ *
+ * The action name corresponds to the {@code name} field in the
+ * {@code actionList} of the service description.
+ * <ul>
+ * <li>For standard actions defined by a UPnP Forum working committee,
+ * action names must not begin with {@code X_ } nor {@code A_}.</li>
+ * <li>For non-standard actions specified by a UPnP vendor and added to a
+ * standard service, action names must begin with {@code X_}.</li>
+ * </ul>
+ *
+ * <p>
+ * This method must continue to return the action name after the UPnP action
+ * has been removed from the network.
+ *
+ * @return Name of action, must not contain a hyphen character or a hash
+ * character
+ */
+ String getName();
+
+ /**
+ * Returns the name of the designated return argument.
+ * <p>
+ * One of the output arguments can be flagged as a designated return
+ * argument.
+ *
+ * <p>
+ * This method must continue to return the action return argument name after
+ * the UPnP action has been removed from the network.
+ *
+ * @return The name of the designated return argument or {@code null} if
+ * none is marked.
+ */
+ String getReturnArgumentName();
+
+ /**
+ * Lists all input arguments for this action.
+ * <p>
+ * Each action may have zero or more input arguments.
+ *
+ * <p>
+ * This method must continue to return the action input argument names after
+ * the UPnP action has been removed from the network.
+ *
+ * @return Array of input argument names or {@code null} if no input
+ * arguments.
+ *
+ * @see UPnPStateVariable
+ */
+ String[] getInputArgumentNames();
+
+ /**
+ * List all output arguments for this action.
+ *
+ * <p>
+ * This method must continue to return the action output argument names
+ * after the UPnP action has been removed from the network.
+ *
+ * @return Array of output argument names or {@code null} if there are no
+ * output arguments.
+ *
+ * @see UPnPStateVariable
+ */
+ String[] getOutputArgumentNames();
+
+ /**
+ * Finds the state variable associated with an argument name.
+ *
+ * Helps to resolve the association of state variables with argument names
+ * in UPnP actions.
+ *
+ * @param argumentName The name of the UPnP action argument.
+ * @return State variable associated with the named argument or {@code null}
+ * if there is no such argument.
+ *
+ * @throws IllegalStateException if the UPnP action has been removed from
+ * the network.
+ *
+ * @see UPnPStateVariable
+ */
+ UPnPStateVariable getStateVariable(String argumentName);
+
+ /**
+ * Invokes the action.
+ *
+ * The input and output arguments are both passed as {@code Dictionary}
+ * objects. Each entry in the {@code Dictionary} object has a {@code String}
+ * object as key representing the argument name and the value is the
+ * argument itself. The class of an argument value must be assignable from
+ * the class of the associated UPnP state variable.
+ *
+ * The input argument {@code Dictionary} object must contain exactly those
+ * arguments listed by {@code getInputArguments} method. The output argument
+ * {@code Dictionary} object will contain exactly those arguments listed by
+ * {@code getOutputArguments} method.
+ *
+ * @param args A {@code Dictionary} of arguments. Must contain the correct
+ * set and type of arguments for this action. May be {@code null} if
+ * no input arguments exist.
+ *
+ * @return A {@code Dictionary} with the output arguments. {@code null} if
+ * the action has no output arguments.
+ *
+ * @throws UPnPException A UPnP error has occurred.
+ * @throws IllegalStateException if the UPnP action has been removed from
+ * the network.
+ * @throws Exception The execution fails for some reason.
+ *
+ * @see UPnPStateVariable
+ */
+ Dictionary invoke(Dictionary args) throws Exception;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPDevice.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPDevice.java
new file mode 100644
index 000000000..a09c1c2f3
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPDevice.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.upnp;
+
+import java.util.Dictionary;
+
+/**
+ * Represents a UPnP device.
+ *
+ * For each UPnP root and embedded device, an object is registered with the
+ * framework under the {@code UPnPDevice} interface.
+ * <p>
+ * The relationship between a root device and its embedded devices can be
+ * deduced using the {@code UPnPDevice.CHILDREN_UDN} and
+ * {@code UPnPDevice.PARENT_UDN} service registration properties.
+ * <p>
+ * The values of the UPnP property names are defined by the UPnP Forum.
+ * <p>
+ * All values of the UPnP properties are obtained from the device using the
+ * device's default locale.
+ * <p>
+ * If an application wants to query for a set of localized property values, it
+ * has to use the method {@code UPnPDevice.getDescriptions(String locale)}.
+ *
+ * @author $Id$
+ */
+public interface UPnPDevice {
+ /*
+ * Constants for the UPnP device match scale.
+ */
+ /**
+ * Constant for the UPnP device match scale, indicating a generic match for
+ * the device. Value is 1.
+ */
+ int MATCH_GENERIC = 1;
+ /**
+ * Constant for the UPnP device match scale, indicating a match with the
+ * device type. Value is 3.
+ */
+ int MATCH_TYPE = 3;
+ /**
+ * Constant for the UPnP device match scale, indicating a match with the
+ * device model. Value is 7.
+ */
+ int MATCH_MANUFACTURER_MODEL = 7;
+ /**
+ * Constant for the UPnP device match scale, indicating a match with the
+ * device revision. Value is 15.
+ */
+ int MATCH_MANUFACTURER_MODEL_REVISION = 15;
+ /**
+ * Constant for the UPnP device match scale, indicating a match with the
+ * device revision and the serial number. Value is 31.
+ */
+ int MATCH_MANUFACTURER_MODEL_REVISION_SERIAL = 31;
+ /**
+ * Constant for the value of the service property {@code DEVICE_CATEGORY}
+ * used for all UPnP devices. Value is "UPnP".
+ *
+ * @see "org.osgi.service.device.Constants.DEVICE_CATEGORY"
+ */
+ String DEVICE_CATEGORY = "UPnP";
+ /**
+ * The {@code UPnP.export} service property is a hint that marks a device to
+ * be picked up and exported by the UPnP Service. Imported devices do not
+ * have this property set. The registered property requires no value.
+ * <p>
+ * The UPNP_EXPORT string is "UPnP.export".
+ */
+ String UPNP_EXPORT = "UPnP.export";
+ /**
+ * Property key for the Unique Device Name (UDN) property. It is the unique
+ * identifier of an instance of a {@code UPnPDevice}. The value of the
+ * property is a {@code String} object of the Device UDN. Value of the key
+ * is "UPnP.device.UDN". This property must be set.
+ */
+ String UDN = "UPnP.device.UDN";
+ /**
+ * Property key for the Unique Device ID property. This property is an alias
+ * to {@code UPnPDevice.UDN}. It is merely provided for reasons of symmetry
+ * with the {@code UPnPService.ID} property. The value of the property is a
+ * {@code String} object of the Device UDN. The value of the key is
+ * "UPnP.device.UDN".
+ */
+ String ID = UDN;
+ /**
+ * Property key for the UPnP Device Type property. Some standard property
+ * values are defined by the Universal Plug and Play Forum. The type string
+ * also includes a version number as defined in the UPnP specification. This
+ * property must be set.
+ * <p>
+ * For standard devices defined by a UPnP Forum working committee, this must
+ * consist of the following components in the given order separated by
+ * colons:
+ * <ul>
+ * <li>{@code urn}</li>
+ * <li>schemas-upnp-org</li>
+ * <li>{@code device}</li>
+ * <li>a device type suffix</li>
+ * <li>an integer device version</li>
+ * </ul>
+ * For non-standard devices specified by UPnP vendors following components
+ * must be specified in the given order separated by colons:
+ * <ul>
+ * <li>{@code urn}</li>
+ * <li>an ICANN domain name owned by the vendor</li>
+ * <li>{@code device}</li>
+ * <li>a device type suffix</li>
+ * <li>an integer device version</li>
+ * </ul>
+ * <p>
+ * To allow for backward compatibility the UPnP driver must automatically
+ * generate additional Device Type property entries for smaller versions
+ * than the current one. If for example a device announces its type as
+ * version 3, then properties for versions 2 and 1 must be automatically
+ * generated.
+ * <p>
+ * In the case of exporting a UPnPDevice, the highest available version must
+ * be announced on the network.
+ * <p>
+ * Syntax Example: {@code urn:schemas-upnp-org:device:deviceType:v}
+ * <p>
+ * The value is "UPnP.device.type".
+ */
+ String TYPE = "UPnP.device.type";
+ /**
+ * Mandatory property key for the device manufacturer's property. The
+ * property value holds a String representation of the device manufacturer's
+ * name. Value is "UPnP.device.manufacturer".
+ */
+ String MANUFACTURER = "UPnP.device.manufacturer";
+ /**
+ * Mandatory property key for the device model name. The property value
+ * holds a {@code String} object giving more information about the device
+ * model. Value is "UPnP.device.modelName".
+ */
+ String MODEL_NAME = "UPnP.device.modelName";
+ /**
+ * Mandatory property key for a short user friendly version of the device
+ * name. The property value holds a {@code String} object with the user
+ * friendly name of the device. Value is "UPnP.device.friendlyName".
+ */
+ String FRIENDLY_NAME = "UPnP.device.friendlyName";
+ /**
+ * Optional property key for a URL to the device manufacturers Web site. The
+ * value of the property is a {@code String} object representing the URL.
+ * Value is "UPnP.device.manufacturerURL".
+ */
+ String MANUFACTURER_URL = "UPnP.device.manufacturerURL";
+ /**
+ * Optional (but recommended) property key for a {@code String} object with
+ * a long description of the device for the end user. The value is
+ * "UPnP.device.modelDescription".
+ */
+ String MODEL_DESCRIPTION = "UPnP.device.modelDescription";
+ /**
+ * Optional (but recommended) property key for a {@code String} class typed
+ * property holding the model number of the device. Value is
+ * "UPnP.device.modelNumber".
+ */
+ String MODEL_NUMBER = "UPnP.device.modelNumber";
+ /**
+ * Optional property key for a {@code String} typed property holding a
+ * string representing the URL to the Web site for this model. Value is
+ * "UPnP.device.modelURL".
+ */
+ String MODEL_URL = "UPnP.device.modelURL";
+ /**
+ * Optional (but recommended) property key for a {@code String} typed
+ * property holding the serial number of the device. Value is
+ * "UPnP.device.serialNumber".
+ */
+ String SERIAL_NUMBER = "UPnP.device.serialNumber";
+ /**
+ * Optional property key for a {@code String} typed property holding the
+ * Universal Product Code (UPC) of the device. Value is "UPnP.device.UPC".
+ */
+ String UPC = "UPnP.device.UPC";
+ /**
+ * Optional (but recommended) property key for a {@code String} typed
+ * property holding a string representing the URL to a device representation
+ * Web page. Value is "UPnP.presentationURL".
+ */
+ String PRESENTATION_URL = "UPnP.presentationURL";
+ /**
+ * The property key that must be set for all embedded devices. It contains
+ * the UDN of the parent device. The property is not set for root devices.
+ * The value is "UPnP.device.parentUDN".
+ */
+ String PARENT_UDN = "UPnP.device.parentUDN";
+ /**
+ * The property key that must be set for all devices containing other
+ * embedded devices.
+ * <p>
+ * The value is an array of UDNs for each of the device's children (
+ * {@code String[]}). The array contains UDNs for the immediate descendants
+ * only.
+ * </p>
+ * <p>
+ * If an embedded device in turn contains embedded devices, the latter are
+ * not included in the array.
+ * </p>
+ * The UPnP Specification does not encourage more than two levels of
+ * nesting.
+ * <p>
+ * The property is not set if the device does not contain embedded devices.
+ * <p>
+ * The property is of type {@code String[]}. Value is
+ * "UPnP.device.childrenUDN"
+ */
+ String CHILDREN_UDN = "UPnP.device.childrenUDN";
+
+ /**
+ * Locates a specific service by its service id.
+ *
+ * @param serviceId The service id
+ * @return The requested service or null if not found.
+ *
+ * @throws IllegalStateException if the UPnP device has been removed from
+ * the network.
+ */
+ UPnPService getService(String serviceId);
+
+ /**
+ * Lists all services provided by this device.
+ *
+ * @return Array of services or {@code null} if no services are available.
+ *
+ * @throws IllegalStateException if the UPnP device has been removed from
+ * the network.
+ */
+ UPnPService[] getServices();
+
+ /**
+ * Lists all icons for this device in a given locale.
+ *
+ * The UPnP specification allows a device to present different icons based
+ * on the client's locale.
+ *
+ * @param locale A language tag as defined by RFC 1766 and maintained by ISO
+ * 639. Examples include "{@code de}", "{@code en}" or "
+ * {@code en-US}". The default locale of the device is specified by
+ * passing a {@code null} argument.
+ *
+ * @return Array of icons or null if no icons are available.
+ *
+ * @throws IllegalStateException if the UPnP device has been removed from
+ * the network.
+ */
+ UPnPIcon[] getIcons(String locale);
+
+ /**
+ * Get a set of localized UPnP properties.
+ *
+ * The UPnP specification allows a device to present different device
+ * properties based on the client's locale. The properties used to register
+ * the UPnPDevice service in the OSGi registry are based on the device's
+ * default locale. To obtain a localized set of the properties, an
+ * application can use this method.
+ * <p>
+ * Not all properties might be available in all locales. This method does
+ * <b>not </b> substitute missing properties with their default locale
+ * versions.
+ * <p>
+ * This method must continue to return the properties after the UPnP device
+ * has been removed from the network.
+ *
+ * @param locale A language tag as defined by RFC 1766 and maintained by ISO
+ * 639. Examples include "{@code de}", "{@code en}" or "
+ * {@code en-US}". The default locale of the device is specified by
+ * passing a {@code null} argument.
+ * @return Dictionary mapping property name Strings to property value
+ * Strings
+ *
+ */
+ Dictionary getDescriptions(String locale);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPEventListener.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPEventListener.java
new file mode 100644
index 000000000..0daf43c61
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPEventListener.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.upnp;
+
+import java.util.Dictionary;
+
+/**
+ * UPnP Events are mapped and delivered to applications according to the OSGi
+ * whiteboard model. An application that wishes to be notified of events
+ * generated by a particular UPnP Device registers a service extending this
+ * interface.
+ * <p>
+ * The notification call from the UPnP Service to any {@code UPnPEventListener}
+ * object must be done asynchronous with respect to the originator (in a
+ * separate thread).
+ * <p>
+ * Upon registration of the UPnP Event Listener service with the Framework, the
+ * service is notified for each variable which it listens for with an initial
+ * event containing the current value of the variable. Subsequent notifications
+ * only happen on changes of the value of the variable.
+ * <p>
+ * A UPnP Event Listener service filter the events it receives. This event set
+ * is limited using a standard framework filter expression which is specified
+ * when the listener service is registered.
+ * <p>
+ * The filter is specified in a property named "upnp.filter" and has as a value
+ * an object of type {@code org.osgi.framework.Filter}.
+ * <p>
+ * When the Filter is evaluated, the folowing keywords are recognized as defined
+ * as literal constants in the {@code UPnPDevice} class.
+ * <p>
+ * The valid subset of properties for the registration of UPnP Event Listener
+ * services are:
+ * <ul>
+ * <li>{@code UPnPDevice.TYPE}-- Which type of device to listen for events.</li>
+ * <li>{@code UPnPDevice.ID}-- The ID of a specific device to listen for events.
+ * </li>
+ * <li>{@code UPnPService.TYPE}-- The type of a specific service to listen for
+ * events.</li>
+ * <li>{@code UPnPService.ID}-- The ID of a specific service to listen for
+ * events.</li>
+ * </ul>
+ *
+ * @author $Id$
+ */
+public interface UPnPEventListener {
+ /**
+ * Key for a service property having a value that is an object of type
+ * {@code org.osgi.framework.Filter} and that is used to limit received
+ * events.
+ */
+ static final String UPNP_FILTER = "upnp.filter";
+
+ /**
+ * Callback method that is invoked for received events.
+ *
+ * The events are collected in a {@code Dictionary} object. Each entry has a
+ * {@code String} key representing the event name (= state variable name)
+ * and the new value of the state variable. The class of the value object
+ * must match the class specified by the UPnP State Variable associated with
+ * the event. This method must be called asynchronously
+ *
+ * @param deviceId ID of the device sending the events
+ * @param serviceId ID of the service sending the events
+ * @param events {@code Dictionary} object containing the new values for the
+ * state variables that have changed.
+ *
+ *
+ */
+ void notifyUPnPEvent(String deviceId, String serviceId, Dictionary events);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPException.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPException.java
new file mode 100644
index 000000000..ffd3b84b0
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPException.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.upnp;
+
+/**
+ * There are several defined error situations describing UPnP problems while a
+ * control point invokes actions to UPnPDevices.
+ *
+ * @since 1.1
+ * @author $Id$
+ */
+public class UPnPException extends Exception {
+
+ static final long serialVersionUID = -262013318122195146L;
+
+ /**
+ * No Action found by that name at this service.
+ */
+ public final static int INVALID_ACTION = 401;
+
+ /**
+ * Not enough arguments, too many arguments with a specific name, or one of
+ * more of the arguments are of the wrong type.
+ */
+ public final static int INVALID_ARGS = 402;
+
+ /**
+ * The different end-points are no longer in synchronization.
+ */
+ public final static int INVALID_SEQUENCE_NUMBER = 403;
+
+ /**
+ * Refers to a non existing variable.
+ */
+ public final static int INVALID_VARIABLE = 404;
+
+ /**
+ * The invoked action failed during execution.
+ */
+ public final static int DEVICE_INTERNAL_ERROR = 501;
+
+ /**
+ * Key for an error information that is an int type variable and that is
+ * used to identify occurred errors.
+ */
+ private final int errorCode;
+
+ /**
+ * This constructor creates a {@code UPnPException} on the specified error
+ * code and error description.
+ *
+ * @param errorCode error code which defined by UPnP Device Architecture
+ * V1.0.
+ * @param errorDescription error description which explain the type of
+ * problem.
+ */
+ public UPnPException(int errorCode, String errorDescription) {
+ super(errorDescription);
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * This constructor creates a {@code UPnPException} on the specified error
+ * code, error description and error cause.
+ *
+ * @param errorCode error code which defined by UPnP Device Architecture
+ * V1.0.
+ * @param errorDescription error description which explain the type of the
+ * problem.
+ * @param errorCause cause of that {@code UPnPException}.
+ *
+ * @since 1.2
+ */
+ public UPnPException(int errorCode, String errorDescription, Throwable errorCause) {
+ super(errorDescription, errorCause);
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Returns the UPnP Error Code occurred by UPnPDevices during invocation.
+ *
+ * @return The UPnPErrorCode defined by a UPnP Forum working committee or
+ * specified by a UPnP vendor.
+ *
+ * @since 1.2
+ */
+ public int getUPnPErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * Returns the UPnPError Code occurred by UPnPDevices during invocation.
+ *
+ * @return The UPnPErrorCode defined by a UPnP Forum working committee or
+ * specified by a UPnP vendor.
+ * @deprecated As of version 1.2, replaced by {@link #getUPnPErrorCode()}
+ */
+ public int getUPnPError_Code() {
+ return getUPnPErrorCode();
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPIcon.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPIcon.java
new file mode 100644
index 000000000..dd5af435f
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPIcon.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.upnp;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A UPnP icon representation.
+ *
+ * Each UPnP device can contain zero or more icons.
+ *
+ * @author $Id$
+ */
+public interface UPnPIcon {
+ /**
+ * Returns the MIME type of the icon.
+ *
+ * This method returns the format in which the icon graphics, read from the
+ * {@code InputStream} object obtained by the {@code getInputStream()}
+ * method, is encoded.
+ * <p>
+ * The format of the returned string is in accordance to RFC2046. A list of
+ * valid MIME types is maintained by the <a
+ * href="http://www.iana.org/assignments/media-types/">IANA</a>.
+ * <p>
+ * Typical values returned include: "image/jpeg" or "image/gif"
+ *
+ * <p>
+ * This method must continue to return the icon MIME type after the UPnP
+ * device has been removed from the network.
+ *
+ * @return The MIME type of the encoded icon.
+ */
+ String getMimeType();
+
+ /**
+ * Returns the width of the icon in pixels.
+ *
+ * If the actual width of the icon is unknown, -1 is returned.
+ *
+ * <p>
+ * This method must continue to return the icon width after the UPnP device
+ * has been removed from the network.
+ *
+ * @return The width in pixels, or -1 if unknown.
+ */
+ int getWidth();
+
+ /**
+ * Returns the height of the icon in pixels.
+ *
+ * If the actual height of the icon is unknown, -1 is returned.
+ *
+ * <p>
+ * This method must continue to return the icon height after the UPnP device
+ * has been removed from the network.
+ *
+ * @return The height in pixels, or -1 if unknown.
+ */
+ int getHeight();
+
+ /**
+ * Returns the size of the icon in bytes.
+ *
+ * This method returns the number of bytes of the icon available to read
+ * from the {@code InputStream} object obtained by the
+ * {@code getInputStream()} method. If the actual size can not be
+ * determined, -1 is returned.
+ *
+ * @return The icon size in bytes, or -1 if the size is unknown.
+ *
+ * @throws IllegalStateException if the UPnP device has been removed from
+ * the network.
+ */
+ int getSize();
+
+ /**
+ * Returns the color depth of the icon in bits.
+ *
+ * <p>
+ * This method must continue to return the icon depth after the UPnP device
+ * has been removed from the network.
+ *
+ * @return The color depth in bits. If the actual color depth of the icon is
+ * unknown, -1 is returned.
+ */
+ int getDepth();
+
+ /**
+ * Returns an {@code InputStream} object for the icon data.
+ *
+ * The {@code InputStream} object provides a way for a client to read the
+ * actual icon graphics data. The number of bytes available from this
+ * {@code InputStream} object can be determined via the {@code getSize()}
+ * method. The format of the data encoded can be determined by the MIME type
+ * available via the {@code getMimeType()} method.
+ *
+ * @return An InputStream to read the icon graphics data from.
+ *
+ * @throws IOException If the {@code InputStream} cannot be returned.
+ * @throws IllegalStateException if the UPnP device has been removed from
+ * the network.
+ *
+ * @see UPnPIcon#getMimeType()
+ */
+ InputStream getInputStream() throws IOException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPLocalStateVariable.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPLocalStateVariable.java
new file mode 100644
index 000000000..351a0315b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPLocalStateVariable.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) OSGi Alliance (2005, 2013). 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.
+ */
+/**
+ * To keep the current values getting from subscribed UPnPDevices.
+ *
+ * The actual values of the UPnPStateVaraible are passed as Java object type.
+ *
+ * @since 1.1
+ **/
+
+package org.osgi.service.upnp;
+
+/**
+ * A local UPnP state variable which allows the value of the state variable to
+ * be queried.
+ *
+ * @since 1.1
+ *
+ * @author $Id$
+ */
+public interface UPnPLocalStateVariable extends UPnPStateVariable {
+ /**
+ * This method will keep the current values of UPnPStateVariables of a
+ * UPnPDevice whenever UPnPStateVariable's value is changed , this method
+ * must be called.
+ *
+ * @return {@code Object} current value of UPnPStateVariable. if the current
+ * value is initialized with the default value defined UPnP service
+ * description.
+ *
+ * @throws IllegalStateException if the UPnP state variable has been
+ * removed.
+ */
+ public Object getCurrentValue();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPService.java
new file mode 100644
index 000000000..08eea1f04
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPService.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.upnp;
+
+/**
+ * A representation of a UPnP Service.
+ *
+ * Each UPnP device contains zero or more services. The UPnP description for a
+ * service defines actions, their arguments, and event characteristics.
+ *
+ * @author $Id$
+ */
+public interface UPnPService {
+ /**
+ * Property key for the optional service type uri.
+ *
+ * The service type property is used when registering UPnP Device services
+ * and UPnP Event Listener services. The property contains a {@code String}
+ * array ({@code String[]}) of service types. A UPnP Device service can thus
+ * announce what types of services it contains. A UPnP Event Listener
+ * service can announce for what type of UPnP services it wants
+ * notifications. The service version is encoded in the type string as
+ * specified in the UPnP specification. A {@code null} value is a wildcard,
+ * matching <b>all </b> service types. Value is "UPnP.service.type".
+ *
+ * @see UPnPService#getType()
+ */
+ String TYPE = "UPnP.service.type";
+ /**
+ * Property key for the optional service id.
+ *
+ * The service id property is used when registering UPnP Device services or
+ * UPnP Event Listener services. The value of the property contains a
+ * {@code String} array ({@code String[]}) of service ids. A UPnP Device
+ * service can thus announce what service ids it contains. A UPnP Event
+ * Listener service can announce for what UPnP service ids it wants
+ * notifications. A service id does <b>not </b> have to be universally
+ * unique. It must be unique only within a device. A {@code null} value is a
+ * wildcard, matching <b>all </b> services. The value is "UPnP.service.id".
+ */
+ String ID = "UPnP.service.id";
+
+ /**
+ * Returns the {@code serviceId} field in the UPnP service description.
+ *
+ *
+ * <p>
+ * For standard services defined by a UPnP Forum working committee, the
+ * serviceId must contain the following components in the indicated order:
+ * <ul>
+ * <li>{@code urn:upnp-org:serviceId:}</li>
+ * <li>service ID suffix</li>
+ * </ul>
+ * Example: {@code urn:upnp-org:serviceId:serviceID}.
+ *
+ * <p>
+ * Note that {@code upnp-org} is used instead of {@code schemas-upnp-org} in
+ * this example because an XML schema is not defined for each serviceId.
+ * </p>
+ *
+ * <p>
+ * For non-standard services specified by UPnP vendors, the serviceId must
+ * contain the following components in the indicated order:
+ * <ul>
+ * <li>{@code urn:}</li>
+ * <li>ICANN domain name owned by the vendor</li>
+ * <li>{@code :serviceId:}</li>
+ * <li>service ID suffix</li>
+ * </ul>
+ * Example: {@code urn:domain-name:serviceId:serviceID}.
+ *
+ * <p>
+ * This method must continue to return the service id after the UPnP service
+ * has been removed from the network.
+ *
+ * @return The service ID suffix defined by a UPnP Forum working committee
+ * or specified by a UPnP vendor. Must be &lt;= 64 characters.
+ * Single URI.
+ */
+ String getId();
+
+ /**
+ * Returns the {@code serviceType} field in the UPnP service description.
+ *
+ * <p>
+ * For standard services defined by a UPnP Forum working committee, the
+ * serviceType must contain the following components in the indicated order:
+ * <ul>
+ * <li>{@code urn:schemas-upnp-org:service:}</li>
+ * <li>service type suffix:</li>
+ * <li>integer service version</li>
+ * </ul>
+ * Example: {@code urn:schemas-upnp-org:service:serviceType:v}.
+ *
+ * <p>
+ * For non-standard services specified by UPnP vendors, the
+ * {@code serviceType} must contain the following components in the
+ * indicated order:
+ * <ul>
+ * <li>{@code urn:}</li>
+ * <li>ICANN domain name owned by the vendor</li>
+ * <li>{@code :service:}</li>
+ * <li>service type suffix:</li>
+ * <li>integer service version</li>
+ * </ul>
+ * Example: {@code urn:domain-name:service:serviceType:v}.
+ *
+ * <p>
+ * This method must continue to return the service type after the UPnP
+ * service has been removed from the network.
+ *
+ * @return The service type suffix defined by a UPnP Forum working committee
+ * or specified by a UPnP vendor. Must be &lt;= 64 characters, not
+ * including the version suffix and separating colon. Single URI.
+ */
+ String getType();
+
+ /**
+ * Returns the version suffix encoded in the {@code serviceType} field in
+ * the UPnP service description.
+ *
+ * <p>
+ * This method must continue to return the service version after the UPnP
+ * service has been removed from the network.
+ *
+ * @return The integer service version defined by a UPnP Forum working
+ * committee or specified by a UPnP vendor.
+ */
+ String getVersion();
+
+ /**
+ * Locates a specific action by name.
+ *
+ * Looks up an action by its name.
+ *
+ * @param name Name of action. Must not contain hyphen or hash characters.
+ * Should be &lt; 32 characters.
+ *
+ * @return The requested action or {@code null} if no action is found.
+ *
+ * @throws IllegalStateException if the UPnP service has been removed from
+ * the network.
+ */
+ UPnPAction getAction(String name);
+
+ /**
+ * Lists all actions provided by this service.
+ *
+ * @return Array of actions ({@code UPnPAction[]} )or {@code null} if no
+ * actions are defined for this service.
+ *
+ * @throws IllegalStateException if the UPnP service has been removed from
+ * the network.
+ */
+ UPnPAction[] getActions();
+
+ /**
+ * Lists all {@code UPnPStateVariable} objects provided by this service.
+ *
+ * @return Array of state variables or {@code null} if none are defined for
+ * this service.
+ *
+ * @throws IllegalStateException if the UPnP service has been removed from
+ * the network.
+ */
+ UPnPStateVariable[] getStateVariables();
+
+ /**
+ * Gets a {@code UPnPStateVariable} objects provided by this service by name
+ *
+ * @param name Name of the State Variable
+ *
+ * @return State variable or {@code null} if no such state variable exists
+ * for this service.
+ *
+ * @throws IllegalStateException if the UPnP service has been removed from
+ * the network.
+ */
+ UPnPStateVariable getStateVariable(String name);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPStateVariable.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPStateVariable.java
new file mode 100644
index 000000000..1ebafb56d
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/UPnPStateVariable.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.upnp;
+
+/**
+ * The meta-information of a UPnP state variable as declared in the device's
+ * service state table (SST).
+ * <p>
+ * Method calls to interact with a device (e.g. {@code UPnPAction.invoke(...);})
+ * use this class to encapsulate meta information about the input and output
+ * arguments.
+ * <p>
+ * The actual values of the arguments are passed as Java objects. The mapping of
+ * types from UPnP data types to Java data types is described with the field
+ * definitions.
+ *
+ * @author $Id$
+ */
+public interface UPnPStateVariable {
+ /**
+ * Unsigned 1 {@code Byte} int.
+ * <p>
+ * Mapped to an {@code Integer} object.
+ */
+ static final String TYPE_UI1 = "ui1";
+ /**
+ * Unsigned 2 Byte int.
+ * <p>
+ * Mapped to {@code Integer} object.
+ */
+ static final String TYPE_UI2 = "ui2";
+ /**
+ * Unsigned 4 Byte int.
+ * <p>
+ * Mapped to {@code Long} object.
+ */
+ static final String TYPE_UI4 = "ui4";
+ /**
+ * 1 Byte int.
+ * <p>
+ * Mapped to {@code Integer} object.
+ */
+ static final String TYPE_I1 = "i1";
+ /**
+ * 2 Byte int.
+ * <p>
+ * Mapped to {@code Integer} object.
+ */
+ static final String TYPE_I2 = "i2";
+ /**
+ * 4 Byte int.
+ * <p>
+ * Must be between -2147483648 and 2147483647
+ * <p>
+ * Mapped to {@code Integer} object.
+ */
+ static final String TYPE_I4 = "i4";
+ /**
+ * Integer number.
+ * <p>
+ * Mapped to {@code Integer} object.
+ */
+ static final String TYPE_INT = "int";
+ /**
+ * 4 Byte float.
+ * <p>
+ * Same format as float. Must be between 3.40282347E+38 to 1.17549435E-38.
+ * <p>
+ * Mapped to {@code Float} object.
+ */
+ static final String TYPE_R4 = "r4";
+ /**
+ * 8 Byte float.
+ * <p>
+ * Same format as float. Must be between -1.79769313486232E308 and
+ * -4.94065645841247E-324 for negative values, and between
+ * 4.94065645841247E-324 and 1.79769313486232E308 for positive values, i.e.,
+ * IEEE 64-bit (8-Byte) double.
+ * <p>
+ * Mapped to {@code Double} object.
+ */
+ static final String TYPE_R8 = "r8";
+ /**
+ * Same as r8.
+ * <p>
+ * Mapped to {@code Double} object.
+ */
+ static final String TYPE_NUMBER = "number";
+ /**
+ * Same as r8 but no more than 14 digits to the left of the decimal point
+ * and no more than 4 to the right.
+ * <p>
+ * Mapped to {@code Double} object.
+ */
+ static final String TYPE_FIXED_14_4 = "fixed.14.4";
+ /**
+ * Floating-point number.
+ * <p>
+ * Mantissa (left of the decimal) and/or exponent may have a leading sign.
+ * Mantissa and/or exponent may have leading zeros. Decimal character in
+ * mantissa is a period, i.e., whole digits in mantissa separated from
+ * fractional digits by period. Mantissa separated from exponent by E. (No
+ * currency symbol.) (No grouping of digits in the mantissa, e.g., no
+ * commas.)
+ * <p>
+ * Mapped to {@code Float} object.
+ */
+ static final String TYPE_FLOAT = "float";
+ /**
+ * Unicode string.
+ * <p>
+ * One character long.
+ * <p>
+ * Mapped to {@code Character} object.
+ */
+ static final String TYPE_CHAR = "char";
+ /**
+ * Unicode string.
+ * <p>
+ * No limit on length.
+ * <p>
+ * Mapped to {@code String} object.
+ */
+ static final String TYPE_STRING = "string";
+ /**
+ * A calendar date.
+ * <p>
+ * Date in a subset of ISO 8601 format without time data.
+ * <p>
+ * See <a
+ * href="http://www.w3.org/TR/xmlschema-2/#date">http://www.w3.org/TR/
+ * xmlschema-2/#date </a>.
+ * <p>
+ * Mapped to {@code java.util.Date} object. Always 00:00 hours.
+ */
+ static final String TYPE_DATE = "date";
+ /**
+ * A specific instant of time.
+ * <p>
+ * Date in ISO 8601 format with optional time but no time zone.
+ * <p>
+ * See <a
+ * href="http://www.w3.org/TR/xmlschema-2/#dateTime">http://www.w3.org
+ * /TR/xmlschema-2/#dateTime </a>.
+ * <p>
+ * Mapped to {@code java.util.Date} object using default time zone.
+ */
+ static final String TYPE_DATETIME = "dateTime";
+ /**
+ * A specific instant of time.
+ * <p>
+ * Date in ISO 8601 format with optional time and optional time zone.
+ * <p>
+ * See <a
+ * href="http://www.w3.org/TR/xmlschema-2/#dateTime">http://www.w3.org
+ * /TR/xmlschema-2/#dateTime </a>.
+ * <p>
+ * Mapped to {@code java.util.Date} object adjusted to default time zone.
+ */
+ static final String TYPE_DATETIME_TZ = "dateTime.tz";
+ /**
+ * An instant of time that recurs every day.
+ * <p>
+ * Time in a subset of ISO 8601 format with no date and no time zone.
+ * <p>
+ * See <a
+ * href="http://www.w3.org/TR/xmlschema-2/#dateTime">http://www.w3.org
+ * /TR/xmlschema-2/#time </a>.
+ * <p>
+ * Mapped to {@code Long}. Converted to milliseconds since midnight.
+ */
+ static final String TYPE_TIME = "time";
+ /**
+ * An instant of time that recurs every day.
+ * <p>
+ * Time in a subset of ISO 8601 format with optional time zone but no date.
+ * <p>
+ * See <a
+ * href="http://www.w3.org/TR/xmlschema-2/#dateTime">http://www.w3.org
+ * /TR/xmlschema-2/#time </a>.
+ * <p>
+ * Mapped to {@code Long} object. Converted to milliseconds since midnight
+ * and adjusted to default time zone, wrapping at 0 and 24*60*60*1000.
+ */
+ static final String TYPE_TIME_TZ = "time.tz";
+ /**
+ * True or false.
+ * <p>
+ * Mapped to {@code Boolean} object.
+ */
+ static final String TYPE_BOOLEAN = "boolean";
+ /**
+ * MIME-style Base64 encoded binary BLOB.
+ * <p>
+ * Takes 3 Bytes, splits them into 4 parts, and maps each 6 bit piece to an
+ * octet. (3 octets are encoded as 4.) No limit on size.
+ * <p>
+ * Mapped to {@code byte[]} object. The Java byte array will hold the
+ * decoded content of the BLOB.
+ */
+ static final String TYPE_BIN_BASE64 = "bin.base64";
+ /**
+ * Hexadecimal digits representing octets.
+ * <p>
+ * Treats each nibble as a hex digit and encodes as a separate Byte. (1
+ * octet is encoded as 2.) No limit on size.
+ * <p>
+ * Mapped to {@code byte[]} object. The Java byte array will hold the
+ * decoded content of the BLOB.
+ */
+ static final String TYPE_BIN_HEX = "bin.hex";
+ /**
+ * Universal Resource Identifier.
+ * <p>
+ * Mapped to {@code String} object.
+ */
+ static final String TYPE_URI = "uri";
+ /**
+ * Universally Unique ID.
+ * <p>
+ * Hexadecimal digits representing octets. Optional embedded hyphens are
+ * ignored.
+ * <p>
+ * Mapped to {@code String} object.
+ */
+ static final String TYPE_UUID = "uuid";
+
+ /**
+ * Returns the variable name.
+ *
+ * <ul>
+ * <li>All standard variables defined by a UPnP Forum working committee must
+ * not begin with {@code X_} nor {@code A_}.</li>
+ * <li>All non-standard variables specified by a UPnP vendor and added to a
+ * standard service must begin with {@code X_}.</li>
+ * </ul>
+ *
+ * <p>
+ * This method must continue to return the state variable name after the
+ * UPnP state variable has been removed from the network.
+ *
+ * @return Name of state variable. Must not contain a hyphen character nor a
+ * hash character. Should be &lt; 32 characters.
+ */
+ String getName();
+
+ /**
+ * Returns the Java class associated with the UPnP data type of this state
+ * variable.
+ * <P>
+ * Mapping between the UPnP data types and Java classes is performed
+ * according to the schema mentioned above.
+ *
+ * <pre>
+ *
+ * Integer ui1, ui2, i1, i2, i4, int
+ * Long ui4, time, time.tz
+ * Float r4, float
+ * Double r8, number, fixed.14.4
+ * Character char
+ * String string, uri, uuid
+ * Date date, dateTime, dateTime.tz
+ * Boolean boolean
+ * byte[] bin.base64, bin.hex
+ *
+ * </pre>
+ *
+ * <p>
+ * This method must continue to return the state variable java type after
+ * the UPnP state variable has been removed from the network.
+ *
+ * @return A class object corresponding to the Java type of this argument.
+ */
+ Class getJavaDataType();
+
+ /**
+ * Returns the UPnP type of this state variable. Valid types are defined as
+ * constants.
+ *
+ * <p>
+ * This method must continue to return the state variable UPnP data type
+ * after the UPnP state variable has been removed from the network.
+ *
+ * @return The UPnP data type of this state variable, as defined in above
+ * constants.
+ */
+ String getUPnPDataType();
+
+ /**
+ * Returns the default value, if defined.
+ *
+ * <p>
+ * This method must continue to return the state variable default value
+ * after the UPnP state variable has been removed from the network.
+ *
+ * @return The default value or {@code null} if not defined. The type of the
+ * returned object can be determined by {@code getJavaDataType}.
+ */
+ Object getDefaultValue();
+
+ /**
+ * Returns the allowed values, if defined. Allowed values can be defined
+ * only for String types.
+ *
+ * <p>
+ * This method must continue to return the state variable allowed values
+ * after the UPnP state variable has been removed from the network.
+ *
+ * @return The allowed values or {@code null} if not defined. Should be less
+ * than 32 characters.
+ */
+ String[] getAllowedValues();
+
+ /**
+ * Returns the minimum value, if defined. Minimum values can only be defined
+ * for numeric types.
+ *
+ * <p>
+ * This method must continue to return the state variable minimum value
+ * after the UPnP state variable has been removed from the network.
+ *
+ * @return The minimum value or {@code null} if not defined.
+ */
+ Number getMinimum();
+
+ /**
+ * Returns the maximum value, if defined. Maximum values can only be defined
+ * for numeric types.
+ *
+ * <p>
+ * This method must continue to return the state variable maximum value
+ * after the UPnP state variable has been removed from the network.
+ *
+ * @return The maximum value or {@code null} if not defined.
+ */
+ Number getMaximum();
+
+ /**
+ * Returns the size of an increment operation, if defined. Step sizes can be
+ * defined only for numeric types.
+ *
+ * <p>
+ * This method must continue to return the step size after the UPnP state
+ * variable has been removed from the network.
+ *
+ * @return The increment size or null if not defined.
+ */
+ Number getStep();
+
+ /**
+ * Tells if this StateVariable can be used as an event source.
+ *
+ * If the StateVariable is eventable, an event listener service can be
+ * registered to be notified when changes to the variable appear.
+ *
+ * <p>
+ * This method must continue to return the correct value after the UPnP
+ * state variable has been removed from the network.
+ *
+ * @return {@code true} if the {@code StateVariable} generates events,
+ * {@code false} otherwise.
+ */
+ boolean sendsEvents();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/package-info.java
new file mode 100644
index 000000000..141651627
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * UPnP Package Version 1.2.
+ *
+ * <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.upnp; version="[1.2,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.upnp; version="[1.2,1.3)"}
+ *
+ * @version 1.2
+ * @author $Id$
+ */
+
+package org.osgi.service.upnp;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/packageinfo
new file mode 100644
index 000000000..ef7df68cb
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/upnp/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Authorization.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Authorization.java
new file mode 100644
index 000000000..4786641d1
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Authorization.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+/**
+ * The {@code Authorization} interface encapsulates an authorization context on
+ * which bundles can base authorization decisions, where appropriate.
+ * <p>
+ * Bundles associate the privilege to access restricted resources or operations
+ * with roles. Before granting access to a restricted resource or operation, a
+ * bundle will check if the {@code Authorization} object passed to it possess
+ * the required role, by calling its {@code hasRole} method.
+ * <p>
+ * Authorization contexts are instantiated by calling the
+ * {@link UserAdmin#getAuthorization(User)} method.
+ *
+ * <p>
+ * <i>Trusting Authorization objects </i>
+ * <p>
+ * There are no restrictions regarding the creation of {@code Authorization}
+ * objects. Hence, a service must only accept {@code Authorization} objects from
+ * bundles that has been authorized to use the service using code based (or Java
+ * 2) permissions.
+ *
+ * <p>
+ * In some cases it is useful to use {@code ServicePermission} to do the code
+ * based access control. A service basing user access control on
+ * {@code Authorization} objects passed to it, will then require that a calling
+ * bundle has the {@code ServicePermission} to get the service in question. This
+ * is the most convenient way. The OSGi environment will do the code based
+ * permission check when the calling bundle attempts to get the service from the
+ * service registry.
+ * <p>
+ * Example: A servlet using a service on a user's behalf. The bundle with the
+ * servlet must be given the {@code ServicePermission} to get the Http Service.
+ * <p>
+ * However, in some cases the code based permission checks need to be more
+ * fine-grained. A service might allow all bundles to get it, but require
+ * certain code based permissions for some of its methods.
+ * <p>
+ * Example: A servlet using a service on a user's behalf, where some service
+ * functionality is open to anyone, and some is restricted by code based
+ * permissions. When a restricted method is called (e.g., one handing over an
+ * {@code Authorization} object), the service explicitly checks that the calling
+ * bundle has permission to make the call.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface Authorization {
+ /**
+ * Gets the name of the {@link User} that this {@code Authorization} context
+ * was created for.
+ *
+ * @return The name of the {@link User} object that this
+ * {@code Authorization} context was created for, or {@code null} if
+ * no user was specified when this {@code Authorization} context was
+ * created.
+ */
+ public String getName();
+
+ /**
+ * Checks if the role with the specified name is implied by this
+ * {@code Authorization} context.
+ * <p>
+ *
+ * Bundles must define globally unique role names that are associated with
+ * the privilege of accessing restricted resources or operations. Operators
+ * will grant users access to these resources, by creating a {@link Group}
+ * object for each role and adding {@link User} objects to it.
+ *
+ * @param name The name of the role to check for.
+ *
+ * @return {@code true} if this {@code Authorization} context implies the
+ * specified role, otherwise {@code false}.
+ */
+ public boolean hasRole(String name);
+
+ /**
+ * Gets the names of all roles implied by this {@code Authorization}
+ * context.
+ *
+ * @return The names of all roles implied by this {@code Authorization}
+ * context, or {@code null} if no roles are in the context. The
+ * predefined role {@code user.anyone} will not be included in this
+ * list.
+ */
+ public String[] getRoles();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Group.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Group.java
new file mode 100644
index 000000000..0ffc7e843
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Group.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+/**
+ * A named grouping of roles ({@code Role} objects).
+ * <p>
+ * Whether or not a given {@code Authorization} context implies a {@code Group}
+ * object depends on the members of that {@code Group} object.
+ * <p>
+ * A {@code Group} object can have two kinds of members: <i>basic </i> and
+ * <i>required </i>. A {@code Group} object is implied by an
+ * {@code Authorization} context if all of its required members are implied and
+ * at least one of its basic members is implied.
+ * <p>
+ * A {@code Group} object must contain at least one basic member in order to be
+ * implied. In other words, a {@code Group} object without any basic member
+ * roles is never implied by any {@code Authorization} context.
+ * <p>
+ * A {@code User} object always implies itself.
+ * <p>
+ * No loop detection is performed when adding members to {@code Group} objects,
+ * which means that it is possible to create circular implications. Loop
+ * detection is instead done when roles are checked. The semantics is that if a
+ * role depends on itself (i.e., there is an implication loop), the role is not
+ * implied.
+ * <p>
+ * The rule that a {@code Group} object must have at least one basic member to
+ * be implied is motivated by the following example:
+ *
+ * <pre>
+ *
+ * group foo
+ * required members: marketing
+ * basic members: alice, bob
+ *
+ * </pre>
+ *
+ * Privileged operations that require membership in "foo" can be performed only
+ * by "alice" and "bob", who are in marketing.
+ * <p>
+ * If "alice" and "bob" ever transfer to a different department, anybody in
+ * marketing will be able to assume the "foo" role, which certainly must be
+ * prevented. Requiring that "foo" (or any {@code Group} object for that matter)
+ * must have at least one basic member accomplishes that.
+ * <p>
+ * However, this would make it impossible for a {@code Group} object to be
+ * implied by just its required members. An example where this implication might
+ * be useful is the following declaration: "Any citizen who is an adult is
+ * allowed to vote." An intuitive configuration of "voter" would be:
+ *
+ * <pre>
+ *
+ * group voter
+ * required members: citizen, adult
+ * basic members:
+ *
+ * </pre>
+ *
+ * However, according to the above rule, the "voter" role could never be assumed
+ * by anybody, since it lacks any basic members. In order to address this issue
+ * a predefined role named "user.anyone" can be specified, which is always
+ * implied. The desired implication of the "voter" group can then be achieved by
+ * specifying "user.anyone" as its basic member, as follows:
+ *
+ * <pre>
+ *
+ * group voter
+ * required members: citizen, adult
+ * basic members: user.anyone
+ *
+ * </pre>
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface Group extends User {
+ /**
+ * Adds the specified {@code Role} object as a basic member to this
+ * {@code Group} object.
+ *
+ * @param role The role to add as a basic member.
+ *
+ * @return {@code true} if the given role could be added as a basic member,
+ * and {@code false} if this {@code Group} object already contains a
+ * {@code Role} object whose name matches that of the specified
+ * role.
+ *
+ * @throws SecurityException If a security manager exists and the caller
+ * does not have the {@code UserAdminPermission} with name
+ * {@code admin}.
+ */
+ public boolean addMember(Role role);
+
+ /**
+ * Adds the specified {@code Role} object as a required member to this
+ * {@code Group} object.
+ *
+ * @param role The {@code Role} object to add as a required member.
+ *
+ * @return {@code true} if the given {@code Role} object could be added as a
+ * required member, and {@code false} if this {@code Group} object
+ * already contains a {@code Role} object whose name matches that of
+ * the specified role.
+ *
+ * @throws SecurityException If a security manager exists and the caller
+ * does not have the {@code UserAdminPermission} with name
+ * {@code admin}.
+ */
+ public boolean addRequiredMember(Role role);
+
+ /**
+ * Removes the specified {@code Role} object from this {@code Group} object.
+ *
+ * @param role The {@code Role} object to remove from this {@code Group}
+ * object.
+ *
+ * @return {@code true} if the {@code Role} object could be removed,
+ * otherwise {@code false}.
+ *
+ * @throws SecurityException If a security manager exists and the caller
+ * does not have the {@code UserAdminPermission} with name
+ * {@code admin}.
+ */
+ public boolean removeMember(Role role);
+
+ /**
+ * Gets the basic members of this {@code Group} object.
+ *
+ * @return The basic members of this {@code Group} object, or {@code null}
+ * if this {@code Group} object does not contain any basic members.
+ */
+ public Role[] getMembers();
+
+ /**
+ * Gets the required members of this {@code Group} object.
+ *
+ * @return The required members of this {@code Group} object, or
+ * {@code null} if this {@code Group} object does not contain any
+ * required members.
+ */
+ public Role[] getRequiredMembers();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Role.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Role.java
new file mode 100644
index 000000000..c366d5a63
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/Role.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+import java.util.Dictionary;
+
+/**
+ * The base interface for {@code Role} objects managed by the User Admin
+ * service.
+ *
+ * <p>
+ * This interface exposes the characteristics shared by all {@code Role}
+ * classes: a name, a type, and a set of properties.
+ * <p>
+ * Properties represent public information about the {@code Role} object that
+ * can be read by anyone. Specific {@link UserAdminPermission} objects are
+ * required to change a {@code Role} object's properties.
+ * <p>
+ * {@code Role} object properties are {@code Dictionary} objects. Changes to
+ * these objects are propagated to the User Admin service and made persistent.
+ * <p>
+ * Every User Admin service contains a set of predefined {@code Role} objects
+ * that are always present and cannot be removed. All predefined {@code Role}
+ * objects are of type {@code ROLE}. This version of the
+ * {@code org.osgi.service.useradmin} package defines a single predefined role
+ * named &quot;user.anyone&quot;, which is inherited by any other role. Other
+ * predefined roles may be added in the future. Since &quot;user.anyone&quot; is
+ * a {@code Role} object that has properties associated with it that can be read
+ * and modified. Access to these properties and their use is application
+ * specific and is controlled using {@code UserAdminPermission} in the same way
+ * that properties for other {@code Role} objects are.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface Role {
+ /**
+ * The name of the predefined role, user.anyone, that all users and groups
+ * belong to.
+ *
+ * @since 1.1
+ */
+ public static final String USER_ANYONE = "user.anyone";
+ /**
+ * The type of a predefined role.
+ *
+ * <p>
+ * The value of {@code ROLE} is 0.
+ */
+ public static final int ROLE = 0;
+ /**
+ * The type of a {@link User} role.
+ *
+ * <p>
+ * The value of {@code USER} is 1.
+ */
+ public static final int USER = 1;
+ /**
+ * The type of a {@link Group} role.
+ *
+ * <p>
+ * The value of {@code GROUP} is 2.
+ */
+ public static final int GROUP = 2;
+
+ /**
+ * Returns the name of this role.
+ *
+ * @return The role's name.
+ */
+ public String getName();
+
+ /**
+ * Returns the type of this role.
+ *
+ * @return The role's type.
+ */
+ public int getType();
+
+ /**
+ * Returns a {@code Dictionary} of the (public) properties of this
+ * {@code Role} object. Any changes to the returned {@code Dictionary} will
+ * change the properties of this {@code Role} object. This will cause a
+ * {@code UserAdminEvent} object of type {@link UserAdminEvent#ROLE_CHANGED}
+ * to be broadcast to any {@code UserAdminListener} objects.
+ *
+ * <p>
+ * Only objects of type {@code String} may be used as property keys, and
+ * only objects of type {@code String} or {@code byte[]} may be used as
+ * property values. Any other types will cause an exception of type
+ * {@code IllegalArgumentException} to be raised.
+ *
+ * <p>
+ * In order to add, change, or remove a property in the returned
+ * {@code Dictionary}, a {@link UserAdminPermission} named after the
+ * property name (or a prefix of it) with action {@code changeProperty} is
+ * required.
+ *
+ * @return {@code Dictionary} containing the properties of this {@code Role}
+ * object.
+ */
+ public Dictionary getProperties();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/User.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/User.java
new file mode 100644
index 000000000..0520ec2dd
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/User.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+import java.util.Dictionary;
+
+/**
+ * A {@code User} role managed by a User Admin service.
+ *
+ * <p>
+ * In this context, the term &quot;user&quot; is not limited to just human
+ * beings. Instead, it refers to any entity that may have any number of
+ * credentials associated with it that it may use to authenticate itself.
+ * <p>
+ * In general, {@code User} objects are associated with a specific User Admin
+ * service (namely the one that created them), and cannot be used with other
+ * User Admin services.
+ * <p>
+ * A {@code User} object may have credentials (and properties, inherited from
+ * the {@link Role} class) associated with it. Specific
+ * {@link UserAdminPermission} objects are required to read or change a
+ * {@code User} object's credentials.
+ * <p>
+ * Credentials are {@code Dictionary} objects and have semantics that are
+ * similar to the properties in the {@code Role} class.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface User extends Role {
+ /**
+ * Returns a {@code Dictionary} of the credentials of this {@code User}
+ * object. Any changes to the returned {@code Dictionary} object will change
+ * the credentials of this {@code User} object. This will cause a
+ * {@code UserAdminEvent} object of type {@link UserAdminEvent#ROLE_CHANGED}
+ * to be broadcast to any {@code UserAdminListeners} objects.
+ *
+ * <p>
+ * Only objects of type {@code String} may be used as credential keys, and
+ * only objects of type {@code String} or of type {@code byte[]} may be used
+ * as credential values. Any other types will cause an exception of type
+ * {@code IllegalArgumentException} to be raised.
+ *
+ * <p>
+ * In order to retrieve a credential from the returned {@code Dictionary}
+ * object, a {@link UserAdminPermission} named after the credential name (or
+ * a prefix of it) with action {@code getCredential} is required.
+ * <p>
+ * In order to add or remove a credential from the returned
+ * {@code Dictionary} object, a {@link UserAdminPermission} named after the
+ * credential name (or a prefix of it) with action {@code changeCredential}
+ * is required.
+ *
+ * @return {@code Dictionary} object containing the credentials of this
+ * {@code User} object.
+ */
+ public Dictionary getCredentials();
+
+ /**
+ * Checks to see if this {@code User} object has a credential with the
+ * specified {@code key} set to the specified {@code value}.
+ *
+ * <p>
+ * If the specified credential {@code value} is not of type {@code String}
+ * or {@code byte[]}, it is ignored, that is, {@code false} is returned (as
+ * opposed to an {@code IllegalArgumentException} being raised).
+ *
+ * @param key The credential {@code key}.
+ * @param value The credential {@code value}.
+ *
+ * @return {@code true} if this user has the specified credential;
+ * {@code false} otherwise.
+ *
+ * @throws SecurityException If a security manager exists and the caller
+ * does not have the {@code UserAdminPermission} named after the
+ * credential key (or a prefix of it) with action
+ * {@code getCredential}.
+ */
+ public boolean hasCredential(String key, Object value);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdmin.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdmin.java
new file mode 100644
index 000000000..60b8b60bc
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdmin.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * This interface is used to manage a database of named {@code Role} objects,
+ * which can be used for authentication and authorization purposes.
+ *
+ * <p>
+ * This version of the User Admin service defines two types of {@code Role}
+ * objects: "User" and "Group". Each type of role is represented by an
+ * {@code int} constant and an interface. The range of positive integers is
+ * reserved for new types of roles that may be added in the future. When
+ * defining proprietary role types, negative constant values must be used.
+ *
+ * <p>
+ * Every role has a name and a type.
+ *
+ * <p>
+ * A {@link User} object can be configured with credentials (e.g., a password)
+ * and properties (e.g., a street address, phone number, etc.).
+ * <p>
+ * A {@link Group} object represents an aggregation of {@link User} and
+ * {@link Group} objects. In other words, the members of a {@code Group} object
+ * are roles themselves.
+ * <p>
+ * Every User Admin service manages and maintains its own namespace of
+ * {@code Role} objects, in which each {@code Role} object has a unique name.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface UserAdmin {
+ /**
+ * Creates a {@code Role} object with the given name and of the given type.
+ *
+ * <p>
+ * If a {@code Role} object was created, a {@code UserAdminEvent} object of
+ * type {@link UserAdminEvent#ROLE_CREATED} is broadcast to any
+ * {@code UserAdminListener} object.
+ *
+ * @param name The {@code name} of the {@code Role} object to create.
+ * @param type The type of the {@code Role} object to create. Must be either
+ * a {@link Role#USER} type or {@link Role#GROUP} type.
+ *
+ * @return The newly created {@code Role} object, or {@code null} if a role
+ * with the given name already exists.
+ *
+ * @throws IllegalArgumentException if {@code type} is invalid.
+ *
+ * @throws SecurityException If a security manager exists and the caller
+ * does not have the {@code UserAdminPermission} with name
+ * {@code admin}.
+ */
+ public Role createRole(String name, int type);
+
+ /**
+ * Removes the {@code Role} object with the given name from this User Admin
+ * service and all groups it is a member of.
+ *
+ * <p>
+ * If the {@code Role} object was removed, a {@code UserAdminEvent} object
+ * of type {@link UserAdminEvent#ROLE_REMOVED} is broadcast to any
+ * {@code UserAdminListener} object.
+ *
+ * @param name The name of the {@code Role} object to remove.
+ *
+ * @return {@code true} If a {@code Role} object with the given name is
+ * present in this User Admin service and could be removed,
+ * otherwise {@code false}.
+ *
+ * @throws SecurityException If a security manager exists and the caller
+ * does not have the {@code UserAdminPermission} with name
+ * {@code admin}.
+ */
+ public boolean removeRole(String name);
+
+ /**
+ * Gets the {@code Role} object with the given {@code name} from this User
+ * Admin service.
+ *
+ * @param name The name of the {@code Role} object to get.
+ *
+ * @return The requested {@code Role} object, or {@code null} if this User
+ * Admin service does not have a {@code Role} object with the given
+ * {@code name}.
+ */
+ public Role getRole(String name);
+
+ /**
+ * Gets the {@code Role} objects managed by this User Admin service that
+ * have properties matching the specified LDAP filter criteria. See
+ * {@code org.osgi.framework.Filter} for a description of the filter syntax.
+ * If a {@code null} filter is specified, all Role objects managed by this
+ * User Admin service are returned.
+ *
+ * @param filter The filter criteria to match.
+ *
+ * @return The {@code Role} objects managed by this User Admin service whose
+ * properties match the specified filter criteria, or all
+ * {@code Role} objects if a {@code null} filter is specified. If no
+ * roles match the filter, {@code null} will be returned.
+ * @throws InvalidSyntaxException If the filter is not well formed.
+ *
+ */
+ public Role[] getRoles(String filter) throws InvalidSyntaxException;
+
+ /**
+ * Gets the user with the given property {@code key}-{@code value} pair from
+ * the User Admin service database. This is a convenience method for
+ * retrieving a {@code User} object based on a property for which every
+ * {@code User} object is supposed to have a unique value (within the scope
+ * of this User Admin service), such as for example a X.500 distinguished
+ * name.
+ *
+ * @param key The property key to look for.
+ * @param value The property value to compare with.
+ *
+ * @return A matching user, if <em>exactly</em> one is found. If zero or
+ * more than one matching users are found, {@code null} is returned.
+ */
+ public User getUser(String key, String value);
+
+ /**
+ * Creates an {@code Authorization} object that encapsulates the specified
+ * {@code User} object and the {@code Role} objects it possesses. The
+ * {@code null} user is interpreted as the anonymous user. The anonymous
+ * user represents a user that has not been authenticated. An
+ * {@code Authorization} object for an anonymous user will be unnamed, and
+ * will only imply groups that user.anyone implies.
+ *
+ * @param user The {@code User} object to create an {@code Authorization}
+ * object for, or {@code null} for the anonymous user.
+ *
+ * @return the {@code Authorization} object for the specified {@code User}
+ * object.
+ */
+ public Authorization getAuthorization(User user);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminEvent.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminEvent.java
new file mode 100644
index 000000000..606618cc7
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminEvent.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * {@code Role} change event.
+ * <p>
+ * {@code UserAdminEvent} objects are delivered asynchronously to any
+ * {@code UserAdminListener} objects when a change occurs in any of the
+ * {@code Role} objects managed by a User Admin service.
+ *
+ * <p>
+ * A type code is used to identify the event. The following event types are
+ * defined: {@link #ROLE_CREATED} type, {@link #ROLE_CHANGED} type, and
+ * {@link #ROLE_REMOVED} type. Additional event types may be defined in the
+ * future.
+ *
+ * @see UserAdmin
+ * @see UserAdminListener
+ *
+ * @author $Id$
+ */
+public class UserAdminEvent {
+ private ServiceReference ref;
+ private int type;
+ private Role role;
+ /**
+ * A {@code Role} object has been created.
+ *
+ * <p>
+ * The value of {@code ROLE_CREATED} is 0x00000001.
+ */
+ public static final int ROLE_CREATED = 0x00000001;
+ /**
+ * A {@code Role} object has been modified.
+ *
+ * <p>
+ * The value of {@code ROLE_CHANGED} is 0x00000002.
+ */
+ public static final int ROLE_CHANGED = 0x00000002;
+ /**
+ * A {@code Role} object has been removed.
+ *
+ * <p>
+ * The value of {@code ROLE_REMOVED} is 0x00000004.
+ */
+ public static final int ROLE_REMOVED = 0x00000004;
+
+ /**
+ * Constructs a {@code UserAdminEvent} object from the given
+ * {@code ServiceReference} object, event type, and {@code Role} object.
+ *
+ * @param ref The {@code ServiceReference} object of the User Admin service
+ * that generated this event.
+ * @param type The event type.
+ * @param role The {@code Role} object on which this event occurred.
+ */
+ public UserAdminEvent(ServiceReference ref, int type, Role role) {
+ this.ref = ref;
+ this.type = type;
+ this.role = role;
+ }
+
+ /**
+ * Gets the {@code ServiceReference} object of the User Admin service that
+ * generated this event.
+ *
+ * @return The User Admin service's {@code ServiceReference} object.
+ */
+ public ServiceReference getServiceReference() {
+ return ref;
+ }
+
+ /**
+ * Returns the type of this event.
+ *
+ * <p>
+ * The type values are {@link #ROLE_CREATED} type, {@link #ROLE_CHANGED}
+ * type, and {@link #ROLE_REMOVED} type.
+ *
+ * @return The event type.
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Gets the {@code Role} object this event was generated for.
+ *
+ * @return The {@code Role} object this event was generated for.
+ */
+ public Role getRole() {
+ return role;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminListener.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminListener.java
new file mode 100644
index 000000000..3d45a44b2
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminListener.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+/**
+ * Listener for UserAdminEvents.
+ *
+ * <p>
+ * {@code UserAdminListener} objects are registered with the Framework service
+ * registry and notified with a {@code UserAdminEvent} object when a
+ * {@code Role} object has been created, removed, or modified.
+ * <p>
+ * {@code UserAdminListener} objects can further inspect the received
+ * {@code UserAdminEvent} object to determine its type, the {@code Role} object
+ * it occurred on, and the User Admin service that generated it.
+ *
+ * @see UserAdmin
+ * @see UserAdminEvent
+ *
+ * @author $Id$
+ */
+public interface UserAdminListener {
+ /**
+ * Receives notification that a {@code Role} object has been created,
+ * removed, or modified.
+ *
+ * @param event The {@code UserAdminEvent} object.
+ */
+ public void roleChanged(UserAdminEvent event);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminPermission.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminPermission.java
new file mode 100644
index 000000000..536a2ac22
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/UserAdminPermission.java
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2013). 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.useradmin;
+
+import java.io.IOException;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * Permission to configure and access the {@link Role} objects managed by a User
+ * Admin service.
+ *
+ * <p>
+ * This class represents access to the {@code Role} objects managed by a User
+ * Admin service and their properties and credentials (in the case of
+ * {@link User} objects).
+ * <p>
+ * The permission name is the name (or name prefix) of a property or credential.
+ * The naming convention follows the hierarchical property naming convention.
+ * Also, an asterisk may appear at the end of the name, following a
+ * &quot;.&quot;, or by itself, to signify a wildcard match. For example:
+ * &quot;org.osgi.security.protocol.*&quot; or &quot;*&quot; is valid, but
+ * &quot;*protocol&quot; or &quot;a*b&quot; are not valid.
+ *
+ * <p>
+ * The {@code UserAdminPermission} with the reserved name &quot;admin&quot;
+ * represents the permission required for creating and removing {@code Role}
+ * objects in the User Admin service, as well as adding and removing members in
+ * a {@code Group} object. This {@code UserAdminPermission} does not have any
+ * actions associated with it.
+ *
+ * <p>
+ * The actions to be granted are passed to the constructor in a string
+ * containing a list of one or more comma-separated keywords. The possible
+ * keywords are: {@code changeProperty},{@code changeCredential}, and
+ * {@code getCredential}. Their meaning is defined as follows:
+ *
+ * <pre>
+ *
+ * action
+ * changeProperty Permission to change (i.e., add and remove)
+ * Role object properties whose names start with
+ * the name argument specified in the constructor.
+ * changeCredential Permission to change (i.e., add and remove)
+ * User object credentials whose names start
+ * with the name argument specified in the constructor.
+ * getCredential Permission to retrieve and check for the
+ * existence of User object credentials whose names
+ * start with the name argument specified in the
+ * constructor.
+ *
+ * </pre>
+ *
+ * The action string is converted to lowercase before processing.
+ *
+ * <p>
+ * Following is a PermissionInfo style policy entry which grants a user
+ * administration bundle a number of {@code UserAdminPermission} object:
+ *
+ * <pre>
+ *
+ * (org.osgi.service.useradmin.UserAdminPermission &quot;admin&quot;)
+ * (org.osgi.service.useradmin.UserAdminPermission &quot;com.foo.*&quot;
+ * &quot;changeProperty,getCredential,changeCredential&quot;)
+ * (org.osgi.service.useradmin.UserAdminPermission &quot;user.*&quot;
+ * &quot;changeProperty,changeCredential&quot;)
+ *
+ * </pre>
+ *
+ * The first permission statement grants the bundle the permission to perform
+ * any User Admin service operations of type "admin", that is, create and remove
+ * roles and configure {@code Group} objects.
+ *
+ * <p>
+ * The second permission statement grants the bundle the permission to change
+ * any properties as well as get and change any credentials whose names start
+ * with {@code com.foo.}.
+ *
+ * <p>
+ * The third permission statement grants the bundle the permission to change any
+ * properties and credentials whose names start with {@code user.}. This means
+ * that the bundle is allowed to change, but not retrieve any credentials with
+ * the given prefix.
+ *
+ * <p>
+ * The following policy entry empowers the Http Service bundle to perform user
+ * authentication:
+ *
+ * <pre>
+ *
+ * grant codeBase &quot;${jars}http.jar&quot; {
+ * permission org.osgi.service.useradmin.UserAdminPermission
+ * &quot;user.password&quot;, &quot;getCredential&quot;;
+ * };
+ *
+ * </pre>
+ *
+ * <p>
+ * The permission statement grants the Http Service bundle the permission to
+ * validate any password credentials (for authentication purposes), but the
+ * bundle is not allowed to change any properties or credentials.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public final class UserAdminPermission extends BasicPermission {
+ static final long serialVersionUID = -1179971692401603789L;
+ /**
+ * The permission name &quot;admin&quot;.
+ */
+ public static final String ADMIN = "admin";
+ /**
+ * The action string &quot;changeProperty&quot;.
+ */
+ public static final String CHANGE_PROPERTY = "changeProperty";
+ private static final int ACTION_CHANGE_PROPERTY = 0x1;
+ /**
+ * The action string &quot;changeCredential&quot;.
+ */
+ public static final String CHANGE_CREDENTIAL = "changeCredential";
+ private static final int ACTION_CHANGE_CREDENTIAL = 0x2;
+ /**
+ * The action string &quot;getCredential&quot;.
+ */
+ public static final String GET_CREDENTIAL = "getCredential";
+ private static final int ACTION_GET_CREDENTIAL = 0x4;
+ /**
+ * All actions
+ */
+ private static final int ACTION_ALL = ACTION_CHANGE_PROPERTY | ACTION_CHANGE_CREDENTIAL | ACTION_GET_CREDENTIAL;
+ /**
+ * No actions.
+ */
+ static final int ACTION_NONE = 0;
+ /**
+ * The actions in canonical form.
+ *
+ * @serial
+ */
+ private volatile String actions = null;
+ /**
+ * The actions mask.
+ */
+ private transient int action_mask;
+
+ /**
+ * Creates a new {@code UserAdminPermission} with the specified name and
+ * actions. {@code name} is either the reserved string &quot;admin&quot; or
+ * the name of a credential or property, and {@code actions} contains a
+ * comma-separated list of the actions granted on the specified name. Valid
+ * actions are {@code changeProperty},{@code changeCredential}, and
+ * getCredential.
+ *
+ * @param name the name of this {@code UserAdminPermission}
+ * @param actions the action string.
+ *
+ * @throws IllegalArgumentException If {@code name} equals &quot;admin&quot;
+ * and {@code actions} are specified.
+ */
+ public UserAdminPermission(String name, String actions) {
+ this(name, parseActions(actions));
+ }
+
+ /**
+ * Package private constructor used by {@code UserAdminPermissionCollection}
+ * .
+ *
+ * @param name class name
+ * @param mask action mask
+ */
+ UserAdminPermission(String name, int mask) {
+ super(name);
+ setTransients(mask);
+ }
+
+ /**
+ * Called by constructors and when deserialized.
+ *
+ * @param mask action mask
+ */
+ private synchronized void setTransients(int mask) {
+ if (getName().equals(ADMIN)) {
+ if (mask != ACTION_NONE) {
+ throw new IllegalArgumentException("Actions specified for " + "no-action " + "UserAdminPermission");
+ }
+ } else {
+ if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
+ action_mask = mask;
+ }
+
+ /**
+ * Returns the current action mask.
+ * <p>
+ * Used by the UserAdminPermissionCollection class.
+ *
+ * @return Current action mask.
+ */
+ synchronized int getActionsMask() {
+ return action_mask;
+ }
+
+ /**
+ * Parse action string into action mask.
+ *
+ * @param actions Action string.
+ * @return action mask.
+ */
+ private static int parseActions(String actions) {
+ boolean seencomma = false;
+ int mask = ACTION_NONE;
+ if (actions == null) {
+ return mask;
+ }
+ char[] a = actions.toCharArray();
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+ while (i != -1) {
+ char c;
+ // skip whitespace
+ while ((i != -1) && ((c = a[i]) == ' ' || c == '\r' || c == '\n' || c == '\f' || c == '\t'))
+ i--;
+ // check for the known strings
+ int matchlen;
+ if (i >= 12 && match_get(a, i - 10) && match_credential(a, i)) {
+ matchlen = 13;
+ mask |= ACTION_GET_CREDENTIAL;
+ } else
+ if (i >= 13 && match_change(a, i - 8) && match_property(a, i)) {
+ matchlen = 14;
+ mask |= ACTION_CHANGE_PROPERTY;
+ } else
+ if (i >= 15 && match_change(a, i - 10) && match_credential(a, i)) {
+ matchlen = 16;
+ mask |= ACTION_CHANGE_CREDENTIAL;
+ } else {
+ // parse error
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ // make sure we didn't just match the tail of a word
+ // like "ackbarfimport". Also, skip to the comma.
+ seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch (a[i - matchlen]) {
+ case ',' :
+ seencomma = true;
+ /* FALLTHROUGH */
+ case ' ' :
+ case '\r' :
+ case '\n' :
+ case '\f' :
+ case '\t' :
+ break;
+ default :
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ i--;
+ }
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+ if (seencomma) {
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ return mask;
+ }
+
+ private static boolean match_change(char[] a, int i) {
+ return ((a[i - 5] == 'c' || a[i - 5] == 'C') && (a[i - 4] == 'h' || a[i - 4] == 'H') && (a[i - 3] == 'a' || a[i - 3] == 'A') && (a[i - 2] == 'n' || a[i - 2] == 'N')
+ && (a[i - 1] == 'g' || a[i - 1] == 'G') && (a[i - 0] == 'e' || a[i - 0] == 'E'));
+ }
+
+ private static boolean match_get(char[] a, int i) {
+ return ((a[i - 2] == 'g' || a[i - 2] == 'G') && (a[i - 1] == 'e' || a[i - 1] == 'E') && (a[i - 0] == 't' || a[i - 0] == 'T'));
+ }
+
+ private static boolean match_property(char[] a, int i) {
+ return ((a[i - 7] == 'p' || a[i - 7] == 'P') && (a[i - 6] == 'r' || a[i - 6] == 'R') && (a[i - 5] == 'o' || a[i - 5] == 'O') && (a[i - 4] == 'p' || a[i - 4] == 'P')
+ && (a[i - 3] == 'e' || a[i - 3] == 'E') && (a[i - 2] == 'r' || a[i - 2] == 'R') && (a[i - 1] == 't' || a[i - 1] == 'T') && (a[i - 0] == 'y' || a[i - 0] == 'Y'));
+ }
+
+ private static boolean match_credential(char[] a, int i) {
+ return ((a[i - 9] == 'c' || a[i - 9] == 'C') && (a[i - 8] == 'r' || a[i - 8] == 'R') && (a[i - 7] == 'e' || a[i - 7] == 'E') && (a[i - 6] == 'd' || a[i - 6] == 'D')
+ && (a[i - 5] == 'e' || a[i - 5] == 'E') && (a[i - 4] == 'n' || a[i - 4] == 'N') && (a[i - 3] == 't' || a[i - 3] == 'T') && (a[i - 2] == 'i' || a[i - 2] == 'I')
+ && (a[i - 1] == 'a' || a[i - 1] == 'A') && (a[i - 0] == 'l' || a[i - 0] == 'L'));
+ }
+
+ /**
+ * Checks if this {@code UserAdminPermission} object &quot;implies&quot; the
+ * specified permission.
+ * <P>
+ * More specifically, this method returns {@code true} if:
+ * <p>
+ * <ul>
+ * <li><i>p</i> is an instanceof {@code UserAdminPermission},</li>
+ * <li><i>p</i>'s actions are a proper subset of this object's actions, and</li>
+ * <li><i>p</i>'s name is implied by this object's name. For example,
+ * &quot;java.*&quot; implies &quot;java.home&quot;.</li>
+ * </ul>
+ *
+ * @param p the permission to check against.
+ *
+ * @return {@code true} if the specified permission is implied by this
+ * object; {@code false} otherwise.
+ */
+ public boolean implies(Permission p) {
+ if (p instanceof UserAdminPermission) {
+ UserAdminPermission requested = (UserAdminPermission) p;
+ int mask = getActionsMask();
+ int targetMask = requested.getActionsMask();
+ return // Check that the we have the requested action
+ ((targetMask & mask) == targetMask) &&
+ // If the target action mask is ACTION_NONE, it must be an
+ // admin permission, and then we must be that too
+ (targetMask != ACTION_NONE || mask == ACTION_NONE) &&
+ // Check that name name matches
+ super.implies(p);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the canonical string representation of the actions, separated by
+ * comma.
+ *
+ * @return the canonical string representation of the actions.
+ */
+ public String getActions() {
+ String result = actions;
+ if (result == null) {
+ StringBuffer sb = new StringBuffer();
+ boolean comma = false;
+ int mask = getActionsMask();
+ if ((mask & ACTION_CHANGE_CREDENTIAL) == ACTION_CHANGE_CREDENTIAL) {
+ sb.append(CHANGE_CREDENTIAL);
+ comma = true;
+ }
+ if ((mask & ACTION_CHANGE_PROPERTY) == ACTION_CHANGE_PROPERTY) {
+ if (comma)
+ sb.append(',');
+ sb.append(CHANGE_PROPERTY);
+ comma = true;
+ }
+ if ((mask & ACTION_GET_CREDENTIAL) == ACTION_GET_CREDENTIAL) {
+ if (comma)
+ sb.append(',');
+ sb.append(GET_CREDENTIAL);
+ }
+ actions = result = sb.toString();
+ }
+ return result;
+ }
+
+ /**
+ * Returns a new {@code PermissionCollection} object for storing
+ * {@code UserAdminPermission} objects.
+ *
+ * @return a new {@code PermissionCollection} object suitable for storing
+ * {@code UserAdminPermission} objects.
+ */
+ public PermissionCollection newPermissionCollection() {
+ return new UserAdminPermissionCollection();
+ }
+
+ /**
+ * Checks two {@code UserAdminPermission} objects for equality. Checks that
+ * {@code obj} is a {@code UserAdminPermission}, and has the same name and
+ * actions as this object.
+ *
+ * @param obj the object to be compared for equality with this object.
+ *
+ * @return {@code true} if {@code obj} is a {@code UserAdminPermission}
+ * object, and has the same name and actions as this
+ * {@code UserAdminPermission} object.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof UserAdminPermission)) {
+ return false;
+ }
+
+ UserAdminPermission uap = (UserAdminPermission) obj;
+
+ return (getActionsMask() == uap.getActionsMask()) && getName().equals(uap.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ public int hashCode() {
+ int h = 31 * 17 + getName().hashCode();
+ h = 31 * h + getActions().hashCode();
+ return h;
+ }
+
+ /**
+ * writeObject is called to save the state of this object to a stream. The
+ * actions are serialized, and the superclass takes care of the name.
+ */
+ private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ // Write out the actions. The superclass takes care of the name
+ // call getActions to make sure actions field is initialized
+ if (actions == null)
+ getActions();
+ s.defaultWriteObject();
+ }
+
+ /*
+ * Restores this object from a stream (i.e., deserializes it).
+ */
+ private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
+ // Read in the action, then initialize the rest
+ s.defaultReadObject();
+ setTransients(parseActions(actions));
+ }
+
+ /**
+ * Returns a string describing this {@code UserAdminPermission} object. This
+ * string must be in {@code PermissionInfo} encoded format.
+ *
+ * @return The {@code PermissionInfo} encoded string for this
+ * {@code UserAdminPermission} object.
+ * @see "org.osgi.service.permissionadmin.PermissionInfo.getEncoded()"
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ sb.append(getClass().getName());
+ sb.append(" \"");
+ sb.append(getName());
+ String a = getActions();
+ if (a.length() > 0) {
+ sb.append("\" \"");
+ sb.append(a);
+ }
+ sb.append("\")");
+ return sb.toString();
+ }
+}
+
+/**
+ * A {@code UserAdminPermissionCollection} stores a set of
+ * {@code UserAdminPermission} permissions.
+ */
+
+final class UserAdminPermissionCollection extends PermissionCollection {
+ static final long serialVersionUID = -7222111885230120581L;
+ /**
+ * Table of permissions.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private final Hashtable permissions;
+ /**
+ * Boolean saying if "*" is in the collection.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private boolean all_allowed;
+
+ /**
+ * Creates an empty {@code UserAdminPermissionCollection} object.
+ */
+ public UserAdminPermissionCollection() {
+ permissions = new Hashtable();
+ all_allowed = false;
+ }
+
+ /**
+ * Adds the given permission to this {@code UserAdminPermissionCollection}.
+ * The key for the hash is the name.
+ *
+ * @param permission the {@code Permission} object to add.
+ *
+ * @throws IllegalArgumentException If the given permission is not a
+ * {@code UserAdminPermission}
+ * @throws SecurityException If this {@code UserAdminPermissionCollection}
+ * object has been marked readonly
+ */
+ public void add(Permission permission) {
+ if (!(permission instanceof UserAdminPermission))
+ throw new IllegalArgumentException("Invalid permission: " + permission);
+ if (isReadOnly()) {
+ throw new SecurityException("Attempt to add a Permission to a " + "readonly PermissionCollection");
+ }
+ final UserAdminPermission uap = (UserAdminPermission) permission;
+ final String name = uap.getName();
+ synchronized (this) {
+ final UserAdminPermission existing = (UserAdminPermission) permissions.get(name);
+ if (existing != null) {
+ int oldMask = existing.getActionsMask();
+ int newMask = uap.getActionsMask();
+ if (oldMask != newMask) {
+ permissions.put(name, new UserAdminPermission(name, oldMask | newMask));
+ }
+ } else {
+ permissions.put(name, uap);
+ }
+ if (!all_allowed) {
+ if (name.equals("*")) {
+ all_allowed = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to see if this {@code PermissionCollection} implies the given
+ * permission.
+ *
+ * @param permission the {@code Permission} object to check against
+ *
+ * @return true if the given permission is implied by this
+ * {@code PermissionCollection}, false otherwise.
+ */
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof UserAdminPermission)) {
+ return false;
+ }
+ final UserAdminPermission requested = (UserAdminPermission) permission;
+ String name = requested.getName();
+ final int desired = requested.getActionsMask();
+ UserAdminPermission x;
+ int effective = 0;
+ synchronized (this) {
+ // Short circuit if the "*" Permission was added.
+ // desired can only be ACTION_NONE when name is "admin".
+ if (all_allowed && (desired != UserAdminPermission.ACTION_NONE)) {
+ x = (UserAdminPermission) permissions.get("*");
+ if (x != null) {
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ }
+ // strategy:
+ // Check for full match first. Then work our way up the
+ // name looking for matches on a.b.*
+
+ x = (UserAdminPermission) permissions.get(name);
+ }
+ if (x != null) {
+ // we have a direct hit!
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ // work our way up the tree...
+ int last;
+ int offset = name.length() - 1;
+ while ((last = name.lastIndexOf(".", offset)) != -1) {
+ name = name.substring(0, last + 1) + "*";
+ synchronized (this) {
+ x = (UserAdminPermission) permissions.get(name);
+ }
+ if (x != null) {
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ offset = last - 1;
+ }
+ // we don't have to check for "*" as it was already checked
+ // at the top (all_allowed), so we just return false
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the {@code UserAdminPermission} objects in
+ * the container.
+ *
+ * @return an enumeration of all the {@code UserAdminPermission} objects.
+ */
+ public Enumeration elements() {
+ return permissions.elements();
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/package-info.java
new file mode 100644
index 000000000..b79edb198
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * User Admin Package Version 1.1.
+ *
+ * <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.useradmin; version="[1.1,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.useradmin; version="[1.1,1.2)"}
+ *
+ * @version 1.1
+ * @author $Id$
+ */
+
+package org.osgi.service.useradmin;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/packageinfo
new file mode 100644
index 000000000..3987f9c4e
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/useradmin/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/BasicEnvelope.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/BasicEnvelope.java
new file mode 100644
index 000000000..e7f7111ce
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/BasicEnvelope.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+/**
+ * {@code BasicEnvelope} is an implementation of the {@link Envelope} interface
+ *
+ * @Immutable
+ * @author $Id$
+ */
+public class BasicEnvelope implements Envelope {
+ private final Object value;
+ private final Object identification;
+ private final String scope;
+
+ /**
+ * Constructor.
+ *
+ * @param value Content of this envelope, may be {@code null}.
+ * @param identification Identifying object for this {@code Envelope}
+ * object, must not be {@code null}
+ * @param scope Scope name for this object, must not be {@code null}
+ * @see Envelope
+ */
+ public BasicEnvelope(Object value, Object identification, String scope) {
+ this.value = value;
+ this.identification = identification;
+ this.scope = scope;
+ }
+
+ /**
+ * @see org.osgi.service.wireadmin.Envelope#getValue()
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * @see org.osgi.service.wireadmin.Envelope#getIdentification()
+ */
+ public Object getIdentification() {
+ return identification;
+ }
+
+ /**
+ * @see org.osgi.service.wireadmin.Envelope#getScope()
+ */
+ public String getScope() {
+ return scope;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Consumer.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Consumer.java
new file mode 100644
index 000000000..3363ead47
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Consumer.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+/**
+ * Data Consumer, a service that can receive udpated values from
+ * {@link Producer} services.
+ *
+ * <p>
+ * Service objects registered under the {@code Consumer} interface are expected
+ * to consume values from a Producer service via a {@code Wire} object. A
+ * Consumer service may poll the Producer service by calling the
+ * {@link Wire#poll()} method. The Consumer service will also receive an updated
+ * value when called at it's {@link #updated(Wire, Object)} method. The Producer
+ * service should have coerced the value to be an instance of one of the types
+ * specified by the {@link Wire#getFlavors()} method, or one of their
+ * subclasses.
+ *
+ * <p>
+ * Consumer service objects must register with a {@code service.pid} and a
+ * {@link WireConstants#WIREADMIN_CONSUMER_FLAVORS} property. It is recommended
+ * that Consumer service objects also register with a
+ * {@code service.description} property.
+ *
+ * <p>
+ * If an {@code Exception} is thrown by any of the {@code Consumer} methods, a
+ * {@code WireAdminEvent} of type {@link WireAdminEvent#CONSUMER_EXCEPTION} is
+ * broadcast by the Wire Admin service.
+ *
+ * <p>
+ * Security Considerations - Data consuming bundles will require
+ * {@code ServicePermission[Consumer,REGISTER]}. In general, only the Wire Admin
+ * service bundle should have this permission. Thus only the Wire Admin service
+ * may directly call a Consumer service. Care must be taken in the sharing of
+ * {@code Wire} objects with other bundles.
+ * <p>
+ * Consumer services must be registered with their scope when they can receive
+ * different types of objects from the Producer service. The Consumer service
+ * should have {@code WirePermission} for each of these scope names.
+ *
+ * @author $Id$
+ */
+public interface Consumer {
+ /**
+ * Update the value. This Consumer service is called by the {@code Wire}
+ * object with an updated value from the Producer service.
+ *
+ * <p>
+ * Note: This method may be called by a {@code Wire} object prior to this
+ * object being notified that it is connected to that {@code Wire} object
+ * (via the {@link #producersConnected(Wire[])} method).
+ * <p>
+ * When the Consumer service can receive {@code Envelope} objects, it must
+ * have registered all scope names together with the service object, and
+ * each of those names must be permitted by the bundle's
+ * {@code WirePermission}. If an {@code Envelope} object is delivered with
+ * the {@code updated} method, then the Consumer service should assume that
+ * the security check has been performed.
+ *
+ * @param wire The {@code Wire} object which is delivering the updated
+ * value.
+ * @param value The updated value. The value should be an instance of one of
+ * the types specified by the {@link Wire#getFlavors()} method.
+ */
+ public void updated(Wire wire, Object value);
+
+ /**
+ * Update the list of {@code Wire} objects to which this Consumer service is
+ * connected.
+ *
+ * <p>
+ * This method is called when the Consumer service is first registered and
+ * subsequently whenever a {@code Wire} associated with this Consumer
+ * service becomes connected, is modified or becomes disconnected.
+ *
+ * <p>
+ * The Wire Admin service must call this method asynchronously. This implies
+ * that implementors of Consumer can be assured that the callback will not
+ * take place during registration when they execute the registration in a
+ * synchronized method.
+ *
+ * @param wires An array of the current and complete list of {@code Wire}
+ * objects to which this Consumer service is connected. May be
+ * {@code null} if the Consumer service is not currently connected to
+ * any {@code Wire} objects.
+ */
+ public void producersConnected(Wire[] wires);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Envelope.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Envelope.java
new file mode 100644
index 000000000..f00816c73
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Envelope.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+/**
+ * Identifies a contained value.
+ *
+ * An {@code Envelope} object combines a status value, an identification object
+ * and a scope name. The {@code Envelope} object allows the use of standard Java
+ * types when a Producer service can produce more than one kind of object. The
+ * {@code Envelope} object allows the Consumer service to recognize the kind of
+ * object that is received. For example, a door lock could be represented by a
+ * {@code Boolean} object. If the {@code Producer} service would send such a
+ * {@code Boolean} object, then the Consumer service would not know what door
+ * the {@code Boolean} object represented. The {@code Envelope} object contains
+ * an identification object so the Consumer service can discriminate between
+ * different kinds of values. The identification object may be a simple
+ * {@code String} object, but it can also be a domain specific object that is
+ * mutually agreed by the Producer and the Consumer service. This object can
+ * then contain relevant information that makes the identification easier.
+ * <p>
+ * The scope name of the envelope is used for security. The Wire object must
+ * verify that any {@code Envelope} object send through the {@code update}
+ * method or coming from the {@code poll} method has a scope name that matches
+ * the permissions of both the Producer service and the Consumer service
+ * involved. The wireadmin package also contains a class {@code BasicEnvelope}
+ * that implements the methods of this interface.
+ *
+ * @see WirePermission
+ * @see BasicEnvelope
+ *
+ * @author $Id$
+ */
+public interface Envelope {
+ /**
+ * Return the value associated with this {@code Envelope} object.
+ *
+ * @return the value of the status item, or {@code null} when no item is
+ * associated with this object.
+ */
+ public Object getValue();
+
+ /**
+ * Return the identification of this {@code Envelope} object.
+ *
+ * An identification may be of any Java type. The type must be mutually
+ * agreed between the Consumer and Producer services.
+ *
+ * @return an object which identifies the status item in the address space
+ * of the composite producer, must not be null.
+ */
+ public Object getIdentification();
+
+ /**
+ * Return the scope name of this {@code Envelope} object.
+ *
+ * Scope names are used to restrict the communication between the Producer
+ * and Consumer services. Only {@code Envelopes} objects with a scope name
+ * that is permitted for the Producer and the Consumer services must be
+ * passed through a {@code Wire} object.
+ *
+ * @return the security scope for the status item, must not be null.
+ */
+ public String getScope();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Producer.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Producer.java
new file mode 100644
index 000000000..a65183e1e
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Producer.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+/**
+ * Data Producer, a service that can generate values to be used by
+ * {@link Consumer} services.
+ *
+ * <p>
+ * Service objects registered under the Producer interface are expected to
+ * produce values (internally generated or from external sensors). The value can
+ * be of different types. When delivering a value to a {@code Wire} object, the
+ * Producer service should coerce the value to be an instance of one of the
+ * types specified by {@link Wire#getFlavors()}. The classes are specified in
+ * order of preference.
+ *
+ * <p>
+ * When the data represented by the Producer object changes, this object should
+ * send the updated value by calling the {@code update} method on each of
+ * {@code Wire} objects passed in the most recent call to this object's
+ * {@link #consumersConnected(Wire[])} method. These {@code Wire} objects will
+ * pass the value on to the associated {@code Consumer} service object.
+ *
+ * <p>
+ * The Producer service may use the information in the {@code Wire} object's
+ * properties to schedule the delivery of values to the {@code Wire} object.
+ *
+ * <p>
+ * Producer service objects must register with a {@code service.pid} and a
+ * {@link WireConstants#WIREADMIN_PRODUCER_FLAVORS} property. It is recommended
+ * that a Producer service object also registers with a
+ * {@code service.description} property. Producer service objects must register
+ * with a {@link WireConstants#WIREADMIN_PRODUCER_FILTERS} property if the
+ * Producer service will be performing filtering instead of the {@code Wire}
+ * object.
+ *
+ * <p>
+ * If an exception is thrown by a Producer object method, a
+ * {@code WireAdminEvent} of type {@link WireAdminEvent#PRODUCER_EXCEPTION} is
+ * broadcast by the Wire Admin service.
+ *
+ * <p>
+ * Security Considerations. Data producing bundles will require
+ * {@code ServicePermission[Producer,REGISTER]} to register a Producer service.
+ * In general, only the Wire Admin service should have
+ * {@code ServicePermission[Producer,GET]}. Thus only the Wire Admin service may
+ * directly call a Producer service. Care must be taken in the sharing of
+ * {@code Wire} objects with other bundles.
+ * <p>
+ * Producer services must be registered with scope names when they can send
+ * different types of objects (composite) to the Consumer service. The Producer
+ * service should have {@code WirePermission} for each of these scope names.
+ *
+ * @author $Id$
+ */
+public interface Producer {
+ /**
+ * Return the current value of this {@code Producer} object.
+ *
+ * <p>
+ * This method is called by a {@code Wire} object in response to the
+ * Consumer service calling the {@code Wire} object's {@code poll} method.
+ * The Producer should coerce the value to be an instance of one of the
+ * types specified by {@link Wire#getFlavors()}. The types are specified in
+ * order of of preference. The returned value should be as new or newer than
+ * the last value furnished by this object.
+ *
+ * <p>
+ * Note: This method may be called by a {@code Wire} object prior to this
+ * object being notified that it is connected to that {@code Wire} object
+ * (via the {@link #consumersConnected(Wire[])} method).
+ * <p>
+ * If the Producer service returns an {@code Envelope} object that has an
+ * unpermitted scope name, then the Wire object must ignore (or remove) the
+ * transfer.
+ * <p>
+ * If the {@code Wire} object has a scope set, the return value must be an
+ * array of {@code Envelope} objects ({@code Envelope[]}). The {@code Wire}
+ * object must have removed any {@code Envelope} objects that have a scope
+ * name that is not in the Wire object's scope.
+ *
+ * @param wire The {@code Wire} object which is polling this service.
+ * @return The current value of the Producer service or {@code null} if the
+ * value cannot be coerced into a compatible type. Or an array of
+ * {@code Envelope} objects.
+ */
+ public Object polled(Wire wire);
+
+ /**
+ * Update the list of {@code Wire} objects to which this {@code Producer}
+ * object is connected.
+ *
+ * <p>
+ * This method is called when the Producer service is first registered and
+ * subsequently whenever a {@code Wire} associated with this Producer
+ * becomes connected, is modified or becomes disconnected.
+ *
+ * <p>
+ * The Wire Admin service must call this method asynchronously. This implies
+ * that implementors of a Producer service can be assured that the callback
+ * will not take place during registration when they execute the
+ * registration in a synchronized method.
+ *
+ * @param wires An array of the current and complete list of {@code Wire}
+ * objects to which this Producer service is connected. May be
+ * {@code null} if the Producer is not currently connected to any
+ * {@code Wire} objects.
+ */
+ public void consumersConnected(Wire[] wires);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Wire.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Wire.java
new file mode 100644
index 000000000..de75c27d5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/Wire.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+import java.util.Dictionary;
+
+/**
+ * A connection between a Producer service and a Consumer service.
+ *
+ * <p>
+ * A {@code Wire} object connects a Producer service to a Consumer service. Both
+ * the Producer and Consumer services are identified by their unique
+ * {@code service.pid} values. The Producer and Consumer services may
+ * communicate with each other via {@code Wire} objects that connect them. The
+ * Producer service may send updated values to the Consumer service by calling
+ * the {@link #update(Object)} method. The Consumer service may request an
+ * updated value from the Producer service by calling the {@link #poll()}
+ * method.
+ *
+ * <p>
+ * A Producer service and a Consumer service may be connected through multiple
+ * {@code Wire} objects.
+ *
+ * <p>
+ * Security Considerations. {@code Wire} objects are available to Producer and
+ * Consumer services connected to a given {@code Wire} object and to bundles
+ * which can access the {@code WireAdmin} service. A bundle must have
+ * {@code ServicePermission[WireAdmin,GET]} to get the {@code WireAdmin} service
+ * to access all {@code Wire} objects. A bundle registering a Producer service
+ * or a Consumer service must have the appropriate
+ * {@code ServicePermission[Consumer|Producer,REGISTER]} to register the service
+ * and will be passed {@code Wire} objects when the service object's
+ * {@code consumersConnected} or {@code producersConnected} method is called.
+ *
+ * <p>
+ * Scope. Each Wire object can have a scope set with the {@code setScope}
+ * method. This method should be called by a Consumer service when it assumes a
+ * Producer service that is composite (supports multiple information items). The
+ * names in the scope must be verified by the {@code Wire} object before it is
+ * used in communication. The semantics of the names depend on the Producer
+ * service and must not be interpreted by the Wire Admin service.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface Wire {
+ /**
+ * Return the state of this {@code Wire} object.
+ *
+ * <p>
+ * A connected {@code Wire} must always be disconnected before becoming
+ * invalid.
+ *
+ * @return {@code false} if this {@code Wire} object is invalid because it
+ * has been deleted via {@link WireAdmin#deleteWire(Wire)};
+ * {@code true} otherwise.
+ */
+ public boolean isValid();
+
+ /**
+ * Return the connection state of this {@code Wire} object.
+ *
+ * <p>
+ * A {@code Wire} is connected after the Wire Admin service receives
+ * notification that the Producer service and the Consumer service for this
+ * {@code Wire} object are both registered. This method will return
+ * {@code true} prior to notifying the Producer and Consumer services via
+ * calls to their respective {@code consumersConnected} and
+ * {@code producersConnected} methods.
+ * <p>
+ * A {@code WireAdminEvent} of type {@link WireAdminEvent#WIRE_CONNECTED}
+ * must be broadcast by the Wire Admin service when the {@code Wire} becomes
+ * connected.
+ *
+ * <p>
+ * A {@code Wire} object is disconnected when either the Consumer or
+ * Producer service is unregistered or the {@code Wire} object is deleted.
+ * <p>
+ * A {@code WireAdminEvent} of type {@link WireAdminEvent#WIRE_DISCONNECTED}
+ * must be broadcast by the Wire Admin service when the {@code Wire} becomes
+ * disconnected.
+ *
+ * @return {@code true} if both the Producer and Consumer for this
+ * {@code Wire} object are connected to the {@code Wire} object;
+ * {@code false} otherwise.
+ */
+ public boolean isConnected();
+
+ /**
+ * Return the list of data types understood by the Consumer service
+ * connected to this {@code Wire} object. Note that subclasses of the
+ * classes in this list are acceptable data types as well.
+ *
+ * <p>
+ * The list is the value of the
+ * {@link WireConstants#WIREADMIN_CONSUMER_FLAVORS} service property of the
+ * Consumer service object connected to this object. If no such property was
+ * registered or the type of the property value is not {@code Class[]}, this
+ * method must return {@code null}.
+ *
+ * @return An array containing the list of classes understood by the
+ * Consumer service or {@code null} if the {@code Wire} is not
+ * connected, or the consumer did not register a
+ * {@link WireConstants#WIREADMIN_CONSUMER_FLAVORS} property or the
+ * value of the property is not of type {@code Class[]}.
+ */
+ public Class[] getFlavors();
+
+ /**
+ * Update the value.
+ *
+ * <p>
+ * This methods is called by the Producer service to notify the Consumer
+ * service connected to this {@code Wire} object of an updated value.
+ * <p>
+ * If the properties of this {@code Wire} object contain a
+ * {@link WireConstants#WIREADMIN_FILTER} property, then filtering is
+ * performed. If the Producer service connected to this {@code Wire} object
+ * was registered with the service property
+ * {@link WireConstants#WIREADMIN_PRODUCER_FILTERS}, the Producer service
+ * will perform the filtering according to the rules specified for the
+ * filter. Otherwise, this {@code Wire} object will perform the filtering of
+ * the value.
+ * <p>
+ * If no filtering is done, or the filter indicates the updated value should
+ * be delivered to the Consumer service, then this {@code Wire} object must
+ * call the {@link Consumer#updated(Wire, Object)} method with the updated
+ * value. If this {@code Wire} object is not connected, then the Consumer
+ * service must not be called and the value is ignored.
+ * <p>
+ * If the value is an {@code Envelope} object, and the scope name is not
+ * permitted, then the {@code Wire} object must ignore this call and not
+ * transfer the object to the Consumer service.
+ *
+ * <p>
+ * A {@code WireAdminEvent} of type {@link WireAdminEvent#WIRE_TRACE} must
+ * be broadcast by the Wire Admin service after the Consumer service has
+ * been successfully called.
+ *
+ * @param value The updated value. The value should be an instance of one of
+ * the types returned by {@link #getFlavors()}.
+ * @see WireConstants#WIREADMIN_FILTER
+ */
+ public void update(Object value);
+
+ /**
+ * Poll for an updated value.
+ *
+ * <p>
+ * This methods is normally called by the Consumer service to request an
+ * updated value from the Producer service connected to this {@code Wire}
+ * object. This {@code Wire} object will call the
+ * {@link Producer#polled(Wire)} method to obtain an updated value. If this
+ * {@code Wire} object is not connected, then the Producer service must not
+ * be called.
+ * <p>
+ *
+ * If this {@code Wire} object has a scope, then this method must return an
+ * array of {@code Envelope} objects. The objects returned must match the
+ * scope of this object. The {@code Wire} object must remove all
+ * {@code Envelope} objects with a scope name that is not in the
+ * {@code Wire} object's scope. Thus, the list of objects returned must only
+ * contain {@code Envelope} objects with a permitted scope name. If the
+ * array becomes empty, {@code null} must be returned.
+ *
+ * <p>
+ * A {@code WireAdminEvent} of type {@link WireAdminEvent#WIRE_TRACE} must
+ * be broadcast by the Wire Admin service after the Producer service has
+ * been successfully called.
+ *
+ * @return A value whose type should be one of the types returned by
+ * {@link #getFlavors()},{@code Envelope[]}, or {@code null} if the
+ * {@code Wire} object is not connected, the Producer service threw
+ * an exception, or the Producer service returned a value which is
+ * not an instance of one of the types returned by
+ * {@link #getFlavors()}.
+ */
+ public Object poll();
+
+ /**
+ * Return the last value sent through this {@code Wire} object.
+ *
+ * <p>
+ * The returned value is the most recent, valid value passed to the
+ * {@link #update(Object)} method or returned by the {@link #poll()} method
+ * of this object. If filtering is performed by this {@code Wire} object,
+ * this methods returns the last value provided by the Producer service.
+ * This value may be an {@code Envelope[]} when the Producer service uses
+ * scoping. If the return value is an Envelope object (or array), it must be
+ * verified that the Consumer service has the proper WirePermission to see
+ * it.
+ *
+ * @return The last value passed though this {@code Wire} object or
+ * {@code null} if no valid values have been passed or the Consumer
+ * service has no permission.
+ */
+ public Object getLastValue();
+
+ /**
+ * Return the wire properties for this {@code Wire} object.
+ *
+ * @return The properties for this {@code Wire} object. The returned
+ * {@code Dictionary} must be read only.
+ */
+ public Dictionary getProperties();
+
+ /**
+ * Return the calculated scope of this {@code Wire} object.
+ *
+ * The purpose of the {@code Wire} object's scope is to allow a Producer
+ * and/or Consumer service to produce/consume different types over a single
+ * {@code Wire} object (this was deemed necessary for efficiency reasons).
+ * Both the Consumer service and the Producer service must set an array of
+ * scope names (their scope) with the service registration property
+ * {@code WIREADMIN_PRODUCER_SCOPE}, or {@code WIREADMIN_CONSUMER_SCOPE}
+ * when they can produce multiple types. If a Producer service can produce
+ * different types, it should set this property to the array of scope names
+ * it can produce, the Consumer service must set the array of scope names it
+ * can consume. The scope of a {@code Wire} object is defined as the
+ * intersection of permitted scope names of the Producer service and
+ * Consumer service.
+ * <p>
+ * If neither the Consumer, or the Producer service registers scope names
+ * with its service registration, then the {@code Wire} object's scope must
+ * be {@code null}.
+ * <p>
+ * The {@code Wire} object's scope must not change when a Producer or
+ * Consumer services modifies its scope.
+ * <p>
+ * A scope name is permitted for a Producer service when the registering
+ * bundle has {@code WirePermission[name,PRODUCE]}, and for a Consumer
+ * service when the registering bundle has
+ * {@code WirePermission[name,CONSUME]}.
+ * <p>
+ * If either Consumer service or Producer service has not set a
+ * {@code WIREADMIN_*_SCOPE} property, then the returned value must be
+ * {@code null}.
+ * <p>
+ * If the scope is set, the {@code Wire} object must enforce the scope names
+ * when {@code Envelope} objects are used as a parameter to update or
+ * returned from the {@code poll} method. The {@code Wire} object must then
+ * remove all {@code Envelope} objects with a scope name that is not
+ * permitted.
+ *
+ * @return A list of permitted scope names or null if the Produce or
+ * Consumer service has set no scope names.
+ */
+ public String[] getScope();
+
+ /**
+ * Return true if the given name is in this {@code Wire} object's scope.
+ *
+ * @param name The scope name
+ * @return true if the name is listed in the permitted scope names
+ */
+ public boolean hasScope(String name);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdmin.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdmin.java
new file mode 100644
index 000000000..783de096c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdmin.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+import java.util.Dictionary;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * Wire Administration service.
+ *
+ * <p>
+ * This service can be used to create {@code Wire} objects connecting a Producer
+ * service and a Consumer service. {@code Wire} objects also have wire
+ * properties that may be specified when a {@code Wire} object is created. The
+ * Producer and Consumer services may use the {@code Wire} object's properties
+ * to manage or control their interaction. The use of {@code Wire} object's
+ * properties by a Producer or Consumer services is optional.
+ *
+ * <p>
+ * Security Considerations. A bundle must have
+ * {@code ServicePermission[WireAdmin,GET]} to get the Wire Admin service to
+ * create, modify, find, and delete {@code Wire} objects.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface WireAdmin {
+ /**
+ * Create a new {@code Wire} object that connects a Producer service to a
+ * Consumer service.
+ *
+ * The Producer service and Consumer service do not have to be registered
+ * when the {@code Wire} object is created.
+ *
+ * <p>
+ * The {@code Wire} configuration data must be persistently stored. All
+ * {@code Wire} connections are reestablished when the {@code WireAdmin}
+ * service is registered. A {@code Wire} can be permanently removed by using
+ * the {@link #deleteWire(Wire)} method.
+ *
+ * <p>
+ * The {@code Wire} object's properties must have case insensitive
+ * {@code String} objects as keys (like the Framework). However, the case of
+ * the key must be preserved.
+ *
+ * <p>
+ * The {@code WireAdmin} service must automatically add the following
+ * {@code Wire} properties:
+ * <ul>
+ * <li>{@link WireConstants#WIREADMIN_PID} set to the value of the
+ * {@code Wire} object's persistent identity (PID). This value is generated
+ * by the Wire Admin service when a {@code Wire} object is created.</li>
+ * <li>{@link WireConstants#WIREADMIN_PRODUCER_PID} set to the value of
+ * Producer service's PID.</li>
+ * <li>{@link WireConstants#WIREADMIN_CONSUMER_PID} set to the value of
+ * Consumer service's PID.</li>
+ * </ul>
+ * If the {@code properties} argument already contains any of these keys,
+ * then the supplied values are replaced with the values assigned by the
+ * Wire Admin service.
+ *
+ * <p>
+ * The Wire Admin service must broadcast a {@code WireAdminEvent} of type
+ * {@link WireAdminEvent#WIRE_CREATED} after the new {@code Wire} object
+ * becomes available from {@link #getWires(String)}.
+ *
+ * @param producerPID The {@code service.pid} of the Producer service to be
+ * connected to the {@code Wire} object.
+ * @param consumerPID The {@code service.pid} of the Consumer service to be
+ * connected to the {@code Wire} object.
+ * @param properties The {@code Wire} object's properties. This argument may
+ * be {@code null} if the caller does not wish to define any
+ * {@code Wire} object's properties.
+ * @return The {@code Wire} object for this connection.
+ *
+ * @throws java.lang.IllegalArgumentException If {@code properties} contains
+ * invalid wire types or case variants of the same key name.
+ */
+ public Wire createWire(String producerPID, String consumerPID, Dictionary properties);
+
+ /**
+ * Delete a {@code Wire} object.
+ *
+ * <p>
+ * The {@code Wire} object representing a connection between a Producer
+ * service and a Consumer service must be removed. The persistently stored
+ * configuration data for the {@code Wire} object must destroyed. The
+ * {@code Wire} object's method {@link Wire#isValid()} will return
+ * {@code false} after it is deleted.
+ *
+ * <p>
+ * The Wire Admin service must broadcast a {@code WireAdminEvent} of type
+ * {@link WireAdminEvent#WIRE_DELETED} after the {@code Wire} object becomes
+ * invalid.
+ *
+ * @param wire The {@code Wire} object which is to be deleted.
+ */
+ public void deleteWire(Wire wire);
+
+ /**
+ * Update the properties of a {@code Wire} object.
+ *
+ * The persistently stored configuration data for the {@code Wire} object is
+ * updated with the new properties and then the Consumer and Producer
+ * services will be called at the respective
+ * {@link Consumer#producersConnected(Wire[])} and
+ * {@link Producer#consumersConnected(Wire[])} methods.
+ *
+ * <p>
+ * The Wire Admin service must broadcast a {@code WireAdminEvent} of type
+ * {@link WireAdminEvent#WIRE_UPDATED} after the updated properties are
+ * available from the {@code Wire} object.
+ *
+ * @param wire The {@code Wire} object which is to be updated.
+ * @param properties The new {@code Wire} object's properties or
+ * {@code null} if no properties are required.
+ *
+ * @throws java.lang.IllegalArgumentException If {@code properties} contains
+ * invalid wire types or case variants of the same key name.
+ */
+ public void updateWire(Wire wire, Dictionary properties);
+
+ /**
+ * Return the {@code Wire} objects that match the given {@code filter}.
+ *
+ * <p>
+ * The list of available {@code Wire} objects is matched against the
+ * specified {@code filter}.{@code Wire} objects which match the
+ * {@code filter} must be returned. These {@code Wire} objects are not
+ * necessarily connected. The Wire Admin service should not return invalid
+ * {@code Wire} objects, but it is possible that a {@code Wire} object is
+ * deleted after it was placed in the list.
+ *
+ * <p>
+ * The filter matches against the {@code Wire} object's properties including
+ * {@link WireConstants#WIREADMIN_PRODUCER_PID},
+ * {@link WireConstants#WIREADMIN_CONSUMER_PID} and
+ * {@link WireConstants#WIREADMIN_PID}.
+ *
+ * @param filter Filter string to select {@code Wire} objects or
+ * {@code null} to select all {@code Wire} objects.
+ * @return An array of {@code Wire} objects which match the {@code filter}
+ * or {@code null} if no {@code Wire} objects match the
+ * {@code filter}.
+ * @throws org.osgi.framework.InvalidSyntaxException If the specified
+ * {@code filter} has an invalid syntax.
+ * @see org.osgi.framework.Filter
+ */
+ public Wire[] getWires(String filter) throws InvalidSyntaxException;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminEvent.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminEvent.java
new file mode 100644
index 000000000..665e72cdd
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminEvent.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A Wire Admin Event.
+ *
+ * <p>
+ * {@code WireAdminEvent} objects are delivered to all registered
+ * {@code WireAdminListener} service objects which specify an interest in the
+ * {@code WireAdminEvent} type. Events must be delivered in chronological order
+ * with respect to each listener. For example, a {@code WireAdminEvent} of type
+ * {@link #WIRE_CONNECTED} must be delivered before a {@code WireAdminEvent} of
+ * type {@link #WIRE_DISCONNECTED} for a particular {@code Wire} object.
+ *
+ * <p>
+ * A type code is used to identify the type of event. The following event types
+ * are defined:
+ * <ul>
+ * <li>{@link #WIRE_CREATED}</li>
+ * <li>{@link #WIRE_CONNECTED}</li>
+ * <li>{@link #WIRE_UPDATED}</li>
+ * <li>{@link #WIRE_TRACE}</li>
+ * <li>{@link #WIRE_DISCONNECTED}</li>
+ * <li>{@link #WIRE_DELETED}</li>
+ * <li>{@link #PRODUCER_EXCEPTION}</li>
+ * <li>{@link #CONSUMER_EXCEPTION}</li>
+ * </ul>
+ * Additional event types may be defined in the future.
+ *
+ * <p>
+ * Event type values must be unique and disjoint bit values. Event types must be
+ * defined as a bit in a 32 bit integer and can thus be bitwise OR'ed together.
+ * <p>
+ * Security Considerations. {@code WireAdminEvent} objects contain {@code Wire}
+ * objects. Care must be taken in the sharing of {@code Wire} objects with other
+ * bundles.
+ *
+ * @see WireAdminListener
+ * @Immutable
+ * @author $Id$
+ */
+public class WireAdminEvent {
+ /**
+ * The WireAdmin service which created this event.
+ */
+ private final ServiceReference reference;
+ /**
+ * The {@code Wire} object associated with this event.
+ */
+ private final Wire wire;
+ /**
+ * Type of this event.
+ *
+ * @see #getType()
+ */
+ private final int type;
+ /**
+ * Exception associates with this the event.
+ */
+ private final Throwable throwable;
+ /**
+ * A Producer service method has thrown an exception.
+ *
+ * <p>
+ * This {@code WireAdminEvent} type indicates that a Producer service method
+ * has thrown an exception. The {@link WireAdminEvent#getThrowable()} method
+ * will return the exception that the Producer service method raised.
+ *
+ * <p>
+ * The value of {@code PRODUCER_EXCEPTION} is 0x00000001.
+ */
+ public final static int PRODUCER_EXCEPTION = 0x00000001;
+ /**
+ * A Consumer service method has thrown an exception.
+ *
+ * <p>
+ * This {@code WireAdminEvent} type indicates that a Consumer service method
+ * has thrown an exception. The {@link WireAdminEvent#getThrowable()} method
+ * will return the exception that the Consumer service method raised.
+ *
+ * <p>
+ * The value of {@code CONSUMER_EXCEPTION} is 0x00000002.
+ */
+ public final static int CONSUMER_EXCEPTION = 0x00000002;
+ /**
+ * A {@code Wire} has been created.
+ *
+ * <p>
+ * This {@code WireAdminEvent} type that indicates that a new {@code Wire}
+ * object has been created.
+ *
+ * An event is broadcast when
+ * {@link WireAdmin#createWire(String, String, java.util.Dictionary)} is
+ * called. The {@link WireAdminEvent#getWire()} method will return the
+ * {@code Wire} object that has just been created.
+ *
+ * <p>
+ * The value of {@code WIRE_CREATED} is 0x00000004.
+ */
+ public final static int WIRE_CREATED = 0x00000004;
+ /**
+ * A {@code Wire} has been updated.
+ *
+ * <p>
+ * This {@code WireAdminEvent} type that indicates that an existing
+ * {@code Wire} object has been updated with new properties.
+ *
+ * An event is broadcast when
+ * {@link WireAdmin#updateWire(Wire, java.util.Dictionary)} is called with a
+ * valid wire. The {@link WireAdminEvent#getWire()} method will return the
+ * {@code Wire} object that has just been updated.
+ *
+ * <p>
+ * The value of {@code WIRE_UPDATED} is 0x00000008.
+ */
+ public final static int WIRE_UPDATED = 0x00000008;
+ /**
+ * A {@code Wire} has been deleted.
+ *
+ * <p>
+ * This {@code WireAdminEvent} type that indicates that an existing wire has
+ * been deleted.
+ *
+ * An event is broadcast when {@link WireAdmin#deleteWire(Wire)} is called
+ * with a valid wire. {@link WireAdminEvent#getWire()} will return the
+ * {@code Wire} object that has just been deleted.
+ *
+ * <p>
+ * The value of {@code WIRE_DELETED} is 0x00000010.
+ */
+ public final static int WIRE_DELETED = 0x00000010;
+ /**
+ * The {@code WireAdminEvent} type that indicates that an existing
+ * {@code Wire} object has become connected.
+ *
+ * The Consumer object and the Producer object that are associated with the
+ * {@code Wire} object have both been registered and the {@code Wire} object
+ * is connected. See {@link Wire#isConnected()} for a description of the
+ * connected state. This event may come before the
+ * {@code producersConnected} and {@code consumersConnected} method have
+ * returned or called to allow synchronous delivery of the events. Both
+ * methods can cause other {@code WireAdminEvent} s to take place and
+ * requiring this event to be send before these methods are returned would
+ * mandate asynchronous delivery.
+ *
+ * <p>
+ * The value of {@code WIRE_CONNECTED} is 0x00000020.
+ */
+ public final static int WIRE_CONNECTED = 0x00000020;
+ /**
+ * The {@code WireAdminEvent} type that indicates that an existing
+ * {@code Wire} object has become disconnected.
+ *
+ * The Consumer object or/and Producer object is/are unregistered breaking
+ * the connection between the two. See {@link Wire#isConnected} for a
+ * description of the connected state.
+ *
+ * <p>
+ * The value of {@code WIRE_DISCONNECTED} is 0x00000040.
+ */
+ public final static int WIRE_DISCONNECTED = 0x00000040;
+ /**
+ * The {@code WireAdminEvent} type that indicates that a new value is
+ * transferred over the {@code Wire} object.
+ *
+ * This event is sent after the Consumer service has been notified by
+ * calling the {@link Consumer#updated(Wire, Object)} method or the Consumer
+ * service requested a new value with the {@link Wire#poll()} method. This
+ * is an advisory event meaning that when this event is received, another
+ * update may already have occurred and this the {@link Wire#getLastValue()}
+ * method returns a newer value then the value that was communicated for
+ * this event.
+ *
+ * <p>
+ * The value of {@code WIRE_TRACE} is 0x00000080.
+ */
+ public final static int WIRE_TRACE = 0x00000080;
+
+ /**
+ * Constructs a {@code WireAdminEvent} object from the given
+ * {@code ServiceReference} object, event type, {@code Wire} object and
+ * exception.
+ *
+ * @param reference The {@code ServiceReference} object of the Wire Admin
+ * service that created this event.
+ * @param type The event type. See {@link #getType()}.
+ * @param wire The {@code Wire} object associated with this event.
+ * @param exception An exception associated with this event. This may be
+ * {@code null} if no exception is associated with this event.
+ */
+ public WireAdminEvent(ServiceReference reference, int type, Wire wire, Throwable exception) {
+ this.reference = reference;
+ this.wire = wire;
+ this.type = type;
+ this.throwable = exception;
+ }
+
+ /**
+ * Return the {@code ServiceReference} object of the Wire Admin service that
+ * created this event.
+ *
+ * @return The {@code ServiceReference} object for the Wire Admin service
+ * that created this event.
+ */
+ public ServiceReference getServiceReference() {
+ return reference;
+ }
+
+ /**
+ * Return the {@code Wire} object associated with this event.
+ *
+ * @return The {@code Wire} object associated with this event or
+ * {@code null} when no {@code Wire} object is associated with the
+ * event.
+ */
+ public Wire getWire() {
+ return wire;
+ }
+
+ /**
+ * Return the type of this event.
+ * <p>
+ * The type values are:
+ * <ul>
+ * <li>{@link #WIRE_CREATED}</li>
+ * <li>{@link #WIRE_CONNECTED}</li>
+ * <li>{@link #WIRE_UPDATED}</li>
+ * <li>{@link #WIRE_TRACE}</li>
+ * <li>{@link #WIRE_DISCONNECTED}</li>
+ * <li>{@link #WIRE_DELETED}</li>
+ * <li>{@link #PRODUCER_EXCEPTION}</li>
+ * <li>{@link #CONSUMER_EXCEPTION}</li>
+ * </ul>
+ *
+ * @return The type of this event.
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Returns the exception associated with the event, if any.
+ *
+ * @return An exception or {@code null} if no exception is associated with
+ * this event.
+ */
+ public Throwable getThrowable() {
+ return throwable;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminListener.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminListener.java
new file mode 100644
index 000000000..0a0f329f6
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireAdminListener.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+/**
+ * Listener for Wire Admin Events.
+ *
+ * <p>
+ * {@code WireAdminListener} objects are registered with the Framework service
+ * registry and are notified with a {@code WireAdminEvent} object when an event
+ * is broadcast.
+ * <p>
+ * {@code WireAdminListener} objects can inspect the received
+ * {@code WireAdminEvent} object to determine its type, the {@code Wire} object
+ * with which it is associated, and the Wire Admin service that broadcasts the
+ * event.
+ *
+ * <p>
+ * {@code WireAdminListener} objects must be registered with a service property
+ * {@link WireConstants#WIREADMIN_EVENTS} whose value is a bitwise OR of all the
+ * event types the listener is interested in receiving.
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * Integer mask = new Integer(WIRE_TRACE | WIRE_CONNECTED | WIRE_DISCONNECTED);
+ * Hashtable ht = new Hashtable();
+ * ht.put(WIREADMIN_EVENTS, mask);
+ * context.registerService(WireAdminListener.class.getName(), this, ht);
+ * </pre>
+ *
+ * If a {@code WireAdminListener} object is registered without a service
+ * property {@link WireConstants#WIREADMIN_EVENTS}, then the
+ * {@code WireAdminListener} will receive no events.
+ *
+ * <p>
+ * Security Considerations. Bundles wishing to monitor {@code WireAdminEvent}
+ * objects will require {@code ServicePermission[WireAdminListener,REGISTER]} to
+ * register a {@code WireAdminListener} service. Since {@code WireAdminEvent}
+ * objects contain {@code Wire} objects, care must be taken in assigning
+ * permission to register a {@code WireAdminListener} service.
+ *
+ * @see WireAdminEvent
+ *
+ * @author $Id$
+ */
+public interface WireAdminListener {
+ /**
+ * Receives notification of a broadcast {@code WireAdminEvent} object.
+ *
+ * The event object will be of an event type specified in this
+ * {@code WireAdminListener} service's
+ * {@link WireConstants#WIREADMIN_EVENTS} service property.
+ *
+ * @param event The {@code WireAdminEvent} object.
+ */
+ void wireAdminEvent(WireAdminEvent event);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireConstants.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireConstants.java
new file mode 100644
index 000000000..12b9e446d
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WireConstants.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+/**
+ * Defines standard names for {@code Wire} properties, wire filter attributes,
+ * Consumer and Producer service properties.
+ *
+ * @noimplement
+ * @author $Id$
+ */
+public interface WireConstants {
+ /**
+ * {@code Wire} property key (named {@code wireadmin.pid}) specifying the
+ * persistent identity (PID) of this {@code Wire} object.
+ *
+ * <p>
+ * Each {@code Wire} object has a PID to allow unique and persistent
+ * identification of a specific {@code Wire} object. The PID must be
+ * generated by the {@link WireAdmin} service when the {@code Wire} object
+ * is created.
+ *
+ * <p>
+ * This wire property is automatically set by the Wire Admin service. The
+ * value of the property must be of type {@code String}.
+ */
+ public final static String WIREADMIN_PID = "wireadmin.pid";
+ /**
+ * A service registration property for a Producer service that is composite.
+ * It contains the names of the composite Consumer services it can
+ * inter-operate with. Inter-operability exists when any name in this array
+ * matches any name in the array set by the Consumer service. The type of
+ * this property must be {@code String[]}.
+ */
+ public final static String WIREADMIN_PRODUCER_COMPOSITE = "wireadmin.producer.composite";
+ /**
+ * A service registration property for a Consumer service that is composite.
+ * It contains the names of the composite Producer services it can cooperate
+ * with. Inter-operability exists when any name in this array matches any
+ * name in the array set by the Producer service. The type of this property
+ * must be {@code String[]}.
+ */
+ public final static String WIREADMIN_CONSUMER_COMPOSITE = "wireadmin.consumer.composite";
+ /**
+ * Service registration property key (named {@code wireadmin.producer.scope}
+ * ) specifying a list of names that may be used to define the scope of this
+ * {@code Wire} object. A Producer service should set this service property
+ * when it can produce more than one kind of value. This property is only
+ * used during registration, modifying the property must not have any effect
+ * of the {@code Wire} object's scope. Each name in the given list mist have
+ * {@code WirePermission[name,PRODUCE]} or else is ignored. The type of this
+ * service registration property must be {@code String[]}.
+ *
+ * @see Wire#getScope()
+ * @see #WIREADMIN_CONSUMER_SCOPE
+ */
+ public final static String WIREADMIN_PRODUCER_SCOPE = "wireadmin.producer.scope";
+ /**
+ * Service registration property key (named {@code wireadmin.consumer.scope}
+ * ) specifying a list of names that may be used to define the scope of this
+ * {@code Wire} object. A {@code Consumer} service should set this service
+ * property when it can produce more than one kind of value. This property
+ * is only used during registration, modifying the property must not have
+ * any effect of the {@code Wire} object's scope. Each name in the given
+ * list mist have {@code WirePermission[name,CONSUME]} or else is ignored.
+ * The type of this service registration property must be {@code String[]}.
+ *
+ * @see Wire#getScope()
+ * @see #WIREADMIN_PRODUCER_SCOPE
+ */
+ public final static String WIREADMIN_CONSUMER_SCOPE = "wireadmin.consumer.scope";
+ /**
+ * Matches all scope names.
+ */
+ public final static String WIREADMIN_SCOPE_ALL[] = {"*"};
+ /**
+ * {@code Wire} property key (named {@code wireadmin.producer.pid})
+ * specifying the {@code service.pid} of the associated Producer service.
+ *
+ * <p>
+ * This wire property is automatically set by the WireAdmin service. The
+ * value of the property must be of type {@code String}.
+ */
+ public final static String WIREADMIN_PRODUCER_PID = "wireadmin.producer.pid";
+ /**
+ * {@code Wire} property key (named {@code wireadmin.consumer.pid})
+ * specifying the {@code service.pid} of the associated Consumer service.
+ *
+ * <p>
+ * This wire property is automatically set by the Wire Admin service. The
+ * value of the property must be of type {@code String}.
+ */
+ public final static String WIREADMIN_CONSUMER_PID = "wireadmin.consumer.pid";
+ /**
+ * {@code Wire} property key (named {@code wireadmin.filter}) specifying a
+ * filter used to control the delivery rate of data between the Producer and
+ * the Consumer service.
+ *
+ * <p>
+ * This property should contain a filter as described in the {@code Filter}
+ * class. The filter can be used to specify when an updated value from the
+ * Producer service should be delivered to the Consumer service. In many
+ * cases the Consumer service does not need to receive the data with the
+ * same rate that the Producer service can generate data. This property can
+ * be used to control the delivery rate.
+ * <p>
+ * The filter can use a number of pre-defined attributes that can be used to
+ * control the delivery of new data values. If the filter produces a match
+ * upon the wire filter attributes, the Consumer service should be notifed
+ * of the updated data value.
+ * <p>
+ * If the Producer service was registered with the
+ * {@link #WIREADMIN_PRODUCER_FILTERS} service property indicating that the
+ * Producer service will perform the data filtering then the {@code Wire}
+ * object will not perform data filtering. Otherwise, the {@code Wire}
+ * object must perform basic filtering. Basic filtering includes supporting
+ * the following standard wire filter attributes:
+ * <ul>
+ * <li>{@link #WIREVALUE_CURRENT} - Current value</li>
+ * <li>{@link #WIREVALUE_PREVIOUS} - Previous value</li>
+ * <li>{@link #WIREVALUE_DELTA_ABSOLUTE} - Absolute delta</li>
+ * <li>{@link #WIREVALUE_DELTA_RELATIVE} - Relative delta</li>
+ * <li>{@link #WIREVALUE_ELAPSED} - Elapsed time</li>
+ * </ul>
+ *
+ * @see org.osgi.framework.Filter
+ */
+ public final static String WIREADMIN_FILTER = "wireadmin.filter";
+ /* Wire filter attribute names. */
+ /**
+ * {@code Wire} object's filter attribute (named {@code wirevalue.current})
+ * representing the current value.
+ */
+ public final static String WIREVALUE_CURRENT = "wirevalue.current";
+ /**
+ * {@code Wire} object's filter attribute (named {@code wirevalue.previous})
+ * representing the previous value.
+ */
+ public final static String WIREVALUE_PREVIOUS = "wirevalue.previous";
+ /**
+ * {@code Wire} object's filter attribute (named
+ * {@code wirevalue.delta.absolute}) representing the absolute delta. The
+ * absolute (always positive) difference between the last update and the
+ * current value (only when numeric). This attribute must not be used when
+ * the values are not numeric.
+ */
+ public final static String WIREVALUE_DELTA_ABSOLUTE = "wirevalue.delta.absolute";
+ /**
+ * {@code Wire} object's filter attribute (named
+ * {@code wirevalue.delta.relative}) representing the relative delta. The
+ * relative difference is |{@code previous}-{@code current} |/|
+ * {@code current}| (only when numeric). This attribute must not be used
+ * when the values are not numeric.
+ */
+ public final static String WIREVALUE_DELTA_RELATIVE = "wirevalue.delta.relative";
+ /**
+ * {@code Wire} object's filter attribute (named {@code wirevalue.elapsed})
+ * representing the elapsed time, in ms, between this filter evaluation and
+ * the last update of the {@code Consumer} service.
+ */
+ public final static String WIREVALUE_ELAPSED = "wirevalue.elapsed";
+ /* Service registration property key names. */
+ /**
+ * Service Registration property (named {@code wireadmin.producer.filters}).
+ * A {@code Producer} service registered with this property indicates to the
+ * Wire Admin service that the Producer service implements at least the
+ * filtering as described for the {@link #WIREADMIN_FILTER} property. If the
+ * Producer service is not registered with this property, the {@code Wire}
+ * object must perform the basic filtering as described in
+ * {@link #WIREADMIN_FILTER}.
+ *
+ * <p>
+ * The type of the property value is not relevant. Only its presence is
+ * relevant.
+ */
+ public final static String WIREADMIN_PRODUCER_FILTERS = "wireadmin.producer.filters";
+ /**
+ * Service Registration property (named {@code wireadmin.consumer.flavors})
+ * specifying the list of data types understood by this Consumer service.
+ *
+ * <p>
+ * The Consumer service object must be registered with this service
+ * property. The list must be in the order of preference with the first type
+ * being the most preferred. The value of the property must be of type
+ * {@code Class[]}.
+ */
+ public final static String WIREADMIN_CONSUMER_FLAVORS = "wireadmin.consumer.flavors";
+ /**
+ * Service Registration property (named {@code wireadmin.producer.flavors})
+ * specifying the list of data types available from this Producer service.
+ *
+ * <p>
+ * The Producer service object should be registered with this service
+ * property.
+ *
+ * <p>
+ * The value of the property must be of type {@code Class[]}.
+ */
+ public final static String WIREADMIN_PRODUCER_FLAVORS = "wireadmin.producer.flavors";
+ /**
+ * Service Registration property (named {@code wireadmin.events}) specifying
+ * the {@code WireAdminEvent} type of interest to a Wire Admin Listener
+ * service. The value of the property is a bitwise OR of all the
+ * {@code WireAdminEvent} types the Wire Admin Listener service wishes to
+ * receive and must be of type {@code Integer}.
+ *
+ * @see WireAdminEvent
+ */
+ public final static String WIREADMIN_EVENTS = "wireadmin.events";
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WirePermission.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WirePermission.java
new file mode 100644
index 000000000..99a7e308b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/WirePermission.java
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.wireadmin;
+
+import java.io.IOException;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * Permission for the scope of a {@code Wire} object. When a {@code Envelope}
+ * object is used for communication with the {@code poll} or {@code update}
+ * method, and the scope is set, then the {@code Wire} object must verify that
+ * the Consumer service has {@code WirePermission[name,CONSUME]} and the
+ * Producer service has {@code WirePermission[name,PRODUCE]} for all names in
+ * the scope.
+ * <p>
+ * The names are compared with the normal rules for permission names. This means
+ * that they may end with a "*" to indicate wildcards. E.g. Door.* indicates all
+ * scope names starting with the string "Door". The last period is required due
+ * to the implementations of the {@code BasicPermission} class.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+final public class WirePermission extends BasicPermission {
+ static final long serialVersionUID = -5583709391516569321L;
+ /**
+ * The action string for the {@code produce} action.
+ */
+ public static final String PRODUCE = "produce";
+ /**
+ * The action string for the {@code consume} action.
+ */
+ public static final String CONSUME = "consume";
+ private final static int ACTION_PRODUCE = 0x00000001;
+ private final static int ACTION_CONSUME = 0x00000002;
+ private final static int ACTION_ALL = ACTION_PRODUCE | ACTION_CONSUME;
+ private final static int ACTION_NONE = 0;
+ /**
+ * The actions mask.
+ */
+ private transient int action_mask;
+ /**
+ * The actions in canonical form.
+ *
+ * @serial
+ */
+ private volatile String actions = null;
+
+ /**
+ * Create a new WirePermission with the given name (may be wildcard) and
+ * actions.
+ *
+ * @param name Wire name.
+ * @param actions {@code produce}, {@code consume} (canonical order).
+ */
+ public WirePermission(String name, String actions) {
+ this(name, parseActions(actions));
+ }
+
+ /**
+ * Package private constructor used by WirePermissionCollection.
+ *
+ * @param name class name
+ * @param mask action mask
+ */
+ WirePermission(String name, int mask) {
+ super(name);
+ setTransients(mask);
+ }
+
+ /**
+ * Called by constructors and when deserialized.
+ *
+ * @param mask action mask
+ */
+ private synchronized void setTransients(int mask) {
+ if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+ throw new IllegalArgumentException("invalid action string");
+ }
+ action_mask = mask;
+ }
+
+ /**
+ * Returns the current action mask. Used by the WirePermissionCollection
+ * object.
+ *
+ * @return The actions mask.
+ */
+ synchronized int getActionsMask() {
+ return action_mask;
+ }
+
+ /**
+ * Parse action string into action mask.
+ *
+ * @param actions Action string.
+ * @return action mask.
+ */
+ private static int parseActions(String actions) {
+ boolean seencomma = false;
+ int mask = ACTION_NONE;
+ if (actions == null) {
+ return mask;
+ }
+ char[] a = actions.toCharArray();
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+ while (i != -1) {
+ char c;
+ // skip whitespace
+ while ((i != -1) && ((c = a[i]) == ' ' || c == '\r' || c == '\n' || c == '\f' || c == '\t'))
+ i--;
+ // check for the known strings
+ int matchlen;
+ if (i >= 6 && (a[i - 6] == 'p' || a[i - 6] == 'P') && (a[i - 5] == 'r' || a[i - 5] == 'R') && (a[i - 4] == 'o' || a[i - 4] == 'O') && (a[i - 3] == 'd' || a[i - 3] == 'D')
+ && (a[i - 2] == 'u' || a[i - 2] == 'U') && (a[i - 1] == 'c' || a[i - 1] == 'C') && (a[i] == 'e' || a[i] == 'E')) {
+ matchlen = 7;
+ mask |= ACTION_PRODUCE;
+ } else
+ if (i >= 6 && (a[i - 6] == 'c' || a[i - 6] == 'C') && (a[i - 5] == 'o' || a[i - 5] == 'O') && (a[i - 4] == 'n' || a[i - 4] == 'N') && (a[i - 3] == 's' || a[i - 3] == 'S')
+ && (a[i - 2] == 'u' || a[i - 2] == 'U') && (a[i - 1] == 'm' || a[i - 1] == 'M') && (a[i] == 'e' || a[i] == 'E')) {
+ matchlen = 7;
+ mask |= ACTION_CONSUME;
+ } else {
+ // parse error
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ // make sure we didn't just match the tail of a word
+ // like "ackbarfregister". Also, skip to the comma.
+ seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch (a[i - matchlen]) {
+ case ',' :
+ seencomma = true;
+ /* FALLTHROUGH */
+ case ' ' :
+ case '\r' :
+ case '\n' :
+ case '\f' :
+ case '\t' :
+ break;
+ default :
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ i--;
+ }
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+ if (seencomma) {
+ throw new IllegalArgumentException("invalid permission: " + actions);
+ }
+ return mask;
+ }
+
+ /**
+ * Checks if this {@code WirePermission} object {@code implies} the
+ * specified permission.
+ * <P>
+ * More specifically, this method returns {@code true} if:
+ * <p>
+ * <ul>
+ * <li><i>p</i> is an instanceof the {@code WirePermission} class,</li>
+ * <li><i>p</i>'s actions are a proper subset of this object's actions, and</li>
+ * <li><i>p</i>'s name is implied by this object's name. For example,
+ * {@code java.*} implies {@code java.home}.</li>
+ * </ul>
+ *
+ * @param p The permission to check against.
+ *
+ * @return {@code true} if the specified permission is implied by this
+ * object; {@code false} otherwise.
+ */
+ public boolean implies(Permission p) {
+ if (p instanceof WirePermission) {
+ WirePermission requested = (WirePermission) p;
+ int requestedMask = requested.getActionsMask();
+ return ((getActionsMask() & requestedMask) == requestedMask) && super.implies(p);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the canonical string representation of the actions. Always
+ * returns present actions in the following order: {@code produce},
+ * {@code consume}.
+ *
+ * @return The canonical string representation of the actions.
+ */
+ public String getActions() {
+ String result = actions;
+ if (result == null) {
+ StringBuffer sb = new StringBuffer();
+ boolean comma = false;
+ int mask = getActionsMask();
+ if ((mask & ACTION_PRODUCE) == ACTION_PRODUCE) {
+ sb.append(PRODUCE);
+ comma = true;
+ }
+ if ((mask & ACTION_CONSUME) == ACTION_CONSUME) {
+ if (comma)
+ sb.append(',');
+ sb.append(CONSUME);
+ }
+ actions = result = sb.toString();
+ }
+ return result;
+ }
+
+ /**
+ * Returns a new {@code PermissionCollection} object for storing
+ * {@code WirePermission} objects.
+ *
+ * @return A new {@code PermissionCollection} object suitable for storing
+ * {@code WirePermission} objects.
+ */
+ public PermissionCollection newPermissionCollection() {
+ return new WirePermissionCollection();
+ }
+
+ /**
+ * Determines the equalty of two {@code WirePermission} objects.
+ *
+ * Checks that specified object has the same name and actions as this
+ * {@code WirePermission} object.
+ *
+ * @param obj The object to test for equality.
+ * @return true if {@code obj} is a {@code WirePermission}, and has the same
+ * name and actions as this {@code WirePermission} object;
+ * {@code false} otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof WirePermission)) {
+ return false;
+ }
+ WirePermission wp = (WirePermission) obj;
+ return (getActionsMask() == wp.getActionsMask()) && getName().equals(wp.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return Hash code value for this object.
+ */
+ public int hashCode() {
+ int h = 31 * 17 + getName().hashCode();
+ h = 31 * h + getActions().hashCode();
+ return h;
+ }
+
+ /**
+ * Returns a string describing this {@code WirePermission}. The convention
+ * is to specify the class name, the permission name, and the actions in the
+ * following format: '(org.osgi.service.wireadmin.WirePermission
+ * &quot;name&quot; &quot;actions&quot;)'.
+ *
+ * @return information about this {@code Permission} object.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ sb.append(getClass().getName());
+ sb.append(" \"");
+ sb.append(getName());
+ String a = getActions();
+ if (a.length() > 0) {
+ sb.append("\" \"");
+ sb.append(a);
+ }
+ sb.append("\")");
+ return sb.toString();
+ }
+
+ /**
+ * WriteObject is called to save the state of the ServicePermission to a
+ * stream. The actions are serialized, and the superclass takes care of the
+ * name.
+ */
+ private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ // Write out the actions. The superclass takes care of the name
+ // call getActions to make sure actions field is initialized
+ if (actions == null)
+ getActions();
+ s.defaultWriteObject();
+ }
+
+ /**
+ * readObject is called to restore the state of the ServicePermission from a
+ * stream.
+ */
+ private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
+ // Read in the action, then initialize the rest
+ s.defaultReadObject();
+ setTransients(parseActions(actions));
+ }
+}
+
+/**
+ * A {@code WirePermissionCollection} stores a set of {@code WirePermission}
+ * permissions.
+ */
+
+final class WirePermissionCollection extends PermissionCollection {
+ static final long serialVersionUID = 2617521094909826016L;
+ /**
+ * Table of permissions.
+ *
+ * @GuardedBy this
+ * @serial
+ */
+ private final Hashtable permissions;
+ /**
+ * Boolean saying if "*" is in the collection.
+ *
+ * @GuardedBy this
+ * @serial
+ */
+ private boolean all_allowed;
+
+ /**
+ * Creates an empty WirePermissionCollection object.
+ *
+ */
+ public WirePermissionCollection() {
+ permissions = new Hashtable();
+ all_allowed = false;
+ }
+
+ /**
+ * Adds a permission to this PermissionCollection.
+ *
+ * @param permission The Permission object to add.
+ *
+ * @throws IllegalArgumentException If the permission is not a
+ * WirePermission object.
+ *
+ * @throws SecurityException If this PermissionCollection has been marked
+ * read-only.
+ */
+ public void add(Permission permission) {
+ if (!(permission instanceof WirePermission)) {
+ throw new IllegalArgumentException("invalid permission: " + permission);
+ }
+ if (isReadOnly()) {
+ throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection");
+ }
+ WirePermission wp = (WirePermission) permission;
+ String name = wp.getName();
+ synchronized (this) {
+ WirePermission existing = (WirePermission) permissions.get(name);
+ if (existing != null) {
+ int oldMask = existing.getActionsMask();
+ int newMask = wp.getActionsMask();
+ if (oldMask != newMask) {
+ permissions.put(name, new WirePermission(name, oldMask | newMask));
+ }
+ } else {
+ permissions.put(name, wp);
+ }
+ if (!all_allowed) {
+ if (name.equals("*")) {
+ all_allowed = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines if a set of permissions implies the permissions expressed in
+ * {@code permission}.
+ *
+ * @param permission The Permission object to compare.
+ *
+ * @return {@code true} if {@code permission} is a proper subset of a
+ * permission in the set; {@code false} otherwise.
+ */
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof WirePermission)) {
+ return false;
+ }
+ WirePermission requested = (WirePermission) permission;
+ WirePermission x;
+ int desired = requested.getActionsMask();
+ int effective = 0;
+ String name = requested.getName();
+ synchronized (this) {
+ // short circuit if the "*" Permission was added
+ if (all_allowed) {
+ x = (WirePermission) permissions.get("*");
+ if (x != null) {
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired)
+ return true;
+ }
+ }
+ // strategy:
+ // Check for full match first. Then work our way up the
+ // name looking for matches on a.b.*
+ x = (WirePermission) permissions.get(name);
+ }
+ if (x != null) {
+ // we have a direct hit!
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ // work our way up the tree...
+ int last;
+ int offset = name.length() - 1;
+ while ((last = name.lastIndexOf(".", offset)) != -1) {
+ name = name.substring(0, last + 1) + "*";
+ synchronized (this) {
+ x = (WirePermission) permissions.get(name);
+ }
+ if (x != null) {
+ effective |= x.getActionsMask();
+ if ((effective & desired) == desired) {
+ return (true);
+ }
+ }
+ offset = last - 1;
+ }
+ // we don't have to check for "*" as it was already checked
+ // at the top (all_allowed), so we just return false
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the Permission objects in the container.
+ *
+ * @return Enumeration of all the Permission objects.
+ */
+ public Enumeration elements() {
+ return permissions.elements();
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/package-info.java
new file mode 100644
index 000000000..b5af96bb0
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Wire Admin 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.wireadmin; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.wireadmin; version="[1.0,1.1)"}
+ *
+ * @version 1.0.1
+ * @author $Id$
+ */
+
+package org.osgi.service.wireadmin;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/packageinfo
new file mode 100644
index 000000000..b3d1f97f7
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/wireadmin/packageinfo
@@ -0,0 +1 @@
+version 1.0.1
diff --git a/bundles/org.eclipse.osgi.util/.classpath b/bundles/org.eclipse.osgi.util/.classpath
index ad7732cd3..64c5e31b7 100644
--- a/bundles/org.eclipse.osgi.util/.classpath
+++ b/bundles/org.eclipse.osgi.util/.classpath
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry path="" kind="lib" sourcepath="src.zip"/>
- <classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/OSGi%Minimum-1.2" kind="con"/>
- <classpathentry path="org.eclipse.pde.core.requiredPlugins" kind="con"/>
- <classpathentry path="bin" kind="output"/>
+ <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.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.osgi.util/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi.util/.settings/org.eclipse.jdt.core.prefs
index f786cfa0a..db619c076 100644
--- a/bundles/org.eclipse.osgi.util/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi.util/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,3 @@
-#Tue Jun 06 11:23:10 CDT 2006
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
@@ -7,24 +6,24 @@ org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
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=disabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.3
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=error
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
@@ -71,6 +70,6 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=en
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF
index 0455dd4be..0743c7661 100644
--- a/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %osgiUtil
Bundle-SymbolicName: org.eclipse.osgi.util
-Bundle-Version: 3.2.300.qualifier
+Bundle-Version: 3.3.0.qualifier
Bundle-Description: %osgiUtilDes
Bundle-Vendor: %eclipse.org
Bundle-Localization: plugin
@@ -12,10 +12,8 @@ Export-Package: org.osgi.util.measurement; version="1.0.1",
org.osgi.util.position; version="1.0.1",
org.osgi.util.xml; version="1.0.1"
Import-Package: org.osgi.framework; version=1.1,
- javax.xml.parsers; resolution:=optional,
+ javax.xml.parsers,
org.osgi.util.measurement; version="[1.0.1, 1.2)",
org.osgi.util.position; version="[1.0.1, 1.2)",
org.osgi.util.xml; version="[1.0.1, 1.2)"
-Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2,
- CDC-1.1/Foundation-1.1,
- J2SE-1.4
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/bundles/org.eclipse.osgi.util/build.properties b/bundles/org.eclipse.osgi.util/build.properties
index 7e2fef041..f11b00703 100644
--- a/bundles/org.eclipse.osgi.util/build.properties
+++ b/bundles/org.eclipse.osgi.util/build.properties
@@ -9,15 +9,10 @@
# IBM Corporation - initial API and implementation
###############################################################################
bin.includes = plugin.properties,\
- org/,\
about.html,\
META-INF/,\
about_files/
-src.includes = src.zip,\
- about.html,\
+src.includes = about.html,\
about_files/
-source.. = .
-output.. = .
-customBuildCallbacks=customBuildCallbacks.xml
-javacSource = 1.5
-javacTarget = 1.5
+source.. = src/
+output.. = bin/
diff --git a/bundles/org.eclipse.osgi.util/customBuildCallbacks.xml b/bundles/org.eclipse.osgi.util/customBuildCallbacks.xml
deleted file mode 100644
index d6250e891..000000000
--- a/bundles/org.eclipse.osgi.util/customBuildCallbacks.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-<!-- ===================================================================== -->
-<!-- Custom targets called from a project's generated build.xml -->
-<!-- Set customBuildCallbacks=<path/to/this/file> in your build.properties.-->
-<!-- ===================================================================== -->
-<project name="Build specific targets and properties" default="noDefault">
-
- <!-- ===================================================================== -->
- <!-- Default target -->
- <!-- ===================================================================== -->
- <target name="noDefault">
- <echo message="This file must be called with explicit targets" />
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target build.jars -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="pre.build.jars">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target build.jars -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="post.build.jars">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target build.sources -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="pre.build.sources">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target build.sources -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder to contain the build results -->
- <!-- ===================================================================== -->
- <target name="post.build.sources">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the compilation target <name> -->
- <!-- Substitute "name" with the name of the compilation target, eg @dot -->
- <!-- Available parameters : -->
- <!-- source.foldern : n = 1 ... N, the source folders -->
- <!-- target.folder : where the results of the compilation go -->
- <!-- <name>.classpath : name = name of the compilation target. A -->
- <!-- reference to the classpath structure. -->
- <!-- ===================================================================== -->
- <target name="pre.name">
- </target>
-
- <target name="pre.@dot">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do during the compilation target <name>, after the compile -->
- <!-- but before jaring. Substitute "name" with the name of the compilation-->
- <!-- target, eg @dot -->
- <!-- Available parameters : -->
- <!-- source.foldern : n = 1 ... N, the source folders -->
- <!-- target.folder : where the results of the compilation go -->
- <!-- <name>.classpath : name = name of the compilation target. A -->
- <!-- reference to the classpath structure. -->
- <!-- ===================================================================== -->
- <target name="post.compile.name">
- </target>
-
- <target name="post.compile.@dot">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the compilation target <name> -->
- <!-- Substitute "name" with the name of the compilation target, eg @dot -->
- <!-- Available parameters : -->
- <!-- jar.location - the location of the compilation results -->
- <!-- <name>.classpath : name = name of the compilation target. A -->
- <!-- reference to the classpath structure. -->
- <!-- ===================================================================== -->
- <target name="post.name">
- </target>
-
- <target name="post.@dot">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target gather.bin.parts -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder containing the build results -->
- <!-- target.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.gather.bin.parts">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target gather.bin.parts -->
- <!-- Available parameters : -->
- <!-- build.result.folder - folder containing the build results -->
- <!-- target.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="post.gather.bin.parts">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target gather.sources -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.gather.sources">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target gather.sources -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="post.gather.sources">
- <unzip src="${target.folder}/src.zip" dest="${target.folder}" overwrite="false"/>
- <delete file="${destination.temp.folder}/src.zip" />
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target gather.logs -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.gather.logs">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target gather.logs -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="post.gather.logs">
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do before the target clean -->
- <!-- Available parameters : -->
- <!-- destination.temp.folder - destination folder -->
- <!-- ===================================================================== -->
- <target name="pre.clean">
- <move file="src.zip" tofile="util_src.zip"/>
- </target>
-
- <!-- ===================================================================== -->
- <!-- Steps to do after the target clean -->
- <!-- Available parameters : -->
- <!-- plugin.destination - final destination of the build -->
- <!-- build.result.folder - results of the compilation -->
- <!-- temp.folder - temporary folder -->
- <!-- ===================================================================== -->
- <target name="post.clean">
- <move file="util_src.zip" tofile="src.zip"/>
- </target>
-</project>
diff --git a/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Measurement.class b/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Measurement.class
deleted file mode 100644
index dc157cc49..000000000
--- a/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Measurement.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/State.class b/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/State.class
deleted file mode 100644
index 8e13882cd..000000000
--- a/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/State.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Unit.class b/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Unit.class
deleted file mode 100644
index 7968831e7..000000000
--- a/bundles/org.eclipse.osgi.util/org/osgi/util/measurement/Unit.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/org/osgi/util/position/Position.class b/bundles/org.eclipse.osgi.util/org/osgi/util/position/Position.class
deleted file mode 100644
index 2ff9b049f..000000000
--- a/bundles/org.eclipse.osgi.util/org/osgi/util/position/Position.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/org/osgi/util/xml/XMLParserActivator.class b/bundles/org.eclipse.osgi.util/org/osgi/util/xml/XMLParserActivator.class
deleted file mode 100644
index 44540fb20..000000000
--- a/bundles/org.eclipse.osgi.util/org/osgi/util/xml/XMLParserActivator.class
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/pom.xml b/bundles/org.eclipse.osgi.util/pom.xml
index 15ecddb61..bee575bd9 100644
--- a/bundles/org.eclipse.osgi.util/pom.xml
+++ b/bundles/org.eclipse.osgi.util/pom.xml
@@ -19,6 +19,6 @@
</parent>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.util</artifactId>
- <version>3.2.300-SNAPSHOT</version>
+ <version>3.3.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/bundles/org.eclipse.osgi.util/src.zip b/bundles/org.eclipse.osgi.util/src.zip
deleted file mode 100644
index 9d64d7b27..000000000
--- a/bundles/org.eclipse.osgi.util/src.zip
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Measurement.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Measurement.java
new file mode 100644
index 000000000..5d6be0f87
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Measurement.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.util.measurement;
+
+/**
+ * Represents a value with an error, a unit and a time-stamp.
+ *
+ * <p>
+ * A {@code Measurement} object is used for maintaining the tuple of value,
+ * error, unit and time-stamp. The value and error are represented as doubles
+ * and the time is measured in milliseconds since midnight, January 1, 1970 UTC.
+ *
+ * <p>
+ * Mathematic methods are provided that correctly calculate taking the error
+ * into account. A runtime error will occur when two measurements are used in an
+ * incompatible way. E.g., when a speed (m/s) is added to a distance (m). The
+ * measurement class will correctly track changes in unit during multiplication
+ * and division, always coercing the result to the most simple form. See
+ * {@link Unit} for more information on the supported units.
+ *
+ * <p>
+ * Errors in the measurement class are absolute errors. Measurement errors
+ * should use the P95 rule. Actual values must fall in the range value +/- error
+ * 95% or more of the time.
+ *
+ * <p>
+ * A {@code Measurement} object is immutable in order to be easily shared.
+ *
+ * <p>
+ * Note: This class has a natural ordering that is inconsistent with equals. See
+ * {@link #compareTo(Object)}.
+ *
+ * @Immutable
+ * @author $Id$
+ */
+public class Measurement implements Comparable {
+ private final double value;
+ private final double error;
+ private final long time;
+ private final Unit unit;
+ private transient String name;
+ private transient int hashCode;
+
+ /**
+ * Create a new {@code Measurement} object.
+ *
+ * @param value The value of the {@code Measurement}.
+ * @param error The error of the {@code Measurement}.
+ * @param unit The {@code Unit} object in which the value is measured. If
+ * this argument is {@code null}, then the unit will be set to
+ * {@link Unit#unity}.
+ * @param time The time measured in milliseconds since midnight, January 1,
+ * 1970 UTC.
+ */
+ public Measurement(double value, double error, Unit unit, long time) {
+ this.value = value;
+ this.error = Math.abs(error);
+ this.unit = (unit != null) ? unit : Unit.unity;
+ this.time = time;
+ name = null;
+ hashCode = 0;
+ }
+
+ /**
+ * Create a new {@code Measurement} object with a time of zero.
+ *
+ * @param value The value of the {@code Measurement}.
+ * @param error The error of the {@code Measurement}.
+ * @param unit The {@code Unit} object in which the value is measured. If
+ * this argument is {@code null}, then the unit will be set to
+ * {@link Unit#unity}.
+ */
+ public Measurement(double value, double error, Unit unit) {
+ this(value, error, unit, 0l);
+ }
+
+ /**
+ * Create a new {@code Measurement} object with an error of 0.0 and a time
+ * of zero.
+ *
+ * @param value The value of the {@code Measurement}.
+ * @param unit The {@code Unit} in which the value is measured. If this
+ * argument is {@code null}, then the unit will be set to
+ * {@link Unit#unity}.
+ */
+ public Measurement(double value, Unit unit) {
+ this(value, 0.0d, unit, 0l);
+ }
+
+ /**
+ * Create a new {@code Measurement} object with an error of 0.0, a unit of
+ * {@link Unit#unity} and a time of zero.
+ *
+ * @param value The value of the {@code Measurement}.
+ */
+ public Measurement(double value) {
+ this(value, 0.0d, null, 0l);
+ }
+
+ /**
+ * Returns the value of this {@code Measurement} object.
+ *
+ * @return The value of this {@code Measurement} object as a double.
+ */
+ public final double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the error of this {@code Measurement} object. The error is always
+ * a positive value.
+ *
+ * @return The error of this {@code Measurement} as a double.
+ */
+ public final double getError() {
+ return error;
+ }
+
+ /**
+ * Returns the {@code Unit} object of this {@code Measurement} object.
+ *
+ * @return The {@code Unit} object of this {@code Measurement} object.
+ *
+ * @see Unit
+ */
+ public final Unit getUnit() {
+ return unit;
+ }
+
+ /**
+ * Returns the time at which this {@code Measurement} object was taken. The
+ * time is measured in milliseconds since midnight, January 1, 1970 UTC, or
+ * zero when not defined.
+ *
+ * @return The time at which this {@code Measurement} object was taken or
+ * zero.
+ */
+ public final long getTime() {
+ return time;
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the product of this
+ * object multiplied by the specified object.
+ *
+ * @param m The {@code Measurement} object that will be multiplied with this
+ * object.
+ * @return A new {@code Measurement} that is the product of this object
+ * multiplied by the specified object. The error and unit of the new
+ * object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified object cannot be multiplied.
+ * @see Unit
+ */
+ public Measurement mul(Measurement m) {
+ double mvalue = m.value;
+ return new Measurement(value * mvalue, Math.abs(value) * m.error + error * Math.abs(mvalue), unit.mul(m.unit), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the product of this
+ * object multiplied by the specified value.
+ *
+ * @param d The value that will be multiplied with this object.
+ * @param u The {@code Unit} of the specified value.
+ * @return A new {@code Measurement} object that is the product of this
+ * object multiplied by the specified value. The error and unit of
+ * the new object are computed. The time of the new object is set to
+ * the time of this object.
+ * @throws ArithmeticException If the units of this object and the specified
+ * value cannot be multiplied.
+ * @see Unit
+ */
+ public Measurement mul(double d, Unit u) {
+ return new Measurement(value * d, error * Math.abs(d), unit.mul(u), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the product of this
+ * object multiplied by the specified value.
+ *
+ * @param d The value that will be multiplied with this object.
+ * @return A new {@code Measurement} object that is the product of this
+ * object multiplied by the specified value. The error of the new
+ * object is computed. The unit and time of the new object is set to
+ * the unit and time of this object.
+ */
+ public Measurement mul(double d) {
+ return new Measurement(value * d, error * Math.abs(d), unit, time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the quotient of this
+ * object divided by the specified object.
+ *
+ * @param m The {@code Measurement} object that will be the divisor of this
+ * object.
+ * @return A new {@code Measurement} object that is the quotient of this
+ * object divided by the specified object. The error and unit of the
+ * new object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified object cannot be divided.
+ * @see Unit
+ */
+ public Measurement div(Measurement m) {
+ double mvalue = m.value;
+ return new Measurement(value / mvalue, (Math.abs(value) * m.error + error * Math.abs(mvalue)) / (mvalue * mvalue), unit.div(m.unit), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the quotient of this
+ * object divided by the specified value.
+ *
+ * @param d The value that will be the divisor of this object.
+ * @param u The {@code Unit} object of the specified value.
+ * @return A new {@code Measurement} that is the quotient of this object
+ * divided by the specified value. The error and unit of the new
+ * object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified object cannot be divided.
+ * @see Unit
+ */
+ public Measurement div(double d, Unit u) {
+ return new Measurement(value / d, error / Math.abs(d), unit.div(u), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the quotient of this
+ * object divided by the specified value.
+ *
+ * @param d The value that will be the divisor of this object.
+ * @return A new {@code Measurement} object that is the quotient of this
+ * object divided by the specified value. The error of the new
+ * object is computed. The unit and time of the new object is set to
+ * the {@code Unit} and time of this object.
+ */
+ public Measurement div(double d) {
+ return new Measurement(value / d, error / Math.abs(d), unit, time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the sum of this object
+ * added to the specified object.
+ *
+ * The error and unit of the new object are computed. The time of the new
+ * object is set to the time of this object.
+ *
+ * @param m The {@code Measurement} object that will be added with this
+ * object.
+ * @return A new {@code Measurement} object that is the sum of this and m.
+ * @see Unit
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified object cannot be added.
+ */
+ public Measurement add(Measurement m) {
+ return new Measurement(value + m.value, error + m.error, unit.add(m.unit), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the sum of this object
+ * added to the specified value.
+ *
+ * @param d The value that will be added with this object.
+ * @param u The {@code Unit} object of the specified value.
+ * @return A new {@code Measurement} object that is the sum of this object
+ * added to the specified value. The unit of the new object is
+ * computed. The error and time of the new object is set to the
+ * error and time of this object.
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified value cannot be added.
+ * @see Unit
+ */
+ public Measurement add(double d, Unit u) {
+ return new Measurement(value + d, error, unit.add(u), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the sum of this object
+ * added to the specified value.
+ *
+ * @param d The value that will be added with this object.
+ * @return A new {@code Measurement} object that is the sum of this object
+ * added to the specified value. The error, unit, and time of the
+ * new object is set to the error, {@code Unit} and time of this
+ * object.
+ */
+ public Measurement add(double d) {
+ return new Measurement(value + d, error, unit, time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the subtraction of the
+ * specified object from this object.
+ *
+ * @param m The {@code Measurement} object that will be subtracted from this
+ * object.
+ * @return A new {@code Measurement} object that is the subtraction of the
+ * specified object from this object. The error and unit of the new
+ * object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified object cannot be subtracted.
+ * @see Unit
+ */
+ public Measurement sub(Measurement m) {
+ return new Measurement(value - m.value, error + m.error, unit.sub(m.unit), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the subtraction of the
+ * specified value from this object.
+ *
+ * @param d The value that will be subtracted from this object.
+ * @param u The {@code Unit} object of the specified value.
+ * @return A new {@code Measurement} object that is the subtraction of the
+ * specified value from this object. The unit of the new object is
+ * computed. The error and time of the new object is set to the
+ * error and time of this object.
+ * @throws ArithmeticException If the {@code Unit} objects of this object
+ * and the specified object cannot be subtracted.
+ * @see Unit
+ */
+ public Measurement sub(double d, Unit u) {
+ return new Measurement(value - d, error, unit.sub(u), time);
+ }
+
+ /**
+ * Returns a new {@code Measurement} object that is the subtraction of the
+ * specified value from this object.
+ *
+ * @param d The value that will be subtracted from this object.
+ * @return A new {@code Measurement} object that is the subtraction of the
+ * specified value from this object. The error, unit and time of the
+ * new object is set to the error, {@code Unit} object and time of
+ * this object.
+ */
+ public Measurement sub(double d) {
+ return new Measurement(value - d, error, unit, time);
+ }
+
+ /**
+ * Returns a {@code String} object representing this {@code Measurement}
+ * object.
+ *
+ * @return a {@code String} object representing this {@code Measurement}
+ * object.
+ */
+ public String toString() {
+ String result = name;
+ if (result == null) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(value);
+ if (error != 0.0d) {
+ sb.append(" +/- ");
+ sb.append(error);
+ }
+ String u = unit.toString();
+ if (u.length() > 0) {
+ sb.append(" ");
+ sb.append(u);
+ }
+ result = sb.toString();
+ name = result;
+ }
+ return result;
+ }
+
+ /**
+ * Compares this object with the specified object for order. Returns a
+ * negative integer, zero, or a positive integer if this object is less
+ * than, equal to, or greater than the specified object.
+ *
+ * <p>
+ * Note: This class has a natural ordering that is inconsistent with equals.
+ * For this method, another {@code Measurement} object is considered equal
+ * if there is some {@code x} such that
+ *
+ * <pre>
+ * getValue() - getError() &lt;= x &lt;= getValue() + getError()
+ * </pre>
+ *
+ * for both {@code Measurement} objects being compared.
+ *
+ * @param obj The object to be compared.
+ * @return A negative integer, zero, or a positive integer if this object is
+ * less than, equal to, or greater than the specified object.
+ *
+ * @throws ClassCastException If the specified object is not of type
+ * {@code Measurement}.
+ * @throws ArithmeticException If the unit of the specified
+ * {@code Measurement} object is not equal to the {@code Unit}
+ * object of this object.
+ */
+ public int compareTo(Object obj) {
+ if (this == obj) {
+ return 0;
+ }
+ Measurement that = (Measurement) obj;
+ if (!unit.equals(that.unit)) {
+ throw new ArithmeticException("Cannot compare " + this + " and " + that);
+ }
+ int result = Double.compare(value, that.value);
+ if (result == 0) {
+ return 0;
+ }
+ if (result < 0) {
+ if (Double.compare(value + error, that.value - that.error) >= 0) {
+ return 0;
+ }
+ return -1;
+ }
+ if (Double.compare(value - error, that.value + that.error) <= 0) {
+ return 0;
+ }
+ return 1;
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ public int hashCode() {
+ int h = hashCode;
+ if (h == 0) {
+ long bits = Double.doubleToLongBits(value);
+ h = 31 * 17 + ((int) (bits ^ (bits >>> 32)));
+ bits = Double.doubleToLongBits(error);
+ h = 31 * h + ((int) (bits ^ (bits >>> 32)));
+ h = 31 * h + unit.hashCode();
+ hashCode = h;
+ }
+ return h;
+ }
+
+ /**
+ * Returns whether the specified object is equal to this object. Two
+ * {@code Measurement} objects are equal if they have same value, error and
+ * {@code Unit}.
+ *
+ * <p>
+ * Note: This class has a natural ordering that is inconsistent with equals.
+ * See {@link #compareTo(Object)}.
+ *
+ * @param obj The object to compare with this object.
+ * @return {@code true} if this object is equal to the specified object;
+ * {@code false} otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Measurement)) {
+ return false;
+ }
+ Measurement that = (Measurement) obj;
+ return (Double.compare(value, that.value) == 0) && (Double.compare(error, that.error) == 0) && unit.equals(that.unit);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/State.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/State.java
new file mode 100644
index 000000000..415613f39
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/State.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.util.measurement;
+
+/**
+ * Groups a state name, value and timestamp.
+ *
+ * <p>
+ * The state itself is represented as an integer and the time is measured in
+ * milliseconds since midnight, January 1, 1970 UTC.
+ *
+ * <p>
+ * A {@code State} object is immutable so that it may be easily shared.
+ *
+ * @Immutable
+ * @author $Id$
+ */
+public class State {
+ private final int value;
+ private final long time;
+ private final String name;
+
+ /**
+ * Create a new {@code State} object.
+ *
+ * @param value The value of the state.
+ * @param name The name of the state.
+ * @param time The time measured in milliseconds since midnight, January 1,
+ * 1970 UTC.
+ */
+ public State(int value, String name, long time) {
+ this.value = value;
+ this.name = name;
+ this.time = time;
+ }
+
+ /**
+ * Create a new {@code State} object with a time of 0.
+ *
+ * @param value The value of the state.
+ * @param name The name of the state.
+ */
+ public State(int value, String name) {
+ this(value, name, 0);
+ }
+
+ /**
+ * Returns the value of this {@code State}.
+ *
+ * @return The value of this {@code State} object.
+ */
+ public final int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the time with which this {@code State} was created.
+ *
+ * @return The time with which this {@code State} was created. The time is
+ * measured in milliseconds since midnight, January 1, 1970 UTC.
+ */
+ public final long getTime() {
+ return time;
+ }
+
+ /**
+ * Returns the name of this {@code State}.
+ *
+ * @return The name of this {@code State} object.
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Returns a {@code String} object representing this object.
+ *
+ * @return a {@code String} object representing this object.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(value);
+ if (name != null) {
+ sb.append(" \"");
+ sb.append(name);
+ sb.append("\"");
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ public int hashCode() {
+ int hash = 31 * 17 + value;
+ if (name != null) {
+ hash = 31 * hash + name.hashCode();
+ }
+ return hash;
+ }
+
+ /**
+ * Return whether the specified object is equal to this object. Two
+ * {@code State} objects are equal if they have same value and name.
+ *
+ * @param obj The object to compare with this object.
+ * @return {@code true} if this object is equal to the specified object;
+ * {@code false} otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof State)) {
+ return false;
+ }
+ State that = (State) obj;
+ if (value != that.value) {
+ return false;
+ }
+ if (name == that.name) {
+ return true;
+ }
+ if (name == null) {
+ return false;
+ }
+ return name.equals(that.name);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Unit.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Unit.java
new file mode 100644
index 000000000..e97563d26
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/Unit.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.util.measurement;
+
+import java.util.Hashtable;
+
+/**
+ * A unit system for measurements.
+ *
+ * This class contains definitions of the most common SI units.
+ * <p>
+ *
+ * <p>
+ * This class only support exponents for the base SI units in the range -64 to
+ * +63. Any operation which produces an exponent outside of this range will
+ * result in a {@code Unit} object with undefined exponents.
+ *
+ * @Immutable
+ * @author $Id$
+ */
+/*
+ * This local class maintains the information about units. It can calculate new
+ * units when two values are multiplied, divided, added or subtracted. <p> The
+ * unit works with the 7 basic SI types + rad + up to 2^6 custom types. For each
+ * type, the unit keeps a bit mask with the exponents of the basic types. Eg.
+ * m/s is m = 1, s = -1. Multiplying one unit with another means that the bit
+ * masks are added, dividing means that the bit masks are subtracted. <p> This
+ * class can handle any reasonable combination of SI units. However, it will
+ * always try to coerce results back into the basic set. E.g. when you do V*A
+ * you should get W and not m2.kg/s3 . Only when the existing types do not match
+ * does the unit fallback to the expanded form. <p> This class uses offset
+ * arithmetic. This means that the exponents are stored in an long. The special
+ * field is used for units that should not be arithmetically divided or
+ * multiplied, like longitude and lattitude. These special units can however, be
+ * divided and multiplied by the basic 7 constants of the SI, e.g. deg/s.
+ */
+public class Unit {
+ private final static long UNITY = createType(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ private final static long ZERO = 0x40L;
+ private final static long MASK = 0x7fL;
+ private final static int m_SHIFT = 0;
+ private final static int s_SHIFT = 7;
+ private final static int kg_SHIFT = 14;
+ private final static int K_SHIFT = 21;
+ private final static int A_SHIFT = 28;
+ private final static int mol_SHIFT = 35;
+ private final static int cd_SHIFT = 42;
+ private final static int rad_SHIFT = 49;
+ private final static int x_SHIFT = 56;
+ private final static long x_MASK = MASK << x_SHIFT;
+ /** No Unit (Unity) */
+ public final static Unit unity = new Unit("", UNITY); // Unity
+ /* SI Base Units */
+ /** The length unit meter (m) */
+ public final static Unit m = new Unit("m", createType(0, 0, 0, 0, 0, 0, 0, 0, 1)); // Distance
+ // meter
+ /** The time unit second (s) */
+ public final static Unit s = new Unit("s", createType(0, 0, 0, 0, 0, 0, 0, 1, 0)); // Time
+ // Seconds
+ // s
+ /** The mass unit kilogram (kg) */
+ public final static Unit kg = new Unit("kg", createType(0, 0, 0, 0, 0, 0, 1, 0, 0)); // Mass
+ // kilogram
+ // kg
+ /** The temperature unit kelvin (K) */
+ public final static Unit K = new Unit("K", createType(0, 0, 0, 0, 0, 1, 0, 0, 0)); // Temperature
+ // kelvin
+ // K
+ /** The electric current unit ampere (A) */
+ public final static Unit A = new Unit("A", createType(0, 0, 0, 0, 1, 0, 0, 0, 0)); // Current
+ // ampere
+ // A
+ /** The amount of substance unit mole (mol) */
+ public final static Unit mol = new Unit("mol", createType(0, 0, 0, 1, 0, 0, 0, 0, 0)); // Substance
+ // mole
+ // mol
+ /** The luminous intensity unit candela (cd) */
+ public final static Unit cd = new Unit("cd", createType(0, 0, 1, 0, 0, 0, 0, 0, 0)); // Light
+ // candela
+ // cd
+ /* SI Derived Units */
+ /** The speed unit meter per second (m/s) */
+ public final static Unit m_s = new Unit("m/s", createType(0, 0, 0, 0, 0, 0, 0, -1, 1)); // Speed
+ // m/s
+ /** The acceleration unit meter per second squared (m/s<sup>2</sup>) */
+ public final static Unit m_s2 = new Unit("m/s2", createType(0, 0, 0, 0, 0, 0, 0, -2, 1)); // Acceleration
+ // m/s^2
+ /** The area unit square meter (m<sup>2</sup>) */
+ public final static Unit m2 = new Unit("m2", createType(0, 0, 0, 0, 0, 0, 0, 0, 2)); // Surface
+ // m^2
+ /** The volume unit cubic meter (m<sup>3</sup>) */
+ public final static Unit m3 = new Unit("m3", createType(0, 0, 0, 0, 0, 0, 0, 0, 3)); // Volume
+ // m^3
+ /**
+ * The frequency unit hertz (Hz).
+ * <p>
+ * hertz is expressed in SI units as 1/s
+ */
+ public final static Unit Hz = new Unit("Hz", createType(0, 0, 0, 0, 0, 0, 0, -1, 0)); // Frequency
+ // 1/s
+ /**
+ * The force unit newton (N).
+ * <p>
+ * N is expressed in SI units as m&#183;kg/s<sup>2</sup>
+ */
+ public final static Unit N = new Unit("N", createType(0, 0, 0, 0, 0, 0, 1, -2, 1)); // Force
+ // newton
+ // (m*kg)/s^2
+ /**
+ * The pressure unit pascal (Pa).
+ * <p>
+ * Pa is equal to N/m<sup>2</sup> or is expressed in SI units as
+ * kg/m&#183;s<sup>2</sup>
+ */
+ public final static Unit Pa = new Unit("Pa", createType(0, 0, 0, 0, 0, 0, 1, -2, -1)); // Pressure
+ // pascal
+ // kg/(m*s^2)
+ /**
+ * The energy unit joule (J).
+ * <p>
+ * joule is equal to N&#183;m or is expressed in SI units as
+ * m<sup>2</sup>&#183;kg/s<sup>2</sup>
+ */
+ public final static Unit J = new Unit("J", createType(0, 0, 0, 0, 0, 0, 1, -2, 2)); // Energy
+ // joule
+ // (m^2*kg)/s^2
+ /**
+ * The power unit watt (W).
+ * <p>
+ * watt is equal to J/s or is expressed in SI units as
+ * m<sup>2</sup>&#183;kg/s<sup>3</sup>
+ */
+ public final static Unit W = new Unit("W", createType(0, 0, 0, 0, 0, 0, 1, -3, 2)); // Power
+ // watt
+ // (m^2*kg)/s^3
+ /**
+ * The electric charge unit coulomb (C).
+ * <p>
+ * coulomb is expressed in SI units as s&#183;A
+ */
+ public final static Unit C = new Unit("C", createType(0, 0, 0, 0, 1, 0, 0, 1, 0)); // Charge
+ // coulumb
+ // s*A
+ /**
+ * The electric potential difference unit volt (V).
+ * <p>
+ * volt is equal to W/A or is expressed in SI units as
+ * m<sup>2</sup>&#183;kg/s<sup>3</sup>&#183;A
+ */
+ public final static Unit V = new Unit("V", createType(0, 0, 0, 0, -1, 0, 1, -3, 2)); // El.
+ // Potent.
+ // volt
+ // (m^2*kg)/(s^3*A)
+ /**
+ * The capacitance unit farad (F).
+ * <p>
+ * farad is equal to C/V or is expressed in SI units as
+ * s<sup>4</sup>&#183;A<sup>2</sup>/m<sup>2</sup>&#183;kg
+ */
+ public final static Unit F = new Unit("F", createType(0, 0, 0, 0, 2, 0, -1, 4, -2)); // Capacitance
+ // farad
+ // (s^4*A^2)/(m^2*kg)
+ /**
+ * The electric resistance unit ohm.
+ * <p>
+ * ohm is equal to V/A or is expressed in SI units as
+ * m<sup>2</sup>&#183;kg/s<sup>3</sup>&#183;A<sup>2</sup>
+ */
+ public final static Unit Ohm = new Unit("Ohm", createType(0, 0, 0, 0, -2, 0, 1, -3, 2)); // Resistance
+ // ohm
+ // (m^2*kg)/(s^3*A^2)
+ /**
+ * The electric conductance unit siemens (S).
+ * <p>
+ * siemens is equal to A/V or is expressed in SI units as
+ * s<sup>3</sup>&#183;A<sup>2</sup>/m<sup>2</sup>&#183;kg
+ */
+ public final static Unit S = new Unit("S", createType(0, 0, 0, 0, 2, 0, -1, 3, -2)); // Conductance
+ // siemens
+ // (s^3*A^2)/(m^2*kg)
+ /**
+ * The magnetic flux unit weber (Wb).
+ * <p>
+ * weber is equal to V&#183;s or is expressed in SI units as
+ * m<sup>2</sup>&#183;kg/s<sup>2</sup>&#183;A
+ */
+ public final static Unit Wb = new Unit("Wb", createType(0, 0, 0, 0, -1, 0, 1, -2, 2)); // Magn.
+ // Flux
+ // weber
+ // (m^2*kg)/(s^2*A)
+ /**
+ * The magnetic flux density unit tesla (T).
+ * <p>
+ * tesla is equal to Wb/m<sup>2</sup> or is expressed in SI units as
+ * kg/s<sup>2</sup>&#183;A
+ */
+ public final static Unit T = new Unit("T", createType(0, 0, 0, 0, -1, 0, 1, -2, 0)); // Magn.
+ // Flux
+ // Dens.
+ // tesla
+ // kg/(s^2*A)
+ /**
+ * The illuminance unit lux (lx).
+ * <p>
+ * lux is expressed in SI units as cd/m<sup>2</sup>
+ */
+ public final static Unit lx = new Unit("lx", createType(0, 0, 1, 0, 0, 0, 0, 0, -2)); // Illuminace
+ // lux
+ // cd/m^2
+ /**
+ * The absorbed dose unit gray (Gy).
+ * <p>
+ * Gy is equal to J/kg or is expressed in SI units as
+ * m<sup>2</sup>/s<sup>2</sup>
+ */
+ public final static Unit Gy = new Unit("Gy", createType(0, 0, 0, 0, 0, 0, 0, -2, 2)); // Absorbed
+ // dose
+ // gray
+ // m^2/s^2
+ /**
+ * The catalytic activity unit katal (kat).
+ * <p>
+ * katal is expressed in SI units as mol/s
+ */
+ public final static Unit kat = new Unit("kat", createType(0, 0, 0, 1, 0, 0, 0, -1, 0)); // Catalytic
+ // Act.
+ // katal
+ // mol/s
+ /** The angle unit radians (rad) */
+ public final static Unit rad = new Unit("rad", createType(0, 1, 0, 0, 0, 0, 0, 0, 0)); // Angle
+ // radians
+ // rad
+ /**
+ * An array containing all units defined. The first seven items must be m,
+ * s, kg, K, A, mol, cd, rad in this order!
+ */
+ private final static Unit[] allUnits = new Unit[] {m, s, kg, K, A, mol, cd, rad, m_s, m_s2, m2, m3, Hz, N, Pa, J, W, C, V, F, Ohm, S, Wb, T, lx, Gy, kat, unity};
+
+ /* @GuardedBy("this") */
+ private static Hashtable base;
+ private final String name;
+ private final long type;
+
+ /**
+ * Creates a new {@code Unit} instance.
+ *
+ * @param name the name of the {@code Unit}
+ * @param type the type of the {@code Unit}
+ */
+ private Unit(String name, long type) {
+ if (name == null) {
+ name = computeName(type);
+ }
+ this.name = name;
+ this.type = type;
+ // System.out.println( name + " " + Long.toHexString( type ) );
+ }
+
+ /**
+ * Create a type field from the base SI unit exponent values.
+ *
+ */
+ private static long createType(int _x, int _rad, int _cd, int _mol, int _A, int _K, int _kg, int _s, int _m) {
+ return (((ZERO + _m) & MASK) << m_SHIFT) | (((ZERO + _s) & MASK) << s_SHIFT) | (((ZERO + _kg) & MASK) << kg_SHIFT) | (((ZERO + _K) & MASK) << K_SHIFT) | (((ZERO + _A) & MASK) << A_SHIFT)
+ | (((ZERO + _mol) & MASK) << mol_SHIFT) | (((ZERO + _cd) & MASK) << cd_SHIFT) | (((ZERO + _rad) & MASK) << rad_SHIFT) | (((long) _x) << x_SHIFT);
+ }
+
+ /**
+ * Checks whether this {@code Unit} object is equal to the specified
+ * {@code Unit} object. The {@code Unit} objects are considered equal if
+ * their exponents are equal.
+ *
+ * @param obj the {@code Unit} object that should be checked for equality
+ *
+ * @return true if the specified {@code Unit} object is equal to this
+ * {@code Unit} object.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Unit)) {
+ return false;
+ }
+ return ((Unit) obj).type == type;
+ }
+
+ /**
+ * Returns the hash code for this object.
+ *
+ * @return This object's hash code.
+ */
+ public int hashCode() {
+ return 31 * 17 + (int) (type ^ (type >>> 32));
+ }
+
+ /**
+ * Returns a new {@code Unit} that is the multiplication of this
+ * {@code Unit} and the {@code Unit} specified
+ *
+ * @param that the {@code Unit} that will be multiplied with this
+ * {@code Unit}
+ *
+ * @return a new {@code Unit} that is the multiplication of this
+ * {@code Unit} and the {@code Unit} specified
+ *
+ * @throws RuntimeException if both {@code Unit} s are special
+ *
+ * @see Unit#isSpecial()
+ */
+ Unit mul(Unit that) {
+ if (this.isSpecial() && that.isSpecial()) {
+ throw new ArithmeticException("Cannot multiply " + this + " with " + that);
+ }
+ return find(this.type - UNITY + that.type);
+ }
+
+ /**
+ * Returns a new {@code Unit} that is the division of this {@code Unit} and
+ * the {@code Unit} specified
+ *
+ * @param that the {@code Unit} that this {@code Unit} will be divided with
+ * @return a new {@code Unit} that is the division of this {@code Unit} and
+ * the {@code Unit} specified
+ *
+ * @throws RuntimeException if both {@code Unit} s are special
+ *
+ * @see Unit#isSpecial()
+ */
+ Unit div(Unit that) {
+ if (this.isSpecial() && that.isSpecial()) {
+ if (this.type == that.type) {
+ return Unit.unity;
+ }
+ throw new ArithmeticException("Cannot divide " + this + " by " + that);
+ }
+ return find(this.type - that.type + UNITY);
+ }
+
+ /**
+ * Returns a new {@code Unit} that is the addition of this {@code Unit} and
+ * the {@code Unit} specified.
+ *
+ * @param that the {@code Unit} that should be added to this {@code Unit}
+ *
+ * @return a new {@code Unit} that is the addition of this {@code Unit} and
+ * the {@code Unit} specified.
+ *
+ * @throws RuntimeException if the two {@code Unit} s are not the same
+ */
+ Unit add(Unit that) {
+ if (!this.equals(that)) {
+ throw new ArithmeticException("Cannot add " + this + " to " + that);
+ }
+ return this;
+ }
+
+ /**
+ * Returns a new {@code Unit} that is the subtraction between this
+ * {@code Unit} and the {@code Unit} specified.
+ *
+ * @param that the {@code Unit} that will be subtracted from this
+ * {@code Unit}
+ * @return a new {@code Unit} that is the subtraction between this
+ * {@code Unit} and the {@code Unit} specified.
+ *
+ * @throws RuntimeException if the {@code Unit} specified is not the same as
+ * this {@code Unit}
+ */
+ Unit sub(Unit that) {
+ if (!this.equals(that)) {
+ throw new ArithmeticException("Cannot subtract " + that + " from " + this);
+ }
+ return this;
+ }
+
+ /**
+ * Finds a {@code Unit} based on a type. If the {@code Unit} is not found,
+ * it will be created and added to the list of all units under a null name.
+ *
+ * @param type the type of the {@code Unit} to find
+ *
+ * @return the {@code Unit}
+ */
+ static synchronized Unit find(long type) {
+ if (base == null) {
+ int size = allUnits.length;
+ base = new Hashtable(size << 1);
+ for (int i = 0; i < size; i++) {
+ base.put(allUnits[i], allUnits[i]);
+ }
+ }
+ Unit unit = new Unit(null, type);
+ Unit out = (Unit) base.get(unit);
+ if (out == null) {
+ base.put(unit, unit);
+ out = unit;
+ }
+ return out;
+ }
+
+ /**
+ * Returns a {@code String} object representing the {@code Unit}
+ *
+ * @return A {@code String} object representing the {@code Unit}
+ */
+ public String toString() {
+ return name;
+ }
+
+ private static String computeName(long type) {
+ int _m = (int) (((type >> m_SHIFT) & MASK) - ZERO);
+ int _s = (int) (((type >> s_SHIFT) & MASK) - ZERO);
+ int _kg = (int) (((type >> kg_SHIFT) & MASK) - ZERO);
+ int _K = (int) (((type >> K_SHIFT) & MASK) - ZERO);
+ int _A = (int) (((type >> A_SHIFT) & MASK) - ZERO);
+ int _mol = (int) (((type >> mol_SHIFT) & MASK) - ZERO);
+ int _cd = (int) (((type >> cd_SHIFT) & MASK) - ZERO);
+ int _rad = (int) (((type >> rad_SHIFT) & MASK) - ZERO);
+ StringBuffer numerator = new StringBuffer();
+ StringBuffer denominator = new StringBuffer();
+ addSIname(_m, "m", numerator, denominator);
+ addSIname(_s, "s", numerator, denominator);
+ addSIname(_kg, "kg", numerator, denominator);
+ addSIname(_K, "K", numerator, denominator);
+ addSIname(_A, "A", numerator, denominator);
+ addSIname(_mol, "mol", numerator, denominator);
+ addSIname(_cd, "cd", numerator, denominator);
+ addSIname(_rad, "rad", numerator, denominator);
+ if (denominator.length() > 0) {
+ if (numerator.length() == 0) {
+ numerator.append("1");
+ }
+ numerator.append("/");
+ numerator.append(denominator.toString());
+ }
+ return numerator.toString();
+ }
+
+ private static void addSIname(int si, String name, StringBuffer numerator, StringBuffer denominator) {
+ if (si != 0) {
+ StringBuffer sb = (si > 0) ? numerator : denominator;
+ if (sb.length() > 0) {
+ sb.append("*");
+ }
+ sb.append(name);
+ int power = Math.abs(si);
+ if (power > 1) {
+ sb.append("^");
+ sb.append(power);
+ }
+ }
+ }
+
+ /**
+ * Checks whether the unit has a special type, i.e. not a SI unit.
+ *
+ * @return true if the type is special, otherwise false.
+ */
+ private boolean isSpecial() {
+ return (type & x_MASK) != 0;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/package-info.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/package-info.java
new file mode 100644
index 000000000..7603bac0b
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Measurement 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.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.measurement; version="[1.0,2.0)"}
+ *
+ * @version 1.0.1
+ * @author $Id$
+ */
+
+package org.osgi.util.measurement;
+
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/packageinfo b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/packageinfo
new file mode 100644
index 000000000..c2664475c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/measurement/packageinfo
@@ -0,0 +1 @@
+version 1.0.1 \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/Position.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/Position.java
new file mode 100644
index 000000000..0e637b36c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/Position.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.util.position;
+
+import org.osgi.util.measurement.Measurement;
+import org.osgi.util.measurement.Unit;
+
+/**
+ * Position represents a geographic location, based on the WGS84 System (World
+ * Geodetic System 1984).
+ * <p>
+ * The {@code org.osgi.util.measurement.Measurement} class is used to represent
+ * the values that make up a position.
+ * <p>
+ * <p>
+ * A given position object may lack any of it's components, i.e. the altitude
+ * may not be known. Such missing values will be represented by null.
+ * <p>
+ * Position does not override the implementation of either equals() or
+ * hashCode() because it is not clear how missing values should be handled. It
+ * is up to the user of a position to determine how best to compare two position
+ * objects. A {@code Position} object is immutable.
+ *
+ * @Immutable
+ * @author $Id$
+ */
+public class Position {
+ private final Measurement altitude;
+ private final Measurement longitude;
+ private final Measurement latitude;
+ private final Measurement speed;
+ private final Measurement track;
+
+ /**
+ * Constructs a {@code Position} object with the given values.
+ *
+ * @param lat a {@code Measurement} object specifying the latitude in
+ * radians, or null
+ * @param lon a {@code Measurement} object specifying the longitude in
+ * radians, or null
+ * @param alt a {@code Measurement} object specifying the altitude in
+ * meters, or null
+ * @param speed a {@code Measurement} object specifying the speed in meters
+ * per second, or null
+ * @param track a {@code Measurement} object specifying the track in
+ * radians, or null
+ */
+ public Position(Measurement lat, Measurement lon, Measurement alt, Measurement speed, Measurement track) {
+ if (lat != null) {
+ if (!Unit.rad.equals(lat.getUnit())) {
+ throw new IllegalArgumentException("Invalid Latitude");
+ }
+ }
+ if (lon != null) {
+ if (!Unit.rad.equals(lon.getUnit())) {
+ throw new IllegalArgumentException("Invalid Longitude");
+ }
+ }
+ if (alt != null) {
+ if (!Unit.m.equals(alt.getUnit())) {
+ throw new IllegalArgumentException("Invalid Altitude");
+ }
+ }
+ if (speed != null) {
+ if (!Unit.m_s.equals(speed.getUnit())) {
+ throw new IllegalArgumentException("Invalid Speed");
+ }
+ }
+ if (track != null) {
+ if (!Unit.rad.equals(track.getUnit())) {
+ throw new IllegalArgumentException("Invalid Track");
+ }
+ }
+
+ /*
+ * Verify the longitude and latitude parameters so they fit the normal
+ * coordinate system. A latitude is between -90 (south) and +90 (north).
+ * A longitude is between -180 (Western hemisphere) and +180 (eastern
+ * hemisphere). This method first normalizes the latitude and longitude
+ * between +/- 180. If the |latitude| > 90, then the longitude is added
+ * 180 and the latitude is normalized to fit +/-90. (Example are with
+ * degrees though radians are used.) No normalization takes place when
+ * either lon or lat is null.
+ */
+ normalizeLatLon: {
+ if (lat == null || lon == null) {
+ break normalizeLatLon;
+ }
+ double dlat = lat.getValue();
+ double dlon = lon.getValue();
+ if (dlon >= -LON_RANGE && dlon < LON_RANGE && dlat >= -LAT_RANGE && dlat <= LAT_RANGE) {
+ break normalizeLatLon;
+ }
+ dlon = normalize(dlon, LON_RANGE);
+ dlat = normalize(dlat, LAT_RANGE * 2.0D); // First over 180 degree
+ // Check if we have to move to other side of the earth
+ if (dlat > LAT_RANGE || dlat < -LAT_RANGE) {
+ dlon = normalize(dlon - LON_RANGE, LON_RANGE);
+ dlat = normalize((LAT_RANGE * 2.0D) - dlat, LAT_RANGE);
+ }
+ lon = new Measurement(dlon, lon.getError(), lon.getUnit(), lon.getTime());
+ lat = new Measurement(dlat, lat.getError(), lat.getUnit(), lat.getTime());
+ }
+
+ /*
+ * Normalize track to be a value such that: 0 <= value < +2PI. This
+ * corresponds to 0 deg to +360 deg. 0 is North, 0.5PI is East, PI is
+ * South, 1.5PI is West
+ */
+ normalizeTrack: {
+ if (track == null) {
+ break normalizeTrack;
+ }
+ double dtrack = track.getValue();
+ if ((0.0D <= dtrack) && (dtrack < TRACK_RANGE)) {
+ break normalizeTrack; /* value is already normalized */
+ }
+ dtrack %= TRACK_RANGE;
+ if (dtrack < 0.0D) {
+ dtrack += TRACK_RANGE;
+ }
+ track = new Measurement(dtrack, track.getError(), track.getUnit(), track.getTime());
+ }
+
+ this.latitude = lat;
+ this.longitude = lon;
+ this.altitude = alt;
+ this.speed = speed;
+ this.track = track;
+ }
+
+ /**
+ * Returns the altitude of this position in meters.
+ *
+ * @return a {@code Measurement} object in {@code Unit.m} representing the
+ * altitude in meters above the ellipsoid {@code null} if the
+ * altitude is not known.
+ */
+ public Measurement getAltitude() {
+ return altitude;
+ }
+
+ /**
+ * Returns the longitude of this position in radians.
+ *
+ * @return a {@code Measurement} object in {@code Unit.rad} representing the
+ * longitude, or {@code null} if the longitude is not known.
+ */
+ public Measurement getLongitude() {
+ return longitude;
+ }
+
+ /**
+ * Returns the latitude of this position in radians.
+ *
+ * @return a {@code Measurement} object in {@code Unit.rad} representing the
+ * latitude, or {@code null} if the latitude is not known..
+ */
+ public Measurement getLatitude() {
+ return latitude;
+ }
+
+ /**
+ * Returns the ground speed of this position in meters per second.
+ *
+ * @return a {@code Measurement} object in {@code Unit.m_s} representing the
+ * speed, or {@code null} if the speed is not known..
+ */
+ public Measurement getSpeed() {
+ return speed;
+ }
+
+ /**
+ * Returns the track of this position in radians as a compass heading. The
+ * track is the extrapolation of previous previously measured positions to a
+ * future position.
+ *
+ * @return a {@code Measurement} object in {@code Unit.rad} representing the
+ * track, or {@code null} if the track is not known..
+ */
+ public Measurement getTrack() {
+ return track;
+ }
+
+ private static final double LON_RANGE = Math.PI;
+ private static final double LAT_RANGE = Math.PI / 2.0D;
+
+ /**
+ * This function normalizes the a value according to a range. This is not
+ * simple modulo (as I thought when I started), but requires some special
+ * handling. For positive numbers we subtract 2*range from the number so
+ * that end up between -/+ range. For negative numbers we add this value.
+ * For example, if the value is 270 and the range is +/- 180. Then sign=1 so
+ * the (int) factor becomes 270+180/360 = 1. This means that 270-360=-90 is
+ * the result. (degrees are only used to make it easier to understand, this
+ * function is agnostic for radians/degrees). The result will be in
+ * [range,range&gt; The algorithm is not very fast, but it handling the
+ * [&gt; ranges made it very messy using integer arithmetic, and this is
+ * very readable. Note that it is highly unlikely that this method is called
+ * in normal situations. Normally input values to position are already
+ * normalized because they come from a GPS. And this is much more readable.
+ *
+ * @param value The value that needs adjusting
+ * @param range -range = < value < range
+ */
+ private static double normalize(double value, double range) {
+ double twiceRange = 2.0D * range;
+ while (value >= range) {
+ value -= twiceRange;
+ }
+ while (value < -range) {
+ value += twiceRange;
+ }
+ return value;
+ }
+
+ private static final double TRACK_RANGE = Math.PI * 2.0D;
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/package-info.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/package-info.java
new file mode 100644
index 000000000..63af1b6e6
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * Position 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.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.position; version="[1.0,2.0)"}
+ *
+ * @version 1.0.1
+ * @author $Id$
+ */
+
+package org.osgi.util.position;
+
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/packageinfo b/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/packageinfo
new file mode 100644
index 000000000..c2664475c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/position/packageinfo
@@ -0,0 +1 @@
+version 1.0.1 \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/XMLParserActivator.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/XMLParserActivator.java
new file mode 100644
index 000000000..c73b3c061
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/XMLParserActivator.java
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) OSGi Alliance (2002, 2013). 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.util.xml;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.SAXParserFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * A BundleActivator class that allows any JAXP compliant XML Parser to register
+ * itself as an OSGi parser service.
+ *
+ * Multiple JAXP compliant parsers can concurrently register by using this
+ * BundleActivator class. Bundles who wish to use an XML parser can then use the
+ * framework's service registry to locate available XML Parsers with the desired
+ * characteristics such as validating and namespace-aware.
+ *
+ * <p>
+ * The services that this bundle activator enables a bundle to provide are:
+ * <ul>
+ * <li>{@code javax.xml.parsers.SAXParserFactory}({@link #SAXFACTORYNAME})</li>
+ * <li>{@code javax.xml.parsers.DocumentBuilderFactory}( {@link #DOMFACTORYNAME}
+ * )</li>
+ * </ul>
+ *
+ * <p>
+ * The algorithm to find the implementations of the abstract parsers is derived
+ * from the JAR file specifications, specifically the Services API.
+ * <p>
+ * An XMLParserActivator assumes that it can find the class file names of the
+ * factory classes in the following files:
+ * <ul>
+ * <li>{@code /META-INF/services/javax.xml.parsers.SAXParserFactory} is a file
+ * contained in a jar available to the runtime which contains the implementation
+ * class name(s) of the SAXParserFactory.</li>
+ * <li>{@code /META-INF/services/javax.xml.parsers.DocumentBuilderFactory} is a
+ * file contained in a jar available to the runtime which contains the
+ * implementation class name(s) of the {@code DocumentBuilderFactory}</li>
+ * </ul>
+ * <p>
+ * If either of the files does not exist, {@code XMLParserActivator} assumes
+ * that the parser does not support that parser type.
+ *
+ * <p>
+ * {@code XMLParserActivator} attempts to instantiate both the
+ * {@code SAXParserFactory} and the {@code DocumentBuilderFactory}. It registers
+ * each factory with the framework along with service properties:
+ * <ul>
+ * <li>{@link #PARSER_VALIDATING}- indicates if this factory supports validating
+ * parsers. It's value is a {@code Boolean}.</li>
+ * <li>{@link #PARSER_NAMESPACEAWARE}- indicates if this factory supports
+ * namespace aware parsers It's value is a {@code Boolean}.</li>
+ * </ul>
+ * <p>
+ * Individual parser implementations may have additional features, properties,
+ * or attributes which could be used to select a parser with a filter. These can
+ * be added by extending this class and overriding the {@code setSAXProperties}
+ * and {@code setDOMProperties} methods.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public class XMLParserActivator implements BundleActivator, ServiceFactory {
+ /** Context of this bundle */
+ private volatile BundleContext context;
+ /**
+ * Filename containing the SAX Parser Factory Class name. Also used as the
+ * basis for the {@code SERVICE_PID} registration property.
+ */
+ public static final String SAXFACTORYNAME = "javax.xml.parsers.SAXParserFactory";
+ /**
+ * Filename containing the DOM Parser Factory Class name. Also used as the
+ * basis for the {@code SERVICE_PID} registration property.
+ */
+ public static final String DOMFACTORYNAME = "javax.xml.parsers.DocumentBuilderFactory";
+ /** Path to the factory class name files */
+ private static final String PARSERCLASSFILEPATH = "/META-INF/services/";
+ /** Fully qualified path name of SAX Parser Factory Class Name file */
+ public static final String SAXCLASSFILE = PARSERCLASSFILEPATH + SAXFACTORYNAME;
+ /** Fully qualified path name of DOM Parser Factory Class Name file */
+ public static final String DOMCLASSFILE = PARSERCLASSFILEPATH + DOMFACTORYNAME;
+ /** SAX Factory Service Description */
+ private static final String SAXFACTORYDESCRIPTION = "A JAXP Compliant SAX Parser";
+ /** DOM Factory Service Description */
+ private static final String DOMFACTORYDESCRIPTION = "A JAXP Compliant DOM Parser";
+ /**
+ * Service property specifying if factory is configured to support
+ * validating parsers. The value is of type {@code Boolean}.
+ */
+ public static final String PARSER_VALIDATING = "parser.validating";
+ /**
+ * Service property specifying if factory is configured to support namespace
+ * aware parsers. The value is of type {@code Boolean}.
+ */
+ public static final String PARSER_NAMESPACEAWARE = "parser.namespaceAware";
+ /**
+ * Key for parser factory name property - this must be saved in the parsers
+ * properties hashtable so that the parser factory can be instantiated from
+ * a ServiceReference
+ */
+ private static final String FACTORYNAMEKEY = "parser.factoryname";
+
+ /**
+ * Called when this bundle is started so the Framework can perform the
+ * bundle-specific activities necessary to start this bundle. This method
+ * can be used to register services or to allocate any resources that this
+ * bundle needs.
+ *
+ * <p>
+ * This method must complete and return to its caller in a timely manner.
+ *
+ * <p>
+ * This method attempts to register a SAX and DOM parser with the
+ * Framework's service registry.
+ *
+ * @param context The execution context of the bundle being started.
+ * @throws java.lang.Exception If this method throws an exception, this
+ * bundle is marked as stopped and the Framework will remove this
+ * bundle's listeners, unregister all services registered by this
+ * bundle, and release all services used by this bundle.
+ */
+ public void start(BundleContext context) throws Exception {
+ this.context = context;
+ Bundle parserBundle = context.getBundle();
+ // check for sax parsers
+ registerSAXParsers(getParserFactoryClassNames(parserBundle.getResource(SAXCLASSFILE)));
+ // check for dom parsers
+ registerDOMParsers(getParserFactoryClassNames(parserBundle.getResource(DOMCLASSFILE)));
+ }
+
+ /**
+ * This method has nothing to do as all active service registrations will
+ * automatically get unregistered when the bundle stops.
+ *
+ * @param context The execution context of the bundle being stopped.
+ * @throws java.lang.Exception If this method throws an exception, the
+ * bundle is still marked as stopped, and the Framework will remove
+ * the bundle's listeners, unregister all services registered by the
+ * bundle, and release all services used by the bundle.
+ */
+ public void stop(BundleContext context) throws Exception {
+ // framework will automatically unregister the parser services
+ }
+
+ /**
+ * Given the URL for a file, reads and returns the parser class names. There
+ * may be multiple classes specified in this file, one per line. There may
+ * also be comment lines in the file, which begin with "#".
+ *
+ * @param parserUrl The URL of the service file containing the parser class
+ * names
+ * @return A List of strings containing the parser class names.
+ * @throws IOException if there is a problem reading the URL input stream
+ */
+ private List getParserFactoryClassNames(URL parserUrl) throws IOException {
+ if (parserUrl == null) {
+ return Collections.EMPTY_LIST;
+ }
+ List v = new ArrayList(1);
+ String parserFactoryClassName = null;
+ InputStream is = parserUrl.openStream();
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ while (true) {
+ parserFactoryClassName = br.readLine();
+ if (parserFactoryClassName == null) {
+ break; // end of file reached
+ }
+ String pfcName = parserFactoryClassName.trim();
+ if (pfcName.length() == 0) {
+ continue; // blank line
+ }
+ int commentIdx = pfcName.indexOf("#");
+ if (commentIdx == 0) { // comment line
+ continue;
+ } else
+ if (commentIdx < 0) { // no comment on this line
+ v.add(pfcName);
+ } else {
+ v.add(pfcName.substring(0, commentIdx).trim());
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Register SAX Parser Factory Services with the framework.
+ *
+ * @param parserFactoryClassNames - a {@code List} of {@code String} objects
+ * containing the names of the parser Factory Classes
+ * @throws FactoryConfigurationError if thrown from {@code getFactory}
+ */
+ private void registerSAXParsers(List parserFactoryClassNames) throws FactoryConfigurationError {
+ Iterator e = parserFactoryClassNames.iterator();
+ int index = 0;
+ while (e.hasNext()) {
+ String parserFactoryClassName = (String) e.next();
+ // create a sax parser factory just to get it's default
+ // properties. It will never be used since
+ // this class will operate as a service factory and give each
+ // service requestor it's own SaxParserFactory
+ SAXParserFactory factory = (SAXParserFactory) getFactory(parserFactoryClassName);
+ Hashtable properties = new Hashtable(7);
+ // figure out the default properties of the parser
+ setDefaultSAXProperties(factory, properties, index);
+ // store the parser factory class name in the properties so that
+ // it can be retrieved when getService is called
+ // to return a parser factory
+ properties.put(FACTORYNAMEKEY, parserFactoryClassName);
+ // register the factory as a service
+ context.registerService(SAXFACTORYNAME, this, properties);
+ index++;
+ }
+ }
+
+ /**
+ * <p>
+ * Set the SAX Parser Service Properties. By default, the following
+ * properties are set:
+ * <ul>
+ * <li>{@code SERVICE_DESCRIPTION}</li>
+ * <li>{@code SERVICE_PID}</li>
+ * <li>{@code PARSER_VALIDATING}- instantiates a parser and queries it to
+ * find out whether it is validating or not</li>
+ * <li>{@code PARSER_NAMESPACEAWARE}- instantiates a parser and queries it
+ * to find out whether it is namespace aware or not</li>
+ * <ul>
+ *
+ * @param factory The {@code SAXParserFactory} object
+ * @param props {@code Hashtable} of service properties.
+ */
+ private void setDefaultSAXProperties(SAXParserFactory factory, Hashtable props, int index) {
+ props.put(Constants.SERVICE_DESCRIPTION, SAXFACTORYDESCRIPTION);
+ props.put(Constants.SERVICE_PID, SAXFACTORYNAME + "." + context.getBundle().getBundleId() + "." + index);
+ setSAXProperties(factory, props);
+ }
+
+ /**
+ * <p>
+ * Set the customizable SAX Parser Service Properties.
+ *
+ * <p>
+ * This method attempts to instantiate a validating parser and a namespace
+ * aware parser to determine if the parser can support those features. The
+ * appropriate properties are then set in the specified properties object.
+ *
+ * <p>
+ * This method can be overridden to add additional SAX2 features and
+ * properties. If you want to be able to filter searches of the OSGi service
+ * registry, this method must put a key, value pair into the properties
+ * object for each feature or property. For example,
+ *
+ * properties.put("http://www.acme.com/features/foo", Boolean.TRUE);
+ *
+ * @param factory - the SAXParserFactory object
+ * @param properties - the properties object for the service
+ */
+ public void setSAXProperties(SAXParserFactory factory, Hashtable properties) {
+ // check if this parser can be configured to validate
+ boolean validating = true;
+ factory.setValidating(true);
+ factory.setNamespaceAware(false);
+ try {
+ factory.newSAXParser();
+ } catch (Exception pce_val) {
+ validating = false;
+ }
+ // check if this parser can be configured to be namespaceaware
+ boolean namespaceaware = true;
+ factory.setValidating(false);
+ factory.setNamespaceAware(true);
+ try {
+ factory.newSAXParser();
+ } catch (Exception pce_nsa) {
+ namespaceaware = false;
+ }
+ // set the factory values
+ factory.setValidating(validating);
+ factory.setNamespaceAware(namespaceaware);
+ // set the OSGi service properties
+ properties.put(PARSER_NAMESPACEAWARE, new Boolean(namespaceaware));
+ properties.put(PARSER_VALIDATING, new Boolean(validating));
+ }
+
+ /**
+ * Register DOM Parser Factory Services with the framework.
+ *
+ * @param parserFactoryClassNames - a {@code List} of {@code String} objects
+ * containing the names of the parser Factory Classes
+ * @throws FactoryConfigurationError if thrown from {@code getFactory}
+ */
+ private void registerDOMParsers(List parserFactoryClassNames) throws FactoryConfigurationError {
+ Iterator e = parserFactoryClassNames.iterator();
+ int index = 0;
+ while (e.hasNext()) {
+ String parserFactoryClassName = (String) e.next();
+ // create a dom parser factory just to get it's default
+ // properties. It will never be used since
+ // this class will operate as a service factory and give each
+ // service requestor it's own DocumentBuilderFactory
+ DocumentBuilderFactory factory = (DocumentBuilderFactory) getFactory(parserFactoryClassName);
+ Hashtable properties = new Hashtable(7);
+ // figure out the default properties of the parser
+ setDefaultDOMProperties(factory, properties, index);
+ // store the parser factory class name in the properties so that
+ // it can be retrieved when getService is called
+ // to return a parser factory
+ properties.put(FACTORYNAMEKEY, parserFactoryClassName);
+ // register the factory as a service
+ context.registerService(DOMFACTORYNAME, this, properties);
+ index++;
+ }
+ }
+
+ /**
+ * Set the DOM parser service properties.
+ *
+ * By default, the following properties are set:
+ * <ul>
+ * <li>{@code SERVICE_DESCRIPTION}</li>
+ * <li>{@code SERVICE_PID}</li>
+ * <li>{@code PARSER_VALIDATING}</li>
+ * <li>{@code PARSER_NAMESPACEAWARE}</li>
+ * <ul>
+ *
+ * @param factory The {@code DocumentBuilderFactory} object
+ * @param props {@code Hashtable} of service properties.
+ */
+ private void setDefaultDOMProperties(DocumentBuilderFactory factory, Hashtable props, int index) {
+ props.put(Constants.SERVICE_DESCRIPTION, DOMFACTORYDESCRIPTION);
+ props.put(Constants.SERVICE_PID, DOMFACTORYNAME + "." + context.getBundle().getBundleId() + "." + index);
+ setDOMProperties(factory, props);
+ }
+
+ /**
+ * <p>
+ * Set the customizable DOM Parser Service Properties.
+ *
+ * <p>
+ * This method attempts to instantiate a validating parser and a namespace
+ * aware parser to determine if the parser can support those features. The
+ * appropriate properties are then set in the specified props object.
+ *
+ * <p>
+ * This method can be overridden to add additional DOM2 features and
+ * properties. If you want to be able to filter searches of the OSGi service
+ * registry, this method must put a key, value pair into the properties
+ * object for each feature or property. For example,
+ *
+ * properties.put("http://www.acme.com/features/foo", Boolean.TRUE);
+ *
+ * @param factory - the DocumentBuilderFactory object
+ * @param props - Hashtable of service properties.
+ */
+ public void setDOMProperties(DocumentBuilderFactory factory, Hashtable props) {
+ // check if this parser can be configured to validate
+ boolean validating = true;
+ factory.setValidating(true);
+ factory.setNamespaceAware(false);
+ try {
+ factory.newDocumentBuilder();
+ } catch (Exception pce_val) {
+ validating = false;
+ }
+ // check if this parser can be configured to be namespaceaware
+ boolean namespaceaware = true;
+ factory.setValidating(false);
+ factory.setNamespaceAware(true);
+ try {
+ factory.newDocumentBuilder();
+ } catch (Exception pce_nsa) {
+ namespaceaware = false;
+ }
+ // set the factory values
+ factory.setValidating(validating);
+ factory.setNamespaceAware(namespaceaware);
+ // set the OSGi service properties
+ props.put(PARSER_VALIDATING, new Boolean(validating));
+ props.put(PARSER_NAMESPACEAWARE, new Boolean(namespaceaware));
+ }
+
+ /**
+ * Given a parser factory class name, instantiate that class.
+ *
+ * @param parserFactoryClassName A {@code String} object containing the name
+ * of the parser factory class
+ * @return a parserFactoryClass Object
+ * @pre parserFactoryClassName!=null
+ */
+ private Object getFactory(String parserFactoryClassName) throws FactoryConfigurationError {
+ try {
+ return context.getBundle().loadClass(parserFactoryClassName).newInstance();
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new FactoryConfigurationError(e);
+ }
+ }
+
+ /**
+ * Creates a new XML Parser Factory object.
+ *
+ * <p>
+ * A unique XML Parser Factory object is returned for each call to this
+ * method.
+ *
+ * <p>
+ * The returned XML Parser Factory object will be configured for validating
+ * and namespace aware support as specified in the service properties of the
+ * specified ServiceRegistration object.
+ *
+ * This method can be overridden to configure additional features in the
+ * returned XML Parser Factory object.
+ *
+ * @param bundle The bundle using the service.
+ * @param registration The {@code ServiceRegistration} object for the
+ * service.
+ * @return A new, configured XML Parser Factory object or null if a
+ * configuration error was encountered
+ */
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ ServiceReference sref = registration.getReference();
+ String parserFactoryClassName = (String) sref.getProperty(FACTORYNAMEKEY);
+ // need to set factory properties
+ Object factory = getFactory(parserFactoryClassName);
+ if (factory instanceof SAXParserFactory) {
+ ((SAXParserFactory) factory).setValidating(((Boolean) sref.getProperty(PARSER_VALIDATING)).booleanValue());
+ ((SAXParserFactory) factory).setNamespaceAware(((Boolean) sref.getProperty(PARSER_NAMESPACEAWARE)).booleanValue());
+ } else {
+ if (factory instanceof DocumentBuilderFactory) {
+ ((DocumentBuilderFactory) factory).setValidating(((Boolean) sref.getProperty(PARSER_VALIDATING)).booleanValue());
+ ((DocumentBuilderFactory) factory).setNamespaceAware(((Boolean) sref.getProperty(PARSER_NAMESPACEAWARE)).booleanValue());
+ }
+ }
+ return factory;
+ }
+
+ /**
+ * Releases a XML Parser Factory object.
+ *
+ * @param bundle The bundle releasing the service.
+ * @param registration The {@code ServiceRegistration} object for the
+ * service.
+ * @param service The XML Parser Factory object returned by a previous call
+ * to the {@code getService} method.
+ */
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/package-info.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/package-info.java
new file mode 100644
index 000000000..8d3c57bb5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
+ */
+
+/**
+ * XML Parser 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.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.xml; version="[1.0,2.0)"}
+ *
+ * @version 1.0.1
+ * @author $Id$
+ */
+
+package org.osgi.util.xml;
+
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/packageinfo b/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/packageinfo
new file mode 100644
index 000000000..c2664475c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/xml/packageinfo
@@ -0,0 +1 @@
+version 1.0.1 \ No newline at end of file

Back to the top