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