Author: davidb
Date: Tue Dec 22 15:28:27 2009
New Revision: 893205
URL: http://svn.apache.org/viewvc?rev=893205&view=rev
Log:
Initial work towards local discovery.
Added:
cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml (with props)
Modified:
cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java
cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtilsTest.java
Modified:
cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java
URL:
http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java?rev=893205&r1=893204&r2=893205&view=diff
==============================================================================
---
cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java
(original)
+++
cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java
Tue Dec 22 15:28:27 2009
@@ -18,12 +18,16 @@
*/
package org.apache.cxf.dosgi.discovery.local;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -37,6 +41,7 @@
import org.osgi.framework.Bundle;
import org.osgi.service.discovery.ServiceEndpointDescription;
import org.osgi.service.discovery.ServicePublication;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
public final class LocalDiscoveryUtils {
@@ -47,10 +52,13 @@
private static final String REMOTE_SERVICES_DIRECTORY =
"OSGI-INF/remote-service";
private static final String REMOTE_SERVICES_NS =
- "http://www.osgi.org/xmlns/sd/v1.0.0";
+ "http://www.osgi.org/xmlns/sd/v1.0.0"; // this one was replaced by the
RSA one in the spec
+ private static final String REMOTE_SERVICES_ADMIN_NS =
+ "http://www.osgi.org/xmlns/rsa/v1.0.0";
private static final String SERVICE_DESCRIPTION_ELEMENT =
"service-description";
+ private static final String ENDPOINT_DESCRIPTION_ELEMENT =
"endpoint-description";
private static final String PROVIDE_INTERFACE_ELEMENT = "provide";
private static final String PROVIDE_INTERFACE_NAME_ATTRIBUTE = "interface";
@@ -89,6 +97,183 @@
}
+
+ @SuppressWarnings("unchecked")
+ public static List<EndpointDescription> getAllEndpointDescriptions(Bundle
b) {
+ List<Element> elements = getAllDescriptionElements(b);
+
+ List<EndpointDescription> eds = new
ArrayList<EndpointDescription>(elements.size());
+ for (Element el : elements) {
+ if (ENDPOINT_DESCRIPTION_ELEMENT.equals(el.getName())) {
+ eds.add(getEndpointDescription(el));
+ } else if (SERVICE_DESCRIPTION_ELEMENT.equals(el.getName())) {
+ Namespace ns = Namespace.getNamespace(REMOTE_SERVICES_NS);
+
+ List<String> iNames =
getProvidedInterfaces(el.getChildren(PROVIDE_INTERFACE_ELEMENT, ns));
+ Map<String, Object> remoteProps =
getProperties(el.getChildren(PROPERTY_ELEMENT, ns));
+
+ // this property is used by discovery for matching
+ remoteProps.put(ServicePublication.SERVICE_INTERFACE_NAME,
iNames);
+
+ if (addEndpointID) {
+ remoteProps.put(ServicePublication.ENDPOINT_ID,
UUID.randomUUID().toString());
+ }
+ // @@@@ TODO
+ // srefs.add(new ServiceEndpointDescriptionImpl(iNames,
remoteProps));
+ }
+ }
+ return eds;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static EndpointDescription getEndpointDescription(Element
endpointDescriptionElement) {
+ Map<String, Object> map = new HashMap<String, Object>();
+
+ List<Element> properties =
endpointDescriptionElement.getChildren("property");
+ for (Element prop : properties) {
+ boolean handled = handleArray(prop, map);
+ if (handled) {
+ continue;
+ }
+ handled = handleList(prop, map);
+ if (handled) {
+ continue;
+ }
+
+ String name = prop.getAttributeValue("name");
+ String value = prop.getAttributeValue("value");
+ if (value == null) {
+ value = prop.getText();
+ }
+ String type = getTypeName(prop);
+ map.put(name, instantiate(type, value));
+ }
+ return new EndpointDescription(map);
+ }
+
+ private static String getTypeName(Element prop) {
+ String type = prop.getAttributeValue("value-type");
+ if (type == null) {
+ type = "String";
+ }
+ return type;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static boolean handleArray(Element prop, Map<String, Object> map) {
+ Element arrayEl = prop.getChild("array");
+ if (arrayEl == null) {
+ return false;
+ }
+
+ List<Element> values = arrayEl.getChildren("value");
+ String type = getTypeName(prop);
+ Class<?> cls = null;
+ if ("long".equals(type)) {
+ cls = long.class;
+ } else if ("double".equals(type)) {
+ cls = double.class;
+ } else if ("float".equals(type)) {
+ cls = float.class;
+ } else if ("int".equals(type)) {
+ cls = int.class;
+ } else if ("byte".equals(type)) {
+ cls = byte.class;
+ } else if ("boolean".equals(type)) {
+ cls = boolean.class;
+ } else if ("short".equals(type)) {
+ cls = short.class;
+ }
+
+ try {
+ if (cls == null) {
+ cls = Class.forName("java.lang." + type, true,
String.class.getClassLoader());
+ }
+ Object array = Array.newInstance(cls, values.size());
+
+ for (int i=0; i < values.size(); i++) {
+ Element vEl = values.get(i);
+ Object val = instantiate(type, vEl.getText());
+ Array.set(array, i, val);
+ }
+
+ String name = prop.getAttributeValue("name");
+ map.put(name, array);
+ return true;
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, "Could not create array for Endpoint
Description", e);
+ return false;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static boolean handleList(Element prop, Map<String, Object> map) {
+ Collection<Object> col = null;
+ Element el = prop.getChild("list");
+ if (el != null) {
+ col = new ArrayList<Object>();
+ } else {
+ el = prop.getChild("set");
+ if (el != null) {
+ col = new HashSet<Object>();
+ }
+ }
+
+ if (el == null) {
+ return false;
+ }
+
+ String type = getTypeName(prop);
+ List<Element> values = el.getChildren("value");
+ for (Element val : values) {
+ col.add(instantiate(type, val.getText()));
+ }
+
+ String name = prop.getAttributeValue("name");
+ map.put(name, col);
+ return true;
+ }
+
+ private static Object instantiate(String type, String value) {
+ if ("String".equals(type)) {
+ return value;
+ }
+
+ value = value.trim();
+ String boxedType = null;
+ if ("long".equals(type)) {
+ boxedType = "Long";
+ } else if ("double".equals(type)) {
+ boxedType = "Double";
+ } else if ("float".equals(type)) {
+ boxedType = "Float";
+ } else if ("int".equals(type)) {
+ boxedType = "Integer";
+ } else if ("byte".equals(type)) {
+ boxedType = "Byte";
+ } else if ("char".equals(type)) {
+ boxedType = "Character";
+ } else if ("boolean".equals(type)) {
+ boxedType = "Boolean";
+ } else if ("short".equals(type)) {
+ boxedType = "Short";
+ }
+
+ if (boxedType == null) {
+ boxedType = type;
+ }
+ String javaType = "java.lang." + boxedType;
+
+ try {
+ Class<?> cls = String.class.getClassLoader().loadClass(javaType);
+ Constructor<?> ctor = cls.getConstructor(String.class);
+ return ctor.newInstance(value);
+ } catch (Exception e) {
+ LOG.warning("Could not create Endpoint Property of type " + type +
" and value " + value);
+ return null;
+ }
+ }
+
@SuppressWarnings("unchecked")
static List<Element> getAllDescriptionElements(Bundle b) {
Object directory = null;
@@ -112,8 +297,12 @@
URL resourceURL = (URL) urls.nextElement();
try {
Document d = new SAXBuilder().build(resourceURL.openStream());
- Namespace ns = Namespace.getNamespace(REMOTE_SERVICES_NS);
-
elements.addAll(d.getRootElement().getChildren(SERVICE_DESCRIPTION_ELEMENT,
ns));
+ if
(d.getRootElement().getNamespaceURI().equals(REMOTE_SERVICES_ADMIN_NS)) {
+
elements.addAll(d.getRootElement().getChildren(ENDPOINT_DESCRIPTION_ELEMENT));
+ }
+
+ Namespace nsOld = Namespace.getNamespace(REMOTE_SERVICES_NS);
+
elements.addAll(d.getRootElement().getChildren(SERVICE_DESCRIPTION_ELEMENT,
nsOld));
} catch (Exception ex) {
LOG.log(Level.WARNING, "Problem parsing: " + resourceURL, ex);
}
@@ -154,5 +343,5 @@
}
return names;
- }
+ }
}
Modified:
cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtilsTest.java
URL:
http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtilsTest.java?rev=893205&r1=893204&r2=893205&view=diff
==============================================================================
---
cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtilsTest.java
(original)
+++
cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtilsTest.java
Tue Dec 22 15:28:27 2009
@@ -37,6 +37,7 @@
import org.osgi.framework.Bundle;
import org.osgi.service.discovery.ServiceEndpointDescription;
import org.osgi.service.discovery.ServicePublication;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
public class LocalDiscoveryUtilsTest extends TestCase {
public void testNoRemoteServicesXMLFiles() {
@@ -148,4 +149,50 @@
return map;
}
+
+ public void testEndpointDescriptionXMLFiles() {
+ URL ed1URL = getClass().getResource("/ed1.xml");
+
+ Bundle b = EasyMock.createNiceMock(Bundle.class);
+ EasyMock.expect(b.findEntries(
+ EasyMock.eq("OSGI-INF/remote-service"),
+ EasyMock.eq("*.xml"), EasyMock.anyBoolean())).andReturn(
+ Collections.enumeration(Arrays.asList(ed1URL))).anyTimes();
+ EasyMock.replay(b);
+
+ List<Element> edElements =
LocalDiscoveryUtils.getAllDescriptionElements(b);
+ assertEquals(4, edElements.size());
+ }
+
+ public void testAllEndpoints() {
+ URL ed1URL = getClass().getResource("/ed1.xml");
+
+ Bundle b = EasyMock.createNiceMock(Bundle.class);
+ EasyMock.expect(b.findEntries(
+ EasyMock.eq("OSGI-INF/remote-service"),
+ EasyMock.eq("*.xml"), EasyMock.anyBoolean())).andReturn(
+ Collections.enumeration(Arrays.asList(ed1URL))).anyTimes();
+ EasyMock.replay(b);
+
+ List<EndpointDescription> eds =
LocalDiscoveryUtils.getAllEndpointDescriptions(b);
+ assertEquals(4, eds.size());
+ EndpointDescription ed0 = eds.get(0);
+ assertEquals("http://somewhere:12345", ed0.getRemoteURI());
+ assertEquals(Arrays.asList("SomeService"), ed0.getInterfaces());
+ assertEquals(Arrays.asList("confidentiality"),
+ ed0.getProperties().get("osgi.remote.requires.intents"));
+ assertEquals("testValue", ed0.getProperties().get("testKey"));
+
+ EndpointDescription ed1 = eds.get(1);
+ assertEquals("myScheme://somewhere:12345", ed1.getRemoteURI());
+ assertEquals(Arrays.asList("SomeOtherService",
"WithSomeSecondInterface"), ed1.getInterfaces());
+
+ EndpointDescription ed2 = eds.get(2);
+ assertEquals("http://somewhere", ed2.getRemoteURI());
+ assertEquals(Arrays.asList("SomeOtherService",
"WithSomeSecondInterface"), ed2.getInterfaces());
+
+ EndpointDescription ed3 = eds.get(3);
+ assertEquals("http://somewhere:1/2/3/4?5", ed3.getRemoteURI());
+ assertEquals(Arrays.asList("SomeOtherService",
"WithSomeSecondInterface"), ed3.getInterfaces());
+ }
}
Added: cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml
URL:
http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml?rev=893205&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml Tue Dec 22
15:28:27 2009
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<rsa:endpoint-descriptions xmlns:rsa="http://www.osgi.org/xmlns/rsa/v1.0.0"
+ xmlns:other="http://www.acme.org/xmlns/other/v1.0.0">
+ <endpoint-description>
+ <property name="objectClass">
+ <array>
+ <value>SomeService</value>
+ </array>
+ </property>
+ <property name="osgi.remote.requires.intents">
+ <list>
+ <value>confidentiality</value>
+ </list>
+ </property>
+ <property name="testKey" value="testValue"/>
+ <property name="endpoint.uri">http://somewhere:12345</property>
+ </endpoint-description>
+
+ <endpoint-description>
+ <property name="objectClass">
+ <array>
+ <value>SomeOtherService</value>
+ <value>WithSomeSecondInterface</value>
+ </array>
+ </property>
+ <property name="endpoint.uri" value-type="String"
value="myScheme://somewhere:12345" />
+ </endpoint-description>
+
+ <endpoint-description>
+ <property name="objectClass" value-type="String">
+ <array>
+ <value>SomeOtherService</value>
+ <value>WithSomeSecondInterface</value>
+ </array>
+ </property>
+ <property name="endpoint.uri" value="http://somewhere" />
+ </endpoint-description>
+
+ <endpoint-description>
+ <property name="objectClass">
+ <array>
+ <value>SomeOtherService</value>
+ <value>WithSomeSecondInterface</value>
+ </array>
+ </property>
+ <property name="endpoint.uri"
value-type="String">http://somewhere:1/2/3/4?5</property>
+ </endpoint-description>
+</rsa:endpoint-descriptions>
+
Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/ed1.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml