Save This Page
Home » org.apache.sling.commons.osgi-2.0.6-source-release » org.apache.sling.commons.osgi » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    *   http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   package org.apache.sling.commons.osgi;
   20   
   21   import java.util.ArrayList;
   22   import java.util.Collection;
   23   import java.util.Dictionary;
   24   import java.util.Hashtable;
   25   import java.util.List;
   26   import java.util.Map;
   27   
   28   import org.osgi.framework.Bundle;
   29   import org.osgi.framework.Constants;
   30   import org.osgi.framework.ServiceReference;
   31   import org.osgi.service.event.Event;
   32   import org.osgi.service.event.EventConstants;
   33   
   34   /**
   35    * The <code>OsgiUtil</code> is a utility class providing some usefull utility
   36    * methods.
   37    */
   38   public class OsgiUtil {
   39   
   40       /**
   41        * Returns the boolean value of the parameter or the
   42        * <code>defaultValue</code> if the parameter is <code>null</code>.
   43        * If the parameter is not a <code>Boolean</code> it is converted
   44        * by calling <code>Boolean.valueOf</code> on the string value of the
   45        * object.
   46        * @param propValue the property value or <code>null</code>
   47        * @param defaultValue the default boolean value
   48        */
   49       public static boolean toBoolean(Object propValue, boolean defaultValue) {
   50           propValue = toObject(propValue);
   51           if (propValue instanceof Boolean) {
   52               return (Boolean) propValue;
   53           } else if (propValue != null) {
   54               return Boolean.valueOf(String.valueOf(propValue));
   55           }
   56   
   57           return defaultValue;
   58       }
   59   
   60       /**
   61        * Returns the parameter as a string or the
   62        * <code>defaultValue</code> if the parameter is <code>null</code>.
   63        * @param propValue the property value or <code>null</code>
   64        * @param defaultValue the default string value
   65        */
   66       public static String toString(Object propValue, String defaultValue) {
   67           propValue = toObject(propValue);
   68           return (propValue != null) ? propValue.toString() : defaultValue;
   69       }
   70   
   71       /**
   72        * Returns the parameter as a long or the
   73        * <code>defaultValue</code> if the parameter is <code>null</code> or if
   74        * the parameter is not a <code>Long</code> and cannot be converted to
   75        * a <code>Long</code> from the parameter's string value.
   76        * @param propValue the property value or <code>null</code>
   77        * @param defaultValue the default long value
   78        */
   79       public static long toLong(Object propValue, long defaultValue) {
   80           propValue = toObject(propValue);
   81           if (propValue instanceof Long) {
   82               return (Long) propValue;
   83           } else if (propValue != null) {
   84               try {
   85                   return Long.valueOf(String.valueOf(propValue));
   86               } catch (NumberFormatException nfe) {
   87                   // don't care, fall through to default value
   88               }
   89           }
   90   
   91           return defaultValue;
   92       }
   93   
   94       /**
   95        * Returns the parameter as an integer or the
   96        * <code>defaultValue</code> if the parameter is <code>null</code> or if
   97        * the parameter is not an <code>Integer</code> and cannot be converted to
   98        * an <code>Integer</code> from the parameter's string value.
   99        * @param propValue the property value or <code>null</code>
  100        * @param defaultValue the default integer value
  101        */
  102       public static int toInteger(Object propValue, int defaultValue) {
  103           propValue = toObject(propValue);
  104           if (propValue instanceof Integer) {
  105               return (Integer) propValue;
  106           } else if (propValue != null) {
  107               try {
  108                   return Integer.valueOf(String.valueOf(propValue));
  109               } catch (NumberFormatException nfe) {
  110                   // don't care, fall through to default value
  111               }
  112           }
  113   
  114           return defaultValue;
  115       }
  116   
  117       /**
  118        * Returns the parameter as a double or the
  119        * <code>defaultValue</code> if the parameter is <code>null</code> or if
  120        * the parameter is not a <code>Double</code> and cannot be converted to
  121        * a <code>Double</code> from the parameter's string value.
  122        * @param propValue the property value or <code>null</code>
  123        * @param defaultValue the default double value
  124        *
  125        * @deprecated since 2.0.4, use {@link #toDouble(Object, double)} instead
  126        */
  127       @Deprecated
  128       public static double getProperty(Object propValue, double defaultValue) {
  129           return toDouble(propValue, defaultValue);
  130       }
  131   
  132       /**
  133        * Returns the parameter as a double or the
  134        * <code>defaultValue</code> if the parameter is <code>null</code> or if
  135        * the parameter is not a <code>Double</code> and cannot be converted to
  136        * a <code>Double</code> from the parameter's string value.
  137        * @param propValue the property value or <code>null</code>
  138        * @param defaultValue the default double value
  139        *
  140        * @since 2.0.4
  141        */
  142       public static double toDouble(Object propValue, double defaultValue) {
  143           propValue = toObject(propValue);
  144           if (propValue instanceof Double) {
  145               return (Double) propValue;
  146           } else if (propValue != null) {
  147               try {
  148                   return Double.valueOf(String.valueOf(propValue));
  149               } catch (NumberFormatException nfe) {
  150                   // don't care, fall through to default value
  151               }
  152           }
  153   
  154           return defaultValue;
  155       }
  156   
  157       /**
  158        * Returns the parameter as a single value. If the
  159        * parameter is neither an array nor a <code>java.util.Collection</code> the
  160        * parameter is returned unmodified. If the parameter is a non-empty array,
  161        * the first array element is returned. If the property is a non-empty
  162        * <code>java.util.Collection</code>, the first collection element is returned.
  163        * Otherwise <code>null</code> is returned.
  164        * @param propValue the parameter to convert.
  165        */
  166       public static Object toObject(Object propValue) {
  167           if (propValue == null) {
  168               return null;
  169           } else if (propValue.getClass().isArray()) {
  170               Object[] prop = (Object[]) propValue;
  171               return prop.length > 0 ? prop[0] : null;
  172           } else if (propValue instanceof Collection<?>) {
  173               Collection<?> prop = (Collection<?>) propValue;
  174               return prop.isEmpty() ? null : prop.iterator().next();
  175           } else {
  176               return propValue;
  177           }
  178       }
  179   
  180       /**
  181        * Returns the parameter as an array of Strings. If
  182        * the parameter is a scalar value its string value is returned as a single
  183        * element array. If the parameter is an array, the elements are converted to
  184        * String objects and returned as an array. If the parameter is a collection, the
  185        * collection elements are converted to String objects and returned as an array.
  186        * Otherwise (if the parameter is <code>null</code>) <code>null</code> is
  187        * returned.
  188        * @param propValue The object to convert.
  189        */
  190       public static String[] toStringArray(Object propValue) {
  191           return toStringArray(propValue, null);
  192       }
  193   
  194       /**
  195        * Returns the parameter as an array of Strings. If
  196        * the parameter is a scalar value its string value is returned as a single
  197        * element array. If the parameter is an array, the elements are converted to
  198        * String objects and returned as an array. If the parameter is a collection, the
  199        * collection elements are converted to String objects and returned as an array.
  200        * Otherwise (if the property is <code>null</code>) a provided default value is
  201        * returned.
  202        * @since 2.0.4
  203        * @param propValue The object to convert.
  204        * @param defaultArray The default array to return.
  205        */
  206       public static String[] toStringArray(Object propValue, String[] defaultArray) {
  207           if (propValue == null) {
  208               // no value at all
  209               return defaultArray;
  210   
  211           } else if (propValue instanceof String) {
  212               // single string
  213               return new String[] { (String) propValue };
  214   
  215           } else if (propValue instanceof String[]) {
  216               // String[]
  217               return (String[]) propValue;
  218   
  219           } else if (propValue.getClass().isArray()) {
  220               // other array
  221               Object[] valueArray = (Object[]) propValue;
  222               List<String> values = new ArrayList<String>(valueArray.length);
  223               for (Object value : valueArray) {
  224                   if (value != null) {
  225                       values.add(value.toString());
  226                   }
  227               }
  228               return values.toArray(new String[values.size()]);
  229   
  230           } else if (propValue instanceof Collection<?>) {
  231               // collection
  232               Collection<?> valueCollection = (Collection<?>) propValue;
  233               List<String> valueList = new ArrayList<String>(valueCollection.size());
  234               for (Object value : valueCollection) {
  235                   if (value != null) {
  236                       valueList.add(value.toString());
  237                   }
  238               }
  239               return valueList.toArray(new String[valueList.size()]);
  240           }
  241   
  242           return defaultArray;
  243       }
  244   
  245       /**
  246        * Create an osgi event with the given topic and properties.
  247        * If a bundle parameter is provided the symbolic name is added
  248        * as a property.
  249        * If a service parameter is provided, information about the service
  250        * is added to the properties.
  251        * @param sourceBundle Optional source bundle
  252        * @param sourceService Optional source service
  253        * @param topic The event topic.
  254        * @param props A non-null map of properties for the event.
  255        * @return The OSGi event.
  256        */
  257       public static Event createEvent(Bundle sourceBundle,
  258               ServiceReference sourceService, String topic,
  259               Map<String, Object> props) {
  260   
  261           // get a private copy of the properties
  262           Dictionary<String, Object> table = new Hashtable<String, Object>(props);
  263   
  264           // service information of the provide service reference
  265           if (sourceService != null) {
  266               table.put(EventConstants.SERVICE, sourceService);
  267               table.put(
  268                   EventConstants.SERVICE_ID,
  269                   sourceService.getProperty(org.osgi.framework.Constants.SERVICE_ID));
  270               table.put(
  271                   EventConstants.SERVICE_OBJECTCLASS,
  272                   sourceService.getProperty(org.osgi.framework.Constants.OBJECTCLASS));
  273               if (sourceService.getProperty(org.osgi.framework.Constants.SERVICE_PID) != null) {
  274                   table.put(
  275                       EventConstants.SERVICE_PID,
  276                       sourceService.getProperty(org.osgi.framework.Constants.SERVICE_PID));
  277               }
  278           }
  279   
  280           // source bundle information (if available)
  281           if (sourceBundle != null) {
  282               table.put(EventConstants.BUNDLE_SYMBOLICNAME,
  283                   sourceBundle.getSymbolicName());
  284           }
  285   
  286           // timestamp the event
  287           table.put(EventConstants.TIMESTAMP,
  288               new Long(System.currentTimeMillis()));
  289   
  290           // create the event
  291           return new Event(topic, table);
  292       }
  293   
  294       /**
  295        * Create a comparable object out of the service properties. With the result
  296        * it is possible to compare service properties based on the service ranking
  297        * of a service. Therefore this object acts like {@link ServiceReference#compareTo(Object)}.
  298        * @param props The service properties.
  299        * @return A comparable for the ranking of the service
  300        * @since 2.0.6
  301        */
  302       public static Comparable<Object> getComparableForServiceRanking(final Map<String, Object> props) {
  303           return new ComparableImplementation(props);
  304       }
  305   
  306       private static final class ComparableImplementation implements Comparable<Object> {
  307   
  308           private final Map<String, Object> props;
  309   
  310           private ComparableImplementation(Map<String, Object> props) {
  311               this.props = props;
  312           }
  313   
  314           @SuppressWarnings("unchecked")
  315           public int compareTo(Object reference) {
  316               final Long otherId;
  317               Object otherRankObj;
  318               if ( reference instanceof ServiceReference ) {
  319                   final ServiceReference other = (ServiceReference) reference;
  320                   otherId = (Long) other.getProperty(Constants.SERVICE_ID);
  321                   otherRankObj = other.getProperty(Constants.SERVICE_RANKING);
  322               } else if (reference instanceof Map){
  323                   final Map<String, Object> otherProps = (Map<String, Object>)reference;
  324                   otherId = (Long) otherProps.get(Constants.SERVICE_ID);
  325                   otherRankObj = otherProps.get(Constants.SERVICE_RANKING);
  326               } else {
  327                   final ComparableImplementation other = (ComparableImplementation)reference;
  328                   otherId = (Long) other.props.get(Constants.SERVICE_ID);
  329                   otherRankObj = other.props.get(Constants.SERVICE_RANKING);
  330               }
  331               final Long id = (Long) props.get(Constants.SERVICE_ID);
  332               if (id.equals(otherId)) {
  333                   return 0; // same service
  334               }
  335   
  336               Object rankObj = props.get(Constants.SERVICE_RANKING);
  337   
  338               // If no rank, then spec says it defaults to zero.
  339               rankObj = (rankObj == null) ? new Integer(0) : rankObj;
  340               otherRankObj = (otherRankObj == null) ? new Integer(0) : otherRankObj;
  341   
  342               // If rank is not Integer, then spec says it defaults to zero.
  343               Integer rank = (rankObj instanceof Integer)
  344                   ? (Integer) rankObj : new Integer(0);
  345               Integer otherRank = (otherRankObj instanceof Integer)
  346                   ? (Integer) otherRankObj : new Integer(0);
  347   
  348               // Sort by rank in ascending order.
  349               if (rank.compareTo(otherRank) < 0) {
  350                   return -1; // lower rank
  351               } else if (rank.compareTo(otherRank) > 0) {
  352                   return 1; // higher rank
  353               }
  354   
  355               // If ranks are equal, then sort by service id in descending order.
  356               return (id.compareTo(otherId) < 0) ? 1 : -1;
  357           }
  358   
  359           @Override
  360           public boolean equals(Object obj) {
  361               if ( obj instanceof ComparableImplementation ) {
  362                   return this.props.equals(((ComparableImplementation)obj).props);
  363               }
  364               return false;
  365           }
  366   
  367           @Override
  368           public int hashCode() {
  369               return this.props.hashCode();
  370           }
  371       }
  372   }

Save This Page
Home » org.apache.sling.commons.osgi-2.0.6-source-release » org.apache.sling.commons.osgi » [javadoc | source]