Package org.apache.cxf.dosgi.discovery.local

Source Code of org.apache.cxf.dosgi.discovery.local.LocalDiscoveryUtils

/**
  * 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.
  */
package org.apache.cxf.dosgi.discovery.local;

import java.io.IOException;
import java.io.InputStream;
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.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.remoteserviceadmin.EndpointDescription;
import org.osgi.service.remoteserviceadmin.RemoteConstants;


public final class LocalDiscoveryUtils {
    private static final Logger LOG =
        Logger.getLogger(LocalDiscoveryUtils.class.getName());       
   
    private static final String REMOTE_SERVICES_HEADER_NAME = "Remote-Service";
    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"; // 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";

    private static final String PROPERTY_ELEMENT = "property";
    private static final String PROPERTY_NAME_ATTRIBUTE = "name";
    private static final String PROPERTY_VALUE_ATTRIBUTE = "value";
    private static final String PROPERTY_VALUE_TYPE_ATTRIBUTE = "value-type";
    private static final String PROPERTY_INTERFACE_ATTRIBUTE = "interface";

    private static final String INTERFACE_SEPARATOR = ":";
   
    static boolean addEndpointID = true; // for testing
   
    private LocalDiscoveryUtils() {}
   
    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())) {
                eds.add(getLegacyEndpointDescription(el));
            }
        }
        return eds;
    }

    @SuppressWarnings("unchecked")
    public static EndpointDescription getEndpointDescription(Element endpointDescriptionElement) {
        Map<String, Object> map = new HashMap<String, Object>();
       
        List<Element> properties = endpointDescriptionElement.getChildren(PROPERTY_ELEMENT,
                Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
        for (Element prop : properties) {
            boolean handled = handleArray(prop, map);
            if (handled) {
                continue;
            }
            handled = handleCollection(prop, map);
            if (handled) {
                continue;
            }
            handled = handleXML(prop, map);
            if (handled) {
                continue;
            }
           
            String name = prop.getAttributeValue(PROPERTY_NAME_ATTRIBUTE);
            String value = prop.getAttributeValue(PROPERTY_VALUE_ATTRIBUTE);
            if (value == null) {
                value = prop.getText();
            }
            String type = getTypeName(prop);
            map.put(name, instantiate(type, value));
        }
        return new EndpointDescription(map);
    }

    @SuppressWarnings("unchecked")
    private static EndpointDescription getLegacyEndpointDescription(Element el) {
        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));
       
        if (remoteProps.get(Constants.OBJECTCLASS) == null) {
            remoteProps.put(Constants.OBJECTCLASS, iNames.toArray(new String[] {}));
        }
       
        Object uri = remoteProps.get("org.apache.cxf.ws.address");
        if (uri == null) {
            uri = remoteProps.get("osgi.remote.configuration.pojo.address");
        }
        if (uri == null) {
            String firstIntf = iNames.get(0);
            uri = "http://localhost:9000/" + firstIntf.replace('.', '/');
        }
        remoteProps.put(RemoteConstants.ENDPOINT_ID, uri.toString());
       
        Object exportedConfigs = remoteProps.get(RemoteConstants.SERVICE_EXPORTED_CONFIGS);
        if (exportedConfigs == null) {
            exportedConfigs = "org.apache.cxf.ws";
        }
        remoteProps.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, exportedConfigs);
       
        for(Iterator<String> it = remoteProps.keySet().iterator(); it.hasNext(); ) {
            if (it.next().startsWith("service.exported.")) {
                it.remove();
            }
        }
       
        return new EndpointDescription(remoteProps);
    }

    private static String getTypeName(Element prop) {
        String type = prop.getAttributeValue(PROPERTY_VALUE_TYPE_ATTRIBUTE);
        if (type == null) {
            type = "String";
        }
        return type;
    }

    @SuppressWarnings("unchecked")
    private static boolean handleArray(Element prop, Map<String, Object> map) {
        Element arrayEl = prop.getChild("array", Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
        if (arrayEl == null) {
            return false;
        }
       
        List<Element> values = arrayEl.getChildren(PROPERTY_VALUE_ATTRIBUTE,
                Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
        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 = ClassLoader.getSystemClassLoader().loadClass("java.lang." + type);
            }
            Object array = Array.newInstance(cls, values.size());
           
            for (int i=0; i < values.size(); i++) {
                Element vEl = values.get(i);
                Object val = handleValue(vEl, type);
                Array.set(array, i, val);
            }
           
            String name = prop.getAttributeValue(PROPERTY_NAME_ATTRIBUTE);
            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 handleCollection(Element prop, Map<String, Object> map) {
        Collection<Object> col = null;       
        Element el = prop.getChild("list",
                Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
        if (el != null) {
            col = new ArrayList<Object>();
        } else {
            el = prop.getChild("set", Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
            if (el != null) {
                col = new HashSet<Object>();
            }
        }
               
        if (el == null) {
            return false;
        }
       
        String type = getTypeName(prop);
        List<Element> values = el.getChildren(PROPERTY_VALUE_ATTRIBUTE,
                Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
        for (Element val : values) {
            Object obj = handleValue(val, type);
            col.add(obj);
        }
       
        String name = prop.getAttributeValue(PROPERTY_NAME_ATTRIBUTE);
        map.put(name, col);
        return true;
    }

    private static boolean handleXML(Element prop, Map<String, Object> map) {
        String sb = readXML(prop);
        if (sb == null) {
            return false;
        }

        String name = prop.getAttributeValue(PROPERTY_NAME_ATTRIBUTE);
        map.put(name, sb);
        return true;
    }

    @SuppressWarnings("unchecked")
    private static String readXML(Element prop) {
        Element el = prop.getChild("xml", Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS));
        if (el == null) {
            return null;
        }
       
        String type = getTypeName(prop);
        if (!"String".equals(type)) {
            LOG.warning("Embedded XML must be of type String, found: " + type);
            return null;
        }
       
        XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat());
        StringBuilder sb = new StringBuilder();   
        List<Element> children = el.getChildren();
        for (Element child : children) {
            sb.append(outputter.outputString(child));
        }
        return sb.toString();
    }

    private static Object handleValue(Element val, String type) {
        String xml = readXML(val);
        if (xml != null) {
            return xml;
        } else {
            return instantiate(type, val.getText());
        }
    }

    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 {
            if (boxedType.equals("Character")) {
                return new Character(value.charAt(0));
            } else {
                Class<?> cls = ClassLoader.getSystemClassLoader().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 header = null;
       
        Dictionary headers = b.getHeaders();
        if (headers != null) {
            header = headers.get(REMOTE_SERVICES_HEADER_NAME);
        }
       
        if (header == null) {
            header = REMOTE_SERVICES_DIRECTORY;
        }
       
        String dir = header.toString();
        String filePattern = "*.xml";
        if (dir.endsWith("/")) {
            dir = dir.substring(0, dir.length()-1);
        } else {
            int idx = dir.lastIndexOf('/');
            if (idx >= 0 & dir.length() > idx) {
                filePattern = dir.substring(idx + 1);
                dir = dir.substring(0, idx);
            } else {
                filePattern = dir;
                dir = "";
            }
        }
       
        Enumeration urls = b.findEntries(dir, filePattern, false);
        if (urls == null) {
            return Collections.emptyList();
        }

        List<Element> elements = new ArrayList<Element>();
        while (urls.hasMoreElements()) {
            URL resourceURL = (URL) urls.nextElement();
            try {
                elements.addAll(getElements(resourceURL.openStream()));
            } catch (Exception ex) {
                LOG.log(Level.WARNING, "Problem parsing: " + resourceURL, ex);
            }           
        }
        return elements;
    }
   
    private static Map<String, Object> getProperties(List<Element> elements) {      
        Map<String, Object> props = new HashMap<String, Object>();
       
        for (Element p : elements) {
            String key = p.getAttributeValue(PROPERTY_NAME_ATTRIBUTE);
            String value = p.getAttributeValue(PROPERTY_VALUE_ATTRIBUTE);
            if (value == null) {
                value = p.getTextTrim();
            }
           
            String iface = p.getAttributeValue(PROPERTY_INTERFACE_ATTRIBUTE);
            if (key != null) {
                props.put(iface == null || iface.length() == 0
                          ? key
                          : key + INTERFACE_SEPARATOR + iface,
                          value);
            }
        }
       
        return props;
    }
   
    private static List<String> getProvidedInterfaces(List<Element> elements) {       
        List<String> names = new ArrayList<String>();
       
        for (Element p : elements) {
            String name = p.getAttributeValue(PROVIDE_INTERFACE_NAME_ATTRIBUTE);
            if (name != null) {
                names.add(name);
            }
        }
       
        return names;
    }
   
    public static List<String> getStringPlusProperty(ServiceReference sr, String key) {
        Object value = sr.getProperty(key);
        if (value == null) {
            return Collections.emptyList();
        }

        if (value instanceof String) {
            return Collections.singletonList((String) value);
        }

        if (value instanceof String[]) {
            String[] values = (String[]) value;
            List<String> result = new ArrayList<String>(values.length);
            for (String v : values) {
                if (v != null) {
                    result.add(v);
                }
            }
            return Collections.unmodifiableList(result);
        }

        if (value instanceof Collection<?>) {
            Collection<?> values = (Collection<?>) value;
            List<String> result = new ArrayList<String>(values.size());
            for (Iterator<?> iter = values.iterator(); iter.hasNext();) {
                Object v = iter.next();
                if ((v != null) && (v instanceof String)) {
                    result.add((String) v);
                }
            }
            return Collections.unmodifiableList(result);
        }

        return Collections.emptyList();
    }

    @SuppressWarnings("unchecked")
    public static String getEndpointDescriptionXML(Map m) {
        Document d = new Document();
        Namespace ns = Namespace.getNamespace("http://www.osgi.org/xmlns/rsa/v1.0.0");
        Element rootEl = new Element("endpoint-descriptions", ns);
        d.setRootElement(rootEl);
        Element contentEl = new Element("endpoint-description", ns);
        rootEl.addContent(contentEl);

        for (Map.Entry entry : (Set<Map.Entry>) m.entrySet()) {
            String key = entry.getKey().toString();
            Object val = entry.getValue();
           
            Element propEl = new Element("property", ns);
            propEl.setAttribute("name", key);
            if (val.getClass().isArray()) {
                Element arrayEl = new Element("array", ns);
                propEl.addContent(arrayEl);
                for (Object o : normalizeArray(val)) {
                    setValueType(propEl, o);
                    Element valueEl = new Element("value", ns);
                    arrayEl.addContent(valueEl);
                    valueEl.addContent(o.toString());
                }
            } else if (val instanceof List) {
                Element listEl = new Element("list", ns);
                propEl.addContent(listEl);
                handleCollectionValue(ns, (Collection) val, propEl, listEl);
            } else if (val instanceof Set) {
                Element setEl = new Element("set", ns);
                propEl.addContent(setEl);
                handleCollectionValue(ns, (Collection) val, propEl, setEl);               
            } else {
                setValueType(propEl, val);
                propEl.setAttribute("value", val.toString());
            }
            contentEl.addContent(propEl);
        }
       
        return new XMLOutputter(Format.getPrettyFormat()).outputString(d);
    }

    @SuppressWarnings("unchecked")
    private static Object [] normalizeArray(Object val) {
        List l = new ArrayList();
        if (val instanceof int[]) {
            int[] ia = (int []) val;
            for (int i : ia) {
                l.add(i);
            }
        } else if (val instanceof long[]) {
            long[] la = (long []) val;
            for (long i : la) {
                l.add(i);
            }
        } else if (val instanceof float[]) {
            float[] fa = (float[]) val;
            for (float f : fa) {
                l.add(f);
            }
        } else if (val instanceof byte[]) {
            byte[] ba = (byte []) val;
            for (byte b : ba) {
                l.add(b);
            }
        } else if (val instanceof boolean[]) {
            boolean[] ba = (boolean []) val;
            for (boolean b : ba) {
                l.add(b);
            }
        } else if (val instanceof short[]) {
            short[] sa = (short []) val;
            for (short s : sa) {
                l.add(s);
            }
        } else if (val instanceof char[]) {
            char[] ca = (char []) val;
            for (char c : ca) {
                l.add(c);
            }
        } else {
            return (Object []) val;
        }
        return l.toArray();
    }

    @SuppressWarnings("unchecked")
    private static void handleCollectionValue(Namespace ns, Collection val, Element propEl, Element listEl) {
        for (Object o : val) {
            setValueType(propEl, o);
            Element valueEl = new Element("value", ns);
            listEl.addContent(valueEl);
            valueEl.addContent(o.toString());
        }
    }

    private static void setValueType(Element propEl, Object val) {
        if (val instanceof String) {
            return;
        }
       
        String dataType = val.getClass().getName();
        if (dataType.startsWith("java.lang.")) {
            dataType = dataType.substring("java.lang.".length());
        }
        propEl.setAttribute("value-type", dataType);
    }

    public static List<Element> getElements(InputStream in) throws JDOMException, IOException {

        List<Element> elements = new ArrayList<Element>();
       
        Document d = new SAXBuilder().build(in);
        if (d.getRootElement().getNamespaceURI().equals(REMOTE_SERVICES_ADMIN_NS)) {
            elements.addAll(d.getRootElement().getChildren(ENDPOINT_DESCRIPTION_ELEMENT,
                    Namespace.getNamespace(REMOTE_SERVICES_ADMIN_NS)));
        }
       
        Namespace nsOld = Namespace.getNamespace(REMOTE_SERVICES_NS);
        elements.addAll(d.getRootElement().getChildren(SERVICE_DESCRIPTION_ELEMENT, nsOld));
       
        return elements;
    }   
}
TOP

Related Classes of org.apache.cxf.dosgi.discovery.local.LocalDiscoveryUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.