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/org.eclipse.osgi.util
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/org.eclipse.osgi.util')
-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
23 files changed, 1931 insertions, 187 deletions
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