Java tutorial
/** * 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.List; import java.util.Map; import java.util.StringTokenizer; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.cxf.dosgi.dsw.decorator.ServiceDecorator; import org.apache.cxf.dosgi.dsw.qos.IntentMap; import org.apache.cxf.dosgi.dsw.service.RemoteServiceAdminCore; import org.apache.cxf.ws.policy.spring.PolicyNamespaceHandler; 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.packageadmin.ExportedPackage; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.service.remoteserviceadmin.EndpointDescription; import org.springframework.context.ApplicationContext; import org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext; public final class OsgiUtils { // TODO: cleanup old code fragments !!! 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()) { // userProperties.put(key, sref.getProperty(key)); // } // List<ServiceEndpointDescription> srefs = getRemoteReferences(sref.getBundle(), names, userProperties, // matchAllNames); // setAdditionalProperties(sref, userProperties); // // 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 = new HashMap<String, Object>(userProperties); // addProperties(remoteProps, 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(), // Constants.EXPORTED_INTERFACES, // Constants.EXPORTED_INTERFACES_OLD, // Constants.RS_PROVIDER_GLOBAL_PROP_KEY, // Constants.RS_PROVIDER_EXPECTED_PROP_KEY, // Constants.RS_PROVIDER_PROP_KEY); // // 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... excludes) { // Collection<String> exList = Arrays.asList(excludes); // // Map<String, Object> pruned = new HashMap<String, Object>(); // for (Object key : properties.keySet()) { // if (exList.contains(key)) { // // 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 void setAdditionalProperties(ServiceReference sref, Map<String, Object> props) { // BundleContext bc = sref.getBundle().getBundleContext(); // ServiceReference[] refs; // try { // refs = bc.getServiceReferences(ServiceDecorator.class.getName(), null); // } catch (InvalidSyntaxException e) { // // should never happen, filter is null // return; // } // if (refs == null) { // return; // } // // for (ServiceReference ref : refs) { // Object svc = bc.getService(ref); // if (svc instanceof ServiceDecorator) { // ((ServiceDecorator)svc).decorate(sref, props); // } // } // } // 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>(); // addProperties(props, elements); // return props; // } // private static void addProperties(Map<String, Object> props, List<Element> elements) { // 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); // } // } // } // 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 { // switch to cxf bundle classloader for spring Thread.currentThread().setContextClassLoader(PolicyNamespaceHandler.class.getClassLoader()); LOG.fine("Loading Intent map from " + springIntentLocations); System.out.println("Loading Intent map from " + springIntentLocations); OsgiBundleXmlApplicationContext ctx = new OsgiBundleXmlApplicationContext( springIntentLocations.toArray(new String[] {})); ctx.setPublishContextAsService(false); ctx.setBundleContext(bundleContext); ctx.refresh(); LOG.fine("application context: " + ctx); System.out.println("application context: " + ctx); IntentMap im = (IntentMap) ctx.getBean("intentMap"); LOG.fine("retrieved intent map: " + im); System.out.println("retrieved intent map: " + im); // switch back Thread.currentThread().setContextClassLoader(RemoteServiceAdminCore.class.getClassLoader()); 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(Map sd, String name) { Object value = sd.get(name); return toBoolean(value); } public static boolean toBoolean(Object value) { return value instanceof Boolean && ((Boolean) value).booleanValue() || value instanceof String && Boolean.parseBoolean((String) value); } @SuppressWarnings("unchecked") public static Collection<String> getMultiValueProperty(Object property) { if (property == null) { return null; } if (property instanceof Collection) { return (Collection<String>) property; } else if (property instanceof String[]) { return Arrays.asList((String[]) property); } else { return Collections.singleton(property.toString()); } } public static String getProperty(EndpointDescription sd, String name) { Object o = sd.getProperties().get(name); if (o != null && o instanceof String) { return (String) o; } return null; } public static String getProperty(Map dict, String name) { Object o = dict.get(name); if (o != null && o instanceof String) { return (String) o; } return 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) { // Collection<String> publishProperty = getMultiValueProperty(sd // .getProperty(Constants.EXPORTED_INTERFACES)); // if (publishProperty == null) { // publishProperty = getMultiValueProperty(sd.getProperty(Constants.EXPORTED_INTERFACES_OLD)); // } // // String[] actualInterfaces = (String[])sref.getProperty(org.osgi.framework.Constants.OBJECTCLASS); // String[] publishableInterfaces = null; // // if (actualInterfaces != null && actualInterfaces.length > 0 && publishProperty != null) { // // if (publishProperty.size() == 1 && INTERFACE_WILDCARD.equals(publishProperty.iterator().next())) { // // wildcard indicates all interfaces should be published // // // publishableInterfaces = actualInterfaces; // } else { // String[] requestedInterfaces; // if (publishProperty.size() == 0) { // requestedInterfaces = null; // } else if (publishProperty.size() == 1) { // requestedInterfaces = tokenize(publishProperty.iterator().next(), ","); // } else { // requestedInterfaces = publishProperty.toArray(new String[publishProperty.size()]); // } // // 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; // } /** * Tries to retrieve the version of iClass via the PackageAdmin * * @param iClass - The interface for which the version should be found * @param bc - any valid BundleContext * @return the version of the interface or "0.0.0" if no version information could be found or an error * occurred during the retrieval */ public static String getVersion(Class<?> iClass, BundleContext bc) { ServiceReference paRef = bc.getServiceReference(PackageAdmin.class.getName()); if (paRef != null) { PackageAdmin pa = (PackageAdmin) bc.getService(paRef); Bundle b = pa.getBundle(iClass); if (b == null) { LOG.info("Unable to find interface version for interface " + iClass.getName() + ". Falling back to 0.0.0"); return "0.0.0"; } LOG.finest("Interface source bundle: " + b.getSymbolicName()); ExportedPackage[] ep = pa.getExportedPackages(b); LOG.finest("Exported Packages of the source bundle: " + ep); String pack = iClass.getPackage().getName(); LOG.finest("Looking for Package: " + pack); for (ExportedPackage p : ep) { if (pack.equals(p.getName())) { LOG.fine("found package -> Version: " + p.getVersion()); return p.getVersion().toString(); } } } else { LOG.severe("Was unable to obtain the package admin service -> can't resolve interface versions"); } LOG.info("Unable to find interface version for interface " + iClass.getName() + ". Falling back to 0.0.0"); return "0.0.0"; } public static String getUUID(BundleContext bc) { synchronized ("org.osgi.framework.uuid") { String uuid = bc.getProperty("org.osgi.framework.uuid"); if (uuid == null) { uuid = UUID.randomUUID().toString(); System.setProperty("org.osgi.framework.uuid", uuid); } return uuid; } } }