FELIX-4401 Temporarily add runtime spec packages to source

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1602632 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/osgi/dto/DTO.java b/scr/src/main/java/org/osgi/dto/DTO.java
new file mode 100644
index 0000000..acb9dd3
--- /dev/null
+++ b/scr/src/main/java/org/osgi/dto/DTO.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.dto;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Super type for Data Transfer Objects.
+ * 
+ * All data transfer objects are easily serializable having only public fields
+ * of primitive types and their wrapper classes, Strings, and DTOs. List, Set,
+ * Map and array aggregates may also be used. The aggregates must only hold
+ * objects of the listed types or aggregates.
+ * 
+ * @author $Id: 36dd2d0b9df1b8a6f67c74eeaad1cc9e20e19574 $
+ * @NotThreadSafe
+ */
+public abstract class DTO {
+
+    /**
+     * Return a string representation of this DTO suitable for use when
+     * debugging.
+     * 
+     * <p>
+     * The format of the string representation is not specified and subject to
+     * change.
+     * 
+     * @return A string representation of this DTO suitable for use when
+     *         debugging.
+     */
+    @Override
+    public String toString() {
+        return appendValue(new StringBuilder(), new IdentityHashMap<Object, String>(), "#", this).toString();
+    }
+
+    /**
+     * Append the specified DTO's string representation to the specified
+     * StringBuilder.
+     * 
+     * <p>
+     * This method handles circular DTO references.
+     * 
+     * @param result StringBuilder to which the string representation is
+     *        appended.
+     * @param objectRefs References to "seen" objects.
+     * @param refpath The reference path of the specified DTO.
+     * @param dto The DTO whose string representation is to be appended.
+     * @return The specified StringBuilder.
+     */
+    private static StringBuilder appendDTO(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final DTO dto) {
+        result.append("{");
+        String delim = "";
+        for (Field field : dto.getClass().getFields()) {
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+            result.append(delim);
+            final String name = field.getName();
+            appendString(result, name);
+            result.append(":");
+            Object value = null;
+            try {
+                value = field.get(dto);
+            } catch (IllegalAccessException e) {
+                // use null value;
+            }
+            appendValue(result, objectRefs, refpath + "/" + name, value);
+            delim = ", ";
+        }
+        result.append("}");
+        return result;
+    }
+
+    /**
+     * Append the specified value's string representation to the specified
+     * StringBuilder.
+     * 
+     * @param result StringBuilder to which the string representation is
+     *        appended.
+     * @param objectRefs References to "seen" objects.
+     * @param refpath The reference path of the specified value.
+     * @param value The object whose string representation is to be appended.
+     * @return The specified StringBuilder.
+     */
+    private static StringBuilder appendValue(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Object value) {
+        if (value == null) {
+            return result.append("null");
+        }
+        // Simple Java types
+        if (value instanceof String || value instanceof Character) {
+            return appendString(result, compress(value.toString()));
+        }
+        if (value instanceof Number || value instanceof Boolean) {
+            return result.append(value.toString());
+        }
+
+        // Complex types
+        final String path = objectRefs.get(value);
+        if (path != null) {
+            result.append("{\"$ref\":");
+            appendString(result, path);
+            result.append("}");
+            return result;
+        }
+        objectRefs.put(value, refpath);
+
+        if (value instanceof DTO) {
+            return appendDTO(result, objectRefs, refpath, (DTO) value);
+        }
+        if (value instanceof Map) {
+            return appendMap(result, objectRefs, refpath, (Map<?, ?>) value);
+        }
+        if (value instanceof List || value instanceof Set) {
+            return appendIterable(result, objectRefs, refpath, (Iterable<?>) value);
+        }
+        if (value.getClass().isArray()) {
+            return appendArray(result, objectRefs, refpath, value);
+        }
+        return appendString(result, compress(value.toString()));
+    }
+
+    /**
+     * Append the specified array's string representation to the specified
+     * StringBuilder.
+     * 
+     * @param result StringBuilder to which the string representation is
+     *        appended.
+     * @param objectRefs References to "seen" objects.
+     * @param refpath The reference path of the specified array.
+     * @param array The array whose string representation is to be appended.
+     * @return The specified StringBuilder.
+     */
+    private static StringBuilder appendArray(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Object array) {
+        result.append("[");
+        final int length = Array.getLength(array);
+        for (int i = 0; i < length; i++) {
+            if (i > 0) {
+                result.append(",");
+            }
+            appendValue(result, objectRefs, refpath + "/" + i, Array.get(array, i));
+        }
+        result.append("]");
+        return result;
+    }
+
+    /**
+     * Append the specified iterable's string representation to the specified
+     * StringBuilder.
+     * 
+     * @param result StringBuilder to which the string representation is
+     *        appended.
+     * @param objectRefs References to "seen" objects.
+     * @param refpath The reference path of the specified list.
+     * @param iterable The iterable whose string representation is to be
+     *        appended.
+     * @return The specified StringBuilder.
+     */
+    private static StringBuilder appendIterable(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Iterable<?> iterable) {
+        result.append("[");
+        int i = 0;
+        for (Object item : iterable) {
+            if (i > 0) {
+                result.append(",");
+            }
+            appendValue(result, objectRefs, refpath + "/" + i, item);
+            i++;
+        }
+        result.append("]");
+        return result;
+    }
+
+    /**
+     * Append the specified map's string representation to the specified
+     * StringBuilder.
+     * 
+     * @param result StringBuilder to which the string representation is
+     *        appended.
+     * @param objectRefs References to "seen" objects.
+     * @param refpath The reference path of the specified map.
+     * @param map The map whose string representation is to be appended.
+     * @return The specified StringBuilder.
+     */
+    private static StringBuilder appendMap(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Map<?, ?> map) {
+        result.append("{");
+        String delim = "";
+        for (Map.Entry<?, ?> entry : map.entrySet()) {
+            result.append(delim);
+            final String name = String.valueOf(entry.getKey());
+            appendString(result, name);
+            result.append(":");
+            final Object value = entry.getValue();
+            appendValue(result, objectRefs, refpath + "/" + name, value);
+            delim = ", ";
+        }
+        result.append("}");
+        return result;
+    }
+
+    /**
+     * Append the specified string to the specified StringBuilder.
+     * 
+     * @param result StringBuilder to which the string is appended.
+     * @param string The string to be appended.
+     * @return The specified StringBuilder.
+     */
+    private static StringBuilder appendString(final StringBuilder result, final CharSequence string) {
+        result.append("\"");
+        int i = result.length();
+        result.append(string);
+        while (i < result.length()) { // escape if necessary
+            char c = result.charAt(i);
+            if ((c == '"') || (c == '\\')) {
+                result.insert(i, '\\');
+                i = i + 2;
+                continue;
+            }
+            if (c < 0x20) {
+                result.insert(i + 1, Integer.toHexString(c | 0x10000));
+                result.replace(i, i + 2, "\\u");
+                i = i + 6;
+                continue;
+            }
+            i++;
+        }
+        result.append("\"");
+        return result;
+    }
+
+    /**
+     * Compress, in length, the specified string.
+     * 
+     * @param in The string to potentially compress.
+     * @return The string compressed, if necessary.
+     */
+    private static CharSequence compress(final CharSequence in) {
+        final int length = in.length();
+        if (length <= 21) {
+            return in;
+        }
+        StringBuilder result = new StringBuilder(21);
+        result.append(in, 0, 9);
+        result.append("...");
+        result.append(in, length - 9, length);
+        return result;
+    }
+}
diff --git a/scr/src/main/java/org/osgi/dto/package-info.java b/scr/src/main/java/org/osgi/dto/package-info.java
new file mode 100644
index 0000000..c3010b3
--- /dev/null
+++ b/scr/src/main/java/org/osgi/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * OSGi Data Transfer Object 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.dto; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code  Import-Package: org.osgi.dto; version="[1.0,1.1)"}
+ *
+ * @author $Id: 1209bb5e60e6b6fc8239119a2dd4a2c15b9a40f2 $
+ */
+
+//@Version("1.0")
+package org.osgi.dto;
+
+//import org.osgi.annotation.versioning.Version;
+
diff --git a/scr/src/main/java/org/osgi/dto/packageinfo b/scr/src/main/java/org/osgi/dto/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/scr/src/main/java/org/osgi/dto/packageinfo
@@ -0,0 +1 @@
+version 1.0