Package org.apache.cxf.dosgi.dsw

Source Code of org.apache.cxf.dosgi.dsw.OsgiUtils

/**
  * 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.dsw;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.cxf.dosgi.dsw.qos.IntentMap;
import org.apache.cxf.dosgi.dsw.service.ServiceEndpointDescriptionImpl;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.discovery.ServiceEndpointDescription;
import org.osgi.service.distribution.DistributionConstants;
import org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext;


public final class OsgiUtils {

    private static final Logger LOG =
        Logger.getLogger(OsgiUtils.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";
   
    static final String[] INTENT_MAP = {"/OSGI-INF/cxf/intents/intent-map.xml"};
   
    private static final String SERVICE_DESCRIPTION_ELEMENT = "service-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_INTERFACE_ATTRIBUTE = "interface";

    private static final String INTERFACE_WILDCARD = "*";
    private static final String INTERFACE_SEPARATOR = ":";
   
    private OsgiUtils() {
    }

   
    // Used by PublishHook
    public static ServiceEndpointDescription getRemoteReference(ServiceReference sref, boolean matchAllNames) {
       
        String[] names = (String[])sref.getProperty(org.osgi.framework.Constants.OBJECTCLASS);
        if (names == null || names.length == 0) {
            return null;
        }
       
        Map<String, Object> userProperties = new HashMap<String, Object>();
        for (String key : sref.getPropertyKeys()) {
            // we're after remote properties only
            if (key.startsWith(DistributionConstants.REMOTE)) {
                userProperties.put(key, sref.getProperty(key));
            }
        }
        List<ServiceEndpointDescription> srefs = getRemoteReferences(sref.getBundle(),
                                                             names,
                                                             userProperties,
                                                             matchAllNames);
       
        if (srefs.isEmpty()) {
            return new ServiceEndpointDescriptionImpl(Arrays.asList(names), userProperties);
        }
       
        return srefs.get(0);
    }
   
    @SuppressWarnings("unchecked")
    public static List<ServiceEndpointDescription> getRemoteReferences(
        Bundle b, String[] names, Map<String, Object> userProperties, boolean matchAllNames) {
       
        List<Element> references = getAllDescriptionElements(b);
       
        List<ServiceEndpointDescription> srefs = new ArrayList<ServiceEndpointDescription>();
        Namespace ns = Namespace.getNamespace(REMOTE_SERVICES_NS);
        for (Element ref : references) {
            List<String> iNames = getProvidedInterfaces(ref.getChildren(PROVIDE_INTERFACE_ELEMENT, ns));
            if (!serviceNamesMatch(names, iNames, matchAllNames)) {
                continue;
            }

            Map<String, Object> remoteProps = getProperties(ref.getChildren(PROPERTY_ELEMENT, ns));
            remoteProps.putAll(userProperties);
            srefs.add(new ServiceEndpointDescriptionImpl(iNames, remoteProps));
           
        }
        return srefs;
       
    }
   
    @SuppressWarnings("unchecked")
    public static List<ServiceEndpointDescription> getAllRemoteReferences(Bundle b) {
        List<Element> references = getAllDescriptionElements(b);
       
        List<ServiceEndpointDescription> srefs = new ArrayList<ServiceEndpointDescription>();
        Namespace ns = Namespace.getNamespace(REMOTE_SERVICES_NS);
        for (Element ref : references) {
            List<String> iNames = getProvidedInterfaces(ref.getChildren(PROVIDE_INTERFACE_ELEMENT, ns));
            Map<String, Object> remoteProps = getProperties(ref.getChildren(PROPERTY_ELEMENT, ns));
            srefs.add(new ServiceEndpointDescriptionImpl(iNames, remoteProps));
        }
        return srefs;
       
    }

    public static ServiceEndpointDescription[] flattenServiceDescription(ServiceEndpointDescription sd) {
        ServiceEndpointDescription[] list = null;
        int interfaceNameCount = sd.getProvidedInterfaces().size();
        if (sd.getProvidedInterfaces() == null || interfaceNameCount <= 1) {
            list = new ServiceEndpointDescription[] {sd};
        } else {
            String[] iNames = (String[])
                sd.getProvidedInterfaces().toArray(new String[interfaceNameCount]);
            list = new ServiceEndpointDescription[iNames.length];
            for (int i = 0; i < iNames.length; i++) {
                Map<String, Object> props = excludeProperty(sd.getProperties()
                        DistributionConstants.REMOTE_INTERFACES);
               
                String keys[] = props.keySet().toArray(new String[props.size()]);
                for (int j = 0; j < keys.length; j++) {
                    int sep = keys[j].indexOf(INTERFACE_SEPARATOR);
                    if (sep > -1) {
                        String value = (String)props.remove(keys[j]);
                        String root = keys[j].substring(0, sep);
                        String iface =
                          sep + INTERFACE_SEPARATOR.length() < keys[j].length()
                          ? keys[j].substring(sep + INTERFACE_SEPARATOR.length())
                          : "";
                        if (iNames[i].equals(iface)) {
                            props.put(root, value);
                        }
                    }
                }
                list[i] = new ServiceEndpointDescriptionImpl(iNames[i], props);
            }
        }
        return list;
    }

    private static Map<String, Object> excludeProperty(Map properties,
                                                       String exclude) {
        Map<String, Object> pruned = new HashMap<String, Object>();
        for (Object key : properties.keySet()) {
            if (key.equals(exclude)) {
            } else {
                pruned.put((String)key, properties.get(key));
            }
        }
        return pruned;
    }
   
    @SuppressWarnings("unchecked")
    public static List<Element> getAllDescriptionElements(Bundle b) {
        Object directory = null;
       
        Dictionary headers = b.getHeaders();
        if (headers != null) {
            directory = headers.get(REMOTE_SERVICES_HEADER_NAME);
        }
       
        if (directory == null) {
            directory = REMOTE_SERVICES_DIRECTORY;
        }
       
        Enumeration urls = b.findEntries(directory.toString(), "*.xml", false);
        if (urls == null) {
            return Collections.emptyList();
        }

        List<Element> elements = new ArrayList<Element>();
        while (urls.hasMoreElements()) {
            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));
            } catch (Exception ex) {
                LOG.log(Level.WARNING, "Problem parsing: " + resourceURL, ex);
            }           
        }
        return elements;
    }
   
    private static boolean serviceNamesMatch(
        String[] names, List<String> iNames, boolean matchAllNames) {
        if (names == null || names.length == 0) {
            return false;
        }
        if (matchAllNames) {
            for (String name : names) {
                if (!iNames.contains(name)) {
                    return false;
                }
            }
            return true;
        } else {
            for (String name : names) {
                if (iNames.contains(name)) {
                    return true;
                }
            }
            return false;
        }
    }
   
    // TODO : consider creating a new List rather than modifyiing the existing one
    public static void matchServiceDescriptions(List<ServiceEndpointDescription> sds,
                                                String interfaceName,
                                                Filter filter,
                                                boolean matchAll) {
       
        for (Iterator<ServiceEndpointDescription> it = sds.iterator(); it.hasNext();) {
            ServiceEndpointDescription sd = it.next();
            
            if (filter != null && !OsgiUtils.matchAgainstFilter(sd, interfaceName, filter, matchAll)) {
                it.remove();
            }
        }
    }
   
    @SuppressWarnings("unchecked")
    public static boolean matchAgainstFilter(ServiceEndpointDescription sd,
        String interfaceName, Filter filter, boolean matchAll) {
        Dictionary props = new Hashtable();
        for (Object key : sd.getPropertyKeys()) {
            if (matchAll || key.toString().startsWith(DistributionConstants.REMOTE)) {
                props.put(key, sd.getProperty(key.toString()));
            }
        }
        String[] interfaceNames = getProvidedInterfaces(sd, interfaceName);
        if (interfaceNames != null) {
            props.put(org.osgi.framework.Constants.OBJECTCLASS,
                      interfaceNames);
        }
        return filter.match(props);
    }
   
    public static String[] getProvidedInterfaces(ServiceEndpointDescription sd, String interfaceName) {
       
        int interfaceNameCount = sd.getProvidedInterfaces().size();
        String[] interfaceNames = (String[])
            sd.getProvidedInterfaces().toArray(new String[interfaceNameCount]);
        if (interfaceName == null) {
            return interfaceNames;
        }
       
        for (String s : interfaceNames) {
            if (s.equals(interfaceName)) {
                return new String[]{s};
            }
        }
        return null;
    }
   
    public static Filter createFilter(BundleContext bc, String filterValue) {
       
        if (filterValue == null) {
            return null;
        }
       
        try {
            return bc.createFilter(filterValue);
        } catch (InvalidSyntaxException ex) {
            System.out.println("Invalid filter expression " + filterValue);
        } catch (Exception ex) {
            System.out.println("Problem creating a Filter from " + filterValue);
        }
        return null;
    }
   
    public static String[] parseIntents(String intentsSequence) {
        return intentsSequence == null ? new String[]{} : intentsSequence.split(" ");
    }
   
    public static String formatIntents(String [] intents) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String intent : intents) {
            if (first) {
                first = false;
            } else {
                sb.append(' ');
            }
            sb.append(intent);
        }
        return sb.toString();
    }
   
    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;
    }
   
    @SuppressWarnings("unchecked")
    public static <T> OsgiService<T> getOsgiService(
        BundleContext bc, Class<T> serviceClass) {
        try {
            ServiceReference sr = bc.getServiceReference(serviceClass.getName());
            if (sr != null) {
                Object o = bc.getService(sr);
                if (o != null && serviceClass.isAssignableFrom(o.getClass())) {
                    return new OsgiService(sr, o);
                }
            }
        } catch (Exception ex) {
            if (LOG.isLoggable(Level.FINE)) {
                LOG.fine("Problem retrieving an OSGI service " + serviceClass.getName()
                + ", exception : " + ex.getMessage());
            }
        }
        return null;
    }
   
    public static IntentMap getIntentMap(BundleContext bundleContext) {
        IntentMap im = readIntentMap(bundleContext);
        if (im == null) {
            // Couldn't read an intent map
            LOG.log(Level.FINE, "Using default intent map");
            im = new IntentMap();
            im.setIntents(new HashMap<String, Object>());
        }
        return im;       
    }
   
    static IntentMap readIntentMap(BundleContext bundleContext) {
        List<String> springIntentLocations = new ArrayList<String>();
        for (String mapFile : INTENT_MAP) {
            if (bundleContext.getBundle().getResource(mapFile) == null) {
                LOG.info("Could not find intent map file " + mapFile);
                return null;
            }
            springIntentLocations.add("classpath:" + mapFile);
        }
       
        try {
            OsgiBundleXmlApplicationContext ctx =
                new OsgiBundleXmlApplicationContext(springIntentLocations.toArray(new String [] {}));
            ctx.setPublishContextAsService(false);
            ctx.setBundleContext(bundleContext);
            ctx.refresh();
            LOG.fine("application context: " + ctx);
            IntentMap im = (IntentMap)ctx.getBean("intentMap");
            LOG.fine("retrieved intent map: " + im);
            return im;
        } catch (Throwable t) {
            LOG.log(Level.WARNING, "Intent map load failed: ", t);
            return null;
        }
    }
   
    //Eg. "(&(" + Constants.OBJECTCLASS + "=Person)(|(sn=Jensen)(cn=Babs J*)))"
    public static Filter createFilterFromProperties(BundleContext bc,
                                             Dictionary properties) {
       
        if (properties == null || properties.isEmpty()) {
            return null;
        }
       
        StringBuilder sb = new StringBuilder();
        sb.append("(&");
        for (Enumeration keys = properties.keys();keys.hasMoreElements();) {
            String key = keys.nextElement().toString();
            String value = properties.get(key).toString();
            sb.append('(').append(key).append('=').append(value).append(')');
        }
        sb.append(')');
        return createFilter(bc, sb.toString());
    }
   
   
    // TODO : move these property helpers into PropertyUtils ?
   
    public static boolean getBooleanProperty(ServiceEndpointDescription sd, String name) {
        Object value = sd.getProperty(name);
        return toBoolean(value);
    }
   
    public static boolean toBoolean(Object value) {
        return value instanceof Boolean && ((Boolean)value).booleanValue()
            || value instanceof String && Boolean.parseBoolean((String)value);
    }
   
    public static String getProperty(ServiceEndpointDescription sd, String name) {
        return getProperty(sd, name, String.class, null);
    }
   
    @SuppressWarnings("unchecked")
    public static <T> T getProperty(ServiceEndpointDescription sd, String name, Class<T> type,
                             T defaultValue) {
        Object o = sd.getProperty(name);
        if (o == null) {
            return defaultValue;
        }
        return type.isAssignableFrom(o.getClass()) ? (T)o : null;
    }

    public static String[] getPublishableInterfaces(ServiceEndpointDescription sd,
                                                    ServiceReference sref) {
        Object publishProperty =
            sd.getProperty(DistributionConstants.REMOTE_INTERFACES);
        String[] actualInterfaces =
            (String[])sref.getProperty(org.osgi.framework.Constants.OBJECTCLASS);
        String[] publishableInterfaces = null;


        if (actualInterfaces != null
            && actualInterfaces.length > 0
            && publishProperty != null) {

            if (INTERFACE_WILDCARD.equals(publishProperty)) {
                // wildcard indicates all interfaces should be published
                //
                publishableInterfaces = actualInterfaces;
            } else {

                String[] requestedInterfaces =
                    publishProperty instanceof String
                    ? tokenize((String)publishProperty, ",")
                    : publishProperty instanceof String[]
                      ? (String[])publishProperty
                      : publishProperty instanceof Collection
                      ? (String[])((Collection)publishProperty).toArray(
                            new String[((Collection)publishProperty).size()])
                         : null;

                ArrayList<String> publishableList = new ArrayList<String>();

                for (int i = 0; requestedInterfaces != null
                                && i < requestedInterfaces.length; i++) {
                    if (contains(actualInterfaces, requestedInterfaces[i])) {
                        publishableList.add(requestedInterfaces[i]);
                    } else {
                        // simply ignore non-exposed interfaces
                        //
                        LOG.warning("ignoring publish interface, "
                                    + requestedInterfaces[i]
                                    + ", not exposed by service");
                    }
                }

                if (publishableList.size() > 0) {
                    publishableInterfaces =
                        publishableList.toArray(new String[publishableList.size()]);
                }
            }
        }

        return publishableInterfaces;
    }

    private static String[] tokenize(String str, String delim) {
        StringTokenizer tokenizer = new StringTokenizer(str, delim);
        String[] tokens = new String[tokenizer.countTokens()];
        for (int i = 0; tokenizer.hasMoreTokens(); i++) {
            tokens[i] = tokenizer.nextToken();
        }
        return tokens;
    }

    private static boolean contains(String[] list, String member) {
        boolean found = false;
        for (int i = 0; i < list.length && !found; i++) {
            found = member.equals(list[i]);
        }
        return found;
    }
}
TOP

Related Classes of org.apache.cxf.dosgi.dsw.OsgiUtils

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.