Home » apache-openjpa-1.1.0-source » org.apache.openjpa.lib » conf » [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.openjpa.lib.conf;
   20   
   21   import java.io.File;
   22   import java.security.AccessController;
   23   import java.security.PrivilegedActionException;
   24   import java.util.ArrayList;
   25   import java.util.Arrays;
   26   import java.util.Collection;
   27   import java.util.Iterator;
   28   import java.util.List;
   29   import java.util.Map;
   30   import java.util.MissingResourceException;
   31   import java.util.Properties;
   32   import java.util.TreeSet;
   33   import javax.naming.Context;
   34   import javax.naming.InitialContext;
   35   import javax.naming.NamingException;
   36   
   37   import org.apache.commons.lang.StringUtils;
   38   import org.apache.commons.lang.exception.NestableRuntimeException;
   39   import org.apache.openjpa.lib.log.Log;
   40   import org.apache.openjpa.lib.util.J2DoPrivHelper;
   41   import org.apache.openjpa.lib.util.Localizer;
   42   import org.apache.openjpa.lib.util.Options;
   43   import org.apache.openjpa.lib.util.ParseException;
   44   import org.apache.openjpa.lib.util.StringDistance;
   45   import java.util.concurrent.ConcurrentHashMap;
   46   import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
   47   import serp.util.Strings;
   48   
   49   /**
   50    * Utility methods dealing with configuration.
   51    *
   52    * @author Abe White
   53    * @nojavadoc
   54    */
   55   public class Configurations {
   56   
   57       private static final Localizer _loc = Localizer.forPackage
   58           (Configurations.class);
   59       
   60       private static final ConcurrentReferenceHashMap _loaders = new
   61           ConcurrentReferenceHashMap(ConcurrentReferenceHashMap.WEAK, 
   62                   ConcurrentReferenceHashMap.HARD);
   63   
   64       private static final Object NULL_LOADER = "null-loader";
   65   
   66       /**
   67        * Return the class name from the given plugin string, or null if none.
   68        */
   69       public static String getClassName(String plugin) {
   70           return getPluginComponent(plugin, true);
   71       }
   72   
   73       /**
   74        * Return the properties part of the given plugin string, or null if none.
   75        */
   76       public static String getProperties(String plugin) {
   77           return getPluginComponent(plugin, false);
   78       }
   79   
   80       /**
   81        * Return either the class name or properties string from a plugin string.
   82        */
   83       private static String getPluginComponent(String plugin, boolean clsName) {
   84           if (plugin != null)
   85               plugin = plugin.trim();
   86           if (StringUtils.isEmpty(plugin))
   87               return null;
   88   
   89           int openParen = -1;
   90           if (plugin.charAt(plugin.length() - 1) == ')')
   91               openParen = plugin.indexOf('(');
   92           if (openParen == -1) {
   93               int eq = plugin.indexOf('=');
   94               if (eq == -1)
   95                   return (clsName) ? plugin : null;
   96               return (clsName) ? null : plugin;
   97           }
   98   
   99           // clsName(props) form
  100           if (clsName)
  101               return plugin.substring(0, openParen).trim();
  102           String prop = plugin.substring(openParen + 1,
  103               plugin.length() - 1).trim();
  104           return (prop.length() == 0) ? null : prop;
  105       }
  106   
  107       /**
  108        * Combine the given class name and properties into a plugin string.
  109        */
  110       public static String getPlugin(String clsName, String props) {
  111           if (StringUtils.isEmpty(clsName))
  112               return props;
  113           if (StringUtils.isEmpty(props))
  114               return clsName;
  115           return clsName + "(" + props + ")";
  116       }
  117   
  118       /**
  119        * Return a plugin string that combines the properties of the given plugin
  120        * strings, where properties of <code>override</code> will override the
  121        * same properties of <code>orig</code>.
  122        */
  123       public static String combinePlugins(String orig, String override) {
  124           if (StringUtils.isEmpty(orig))
  125               return override;
  126           if (StringUtils.isEmpty(override))
  127               return orig;
  128   
  129           String origCls = getClassName(orig);
  130           String overrideCls = getClassName(override);
  131           String cls;
  132           if (StringUtils.isEmpty(origCls))
  133               cls = overrideCls;
  134           else if (StringUtils.isEmpty(overrideCls))
  135               cls = origCls;
  136           else if (!origCls.equals(overrideCls))
  137               return override; // completely different plugin
  138           else
  139               cls = origCls;
  140   
  141           String origProps = getProperties(orig);
  142           String overrideProps = getProperties(override);
  143           if (StringUtils.isEmpty(origProps))
  144               return getPlugin(cls, overrideProps);
  145           if (StringUtils.isEmpty(overrideProps))
  146               return getPlugin(cls, origProps);
  147   
  148           Properties props = parseProperties(origProps);
  149           props.putAll(parseProperties(overrideProps));
  150           return getPlugin(cls, serializeProperties(props)); 
  151       }
  152   
  153       /**
  154        * Create the instance with the given class name, using the given
  155        * class loader. No configuration of the instance is performed by
  156        * this method.
  157        */
  158       public static Object newInstance(String clsName, ClassLoader loader) {
  159           return newInstance(clsName, null, null, loader, true);
  160       }
  161   
  162       /**
  163        * Create and configure an instance with the given class name and
  164        * properties.
  165        */
  166       public static Object newInstance(String clsName, Configuration conf,
  167           String props, ClassLoader loader) {
  168           Object obj = newInstance(clsName, null, conf, loader, true);
  169           configureInstance(obj, conf, props);
  170           return obj;
  171       }
  172   
  173       /**
  174        * Helper method used by members of this package to instantiate plugin
  175        * values.
  176        */
  177       static Object newInstance(String clsName, Value val, Configuration conf,
  178           ClassLoader loader, boolean fatal) {
  179           if (StringUtils.isEmpty(clsName))
  180               return null;
  181   
  182           Class cls = null; 
  183   
  184           while (cls == null) {
  185               // can't have a null reference in the map, so use symbolic
  186               // constant as key
  187               Object key = loader == null ? NULL_LOADER : loader;
  188               Map loaderCache = (Map) _loaders.get(key);
  189               if (loaderCache == null) { // We don't have a cache for this loader.
  190                   loaderCache = new ConcurrentHashMap();
  191                   _loaders.put(key, loaderCache);
  192               } else {  // We have a cache for this loader.
  193                   cls = (Class) loaderCache.get(clsName);
  194               }
  195   
  196               if (cls == null) {
  197                   try {
  198                       cls = Strings.toClass(clsName, findDerivedLoader(conf,
  199                               loader));
  200                       loaderCache.put(clsName, cls);
  201                   } catch (RuntimeException re) {
  202                       if (loader != null)  // Try one more time with loader=null
  203                           loader = null;
  204                       else {
  205                           if (val != null)
  206                               re = getCreateException(clsName, val, re);
  207                           if (fatal)
  208                               throw re;
  209                           Log log = (conf == null) ? null : conf
  210                                   .getConfigurationLog();
  211                           if (log != null && log.isErrorEnabled())
  212                               log.error(_loc
  213                                       .get("plugin-creation-exception", val), re);
  214                           return null;
  215                       }
  216                   }
  217               }
  218           }
  219   
  220           try {
  221               return AccessController.doPrivileged(
  222                   J2DoPrivHelper.newInstanceAction(cls));
  223           } catch (Exception e) {
  224               if (e instanceof PrivilegedActionException) {
  225                   e = ((PrivilegedActionException) e).getException();   
  226               }
  227               RuntimeException re = new NestableRuntimeException(_loc.get
  228                   ("obj-create", cls).getMessage(), e);
  229               if (fatal)
  230                   throw re;
  231               Log log = (conf == null) ? null : conf.getConfigurationLog();
  232               if (log != null && log.isErrorEnabled())
  233                   log.error(_loc.get("plugin-creation-exception", val), re);
  234               return null;
  235           }
  236       }
  237   
  238       /**
  239        * Attempt to find a derived loader that delegates to our target loader.
  240        * This allows application loaders that delegate appropriately for known
  241        * classes first crack at class names.
  242        */
  243       private static ClassLoader findDerivedLoader(Configuration conf,
  244           ClassLoader loader) {
  245           // we always prefer the thread loader, because it's the only thing we
  246           // can access that isn't bound to the OpenJPA classloader, unless
  247           // the conf object is of a custom class
  248           ClassLoader ctxLoader = (ClassLoader) AccessController.doPrivileged(
  249               J2DoPrivHelper.getContextClassLoaderAction());
  250           if (loader == null) {
  251               if (ctxLoader != null)
  252                   return ctxLoader;
  253               if (conf != null)
  254                   return (ClassLoader) AccessController.doPrivileged(
  255                       J2DoPrivHelper.getClassLoaderAction(conf.getClass())); 
  256               return Configurations.class.getClassLoader();
  257           }
  258   
  259           for (ClassLoader parent = ctxLoader; parent != null; 
  260               parent = (ClassLoader) AccessController.doPrivileged(
  261                   J2DoPrivHelper.getParentAction(parent))) {
  262               if (parent == loader)
  263                   return ctxLoader;
  264           }
  265           if (conf != null) {
  266               for (ClassLoader parent = (ClassLoader)
  267                   AccessController.doPrivileged(
  268                       J2DoPrivHelper.getClassLoaderAction(conf.getClass())); 
  269                   parent != null; 
  270                   parent = (ClassLoader) AccessController.doPrivileged(
  271                       J2DoPrivHelper.getParentAction(parent))) {
  272                   if (parent == loader)
  273                       return (ClassLoader) AccessController.doPrivileged(
  274                           J2DoPrivHelper.getClassLoaderAction(conf.getClass())); 
  275               }
  276           }
  277           return loader;
  278       }
  279   
  280       /**
  281        * Return a List<String> of all the fully-qualified anchors specified in the
  282        * properties location listed in <code>opts</code>. If no properties
  283        * location is listed in <code>opts</code>, this returns whatever the
  284        * product derivations can find in their default configurations.
  285        * If the properties location specified in <code>opts</code> already
  286        * contains an anchor spec, this returns that anchor. Note that in this
  287        * fully-qualified-input case, the logic involving product derivations
  288        * and resource parsing is short-circuited, so this method
  289        * should not be used as a means to test that a particular anchor is
  290        * defined in a given location by invoking with a fully-qualified anchor.
  291        *
  292        * This does not mutate <code>opts</code>.
  293        *
  294        * @since 1.1.0
  295        */
  296       public static List getFullyQualifiedAnchorsInPropertiesLocation(
  297           Options opts) {
  298           String props = opts.getProperty("properties", "p", null);
  299           if (props != null) {
  300               int anchorPosition = props.indexOf("#");
  301               if (anchorPosition > -1)
  302                   return Arrays.asList(new String[] { props });
  303           }
  304   
  305           return ProductDerivations.getFullyQualifiedAnchorsInPropertiesLocation(
  306               props);
  307       }
  308   
  309       /**
  310        * Set the given {@link Configuration} instance from the command line
  311        * options provided. All property names of the given configuration are
  312        * recognized; additionally, if a <code>properties</code> or
  313        * <code>p</code> argument exists, the resource it
  314        * points to will be loaded and set into the given configuration instance.
  315        * It can point to either a file or a resource name.
  316        */
  317       public static void populateConfiguration(Configuration conf, Options opts) {
  318           String props = opts.removeProperty("properties", "p", null);
  319           ConfigurationProvider provider;
  320           if (!StringUtils.isEmpty(props)) {
  321               String path = props;
  322               String anchor = null;
  323               int idx = path.lastIndexOf('#');
  324               if (idx != -1) {
  325                   if (idx < path.length() - 1)
  326                       anchor = path.substring(idx + 1);
  327                   path = path.substring(0, idx);
  328                   if (path.length() == 0)
  329                       throw new MissingResourceException(_loc.get("anchor-only",
  330                           props).getMessage(), Configurations.class.getName(), 
  331                           props);
  332               }
  333   
  334               File file = new File(path);
  335               if (((Boolean) AccessController.doPrivileged(J2DoPrivHelper
  336                   .isFileAction(file))).booleanValue())
  337                   provider = ProductDerivations.load(file, anchor, null);
  338               else {
  339                   file = new File("META-INF" + File.separatorChar + path);
  340                   if (((Boolean) AccessController.doPrivileged(J2DoPrivHelper
  341                       .isFileAction(file))).booleanValue())
  342                       provider = ProductDerivations.load(file, anchor, null);
  343                   else
  344                       provider = ProductDerivations.load(path, anchor, null);
  345               }
  346               if (provider != null)
  347                   provider.setInto(conf);
  348               else
  349                   throw new MissingResourceException(_loc.get("no-provider",
  350                       props).getMessage(), Configurations.class.getName(), 
  351                       props);
  352           } else {
  353               provider = ProductDerivations.loadDefaults(null);
  354               if (provider != null)
  355                   provider.setInto(conf);
  356           }
  357           opts.setInto(conf);
  358       }
  359   
  360       /**
  361        * Helper method to throw an informative description on instantiation error.
  362        */
  363       private static RuntimeException getCreateException(String clsName,
  364           Value val, Exception e) {
  365           // re-throw the exception with some better information
  366           final String msg;
  367           final Object[] params;
  368   
  369           String alias = val.alias(clsName);
  370           String[] aliases = val.getAliases();
  371           String[] keys;
  372           if (aliases.length == 0)
  373               keys = aliases;
  374           else {
  375               keys = new String[aliases.length / 2];
  376               for (int i = 0; i < aliases.length; i += 2)
  377                   keys[i / 2] = aliases[i];
  378           }
  379   
  380           String closest;
  381           if (keys.length == 0) {
  382               msg = "invalid-plugin";
  383               params = new Object[]{ val.getProperty(), alias, e.toString(), };
  384           } else if ((closest = StringDistance.getClosestLevenshteinDistance
  385               (alias, keys, 0.5f)) == null) {
  386               msg = "invalid-plugin-aliases";
  387               params = new Object[]{
  388                   val.getProperty(), alias, e.toString(),
  389                   new TreeSet(Arrays.asList(keys)), };
  390           } else {
  391               msg = "invalid-plugin-aliases-hint";
  392               params = new Object[]{
  393                   val.getProperty(), alias, e.toString(),
  394                   new TreeSet(Arrays.asList(keys)), closest, };
  395           }
  396           return new ParseException(_loc.get(msg, params), e);
  397       }
  398   
  399       /**
  400        * Configures the given object with the given properties by
  401        * matching the properties string to the object's setter
  402        * methods. The properties string should be in the form
  403        * "prop1=val1, prop2=val2 ...". Does not validate that setter
  404        * methods exist for the properties.
  405        *
  406        * @throws RuntimeException on configuration error
  407        */
  408       public static void configureInstance(Object obj, Configuration conf,
  409           String properties) {
  410           configureInstance(obj, conf, properties, null);
  411       }
  412   
  413       /**
  414        * Configures the given object with the given properties by
  415        * matching the properties string to the object's setter
  416        * methods. The properties string should be in the form
  417        * "prop1=val1, prop2=val2 ...". Validates that setter methods
  418        * exist for the properties.
  419        *
  420        * @throws RuntimeException on configuration error
  421        */
  422       public static void configureInstance(Object obj, Configuration conf,
  423           String properties, String configurationName) {
  424           if (obj == null)
  425               return;
  426   
  427           Properties props = null;
  428           if (!StringUtils.isEmpty(properties))
  429               props = parseProperties(properties);
  430           configureInstance(obj, conf, props, configurationName);
  431       }
  432   
  433       /**
  434        * Configures the given object with the given properties by
  435        * matching the properties string to the object's setter
  436        * methods. Does not validate that setter methods exist for the properties.
  437        *
  438        * @throws RuntimeException on configuration error
  439        */
  440       public static void configureInstance(Object obj, Configuration conf,
  441           Properties properties) {
  442           configureInstance(obj, conf, properties, null);
  443       }
  444   
  445       /**
  446        * Configures the given object with the given properties by
  447        * matching the properties string to the object's setter
  448        * methods. If <code>configurationName</code> is
  449        * non-<code>null</code>, validates that setter methods exist for
  450        * the properties.
  451        *
  452        * @throws RuntimeException on configuration error
  453        */
  454       public static void configureInstance(Object obj, Configuration conf,
  455           Properties properties, String configurationName) {
  456           if (obj == null)
  457               return;
  458   
  459           Options opts;
  460           if (properties instanceof Options)
  461               opts = (Options) properties;
  462           else { 
  463               opts = new Options();
  464               if (properties != null)
  465                   opts.putAll(properties);
  466           }
  467   
  468           Configurable configurable = null;
  469           if (conf != null && obj instanceof Configurable)
  470               configurable = (Configurable) obj;
  471   
  472           if (configurable != null) {
  473               configurable.setConfiguration(conf);
  474               configurable.startConfiguration();
  475           }
  476           Options invalidEntries = opts.setInto(obj);
  477           if (obj instanceof GenericConfigurable)
  478               ((GenericConfigurable) obj).setInto(invalidEntries);
  479   
  480   		if (!invalidEntries.isEmpty() && configurationName != null) {
  481   			Localizer.Message msg = null;
  482   			String first = (String) invalidEntries.keySet().iterator().next();
  483   			if (invalidEntries.keySet().size() == 1 &&
  484   				first.indexOf('.') == -1) {
  485   				// if there's just one misspelling and this is not a
  486   				// path traversal, check for near misses.
  487   				Collection options = findOptionsFor(obj.getClass());
  488   				String close = StringDistance.getClosestLevenshteinDistance
  489   					(first, options, 0.75f);
  490   				if (close != null)
  491   					msg = _loc.get("invalid-config-param-hint", new Object[]{
  492   						configurationName, obj.getClass(), first, close,
  493   						options, });
  494   			}
  495   
  496               if (msg == null) {
  497                   msg = _loc.get("invalid-config-params", new String[]{
  498                       configurationName, obj.getClass().getName(),
  499                       invalidEntries.keySet().toString(),
  500                       findOptionsFor(obj.getClass()).toString(), });
  501               }
  502               throw new ParseException(msg);
  503           }
  504           if (configurable != null)
  505               configurable.endConfiguration();
  506       }
  507   
  508       private static Collection findOptionsFor(Class cls) {
  509           Collection c = Options.findOptionsFor(cls);
  510           
  511           // remove Configurable.setConfiguration() and 
  512           // GenericConfigurable.setInto() from the set, if applicable.
  513           if (Configurable.class.isAssignableFrom(cls))
  514               c.remove("Configuration");
  515           if (GenericConfigurable.class.isAssignableFrom(cls))
  516               c.remove("Into");
  517           
  518           return c;
  519       }
  520   
  521       /**
  522        * Turn a set of properties into a comma-separated string.
  523        */
  524       public static String serializeProperties(Map map) {
  525           if (map == null || map.isEmpty())
  526               return null;
  527   
  528           StringBuffer buf = new StringBuffer();
  529           Map.Entry entry;
  530           String val;
  531           for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) {
  532               entry = (Map.Entry) itr.next();
  533               if (buf.length() > 0)
  534                   buf.append(", ");
  535               buf.append(entry.getKey()).append('=');
  536               val = String.valueOf(entry.getValue());
  537               if (val.indexOf(',') != -1)
  538                   buf.append('"').append(val).append('"');
  539               else
  540                   buf.append(val);
  541           }
  542           return buf.toString();
  543       }
  544   
  545       /**
  546        * Parse a set of properties from a comma-separated string.
  547        */
  548       public static Options parseProperties(String properties) {
  549           Options opts = new Options();
  550           properties = StringUtils.trimToNull(properties);
  551           if (properties == null)
  552               return opts;
  553   
  554           try {
  555               String[] props = Strings.split(properties, ",", 0);
  556               int idx;
  557               char quote;
  558               String prop;
  559               String val;
  560               for (int i = 0; i < props.length; i++) {
  561                   idx = props[i].indexOf('=');
  562                   if (idx == -1) {
  563                       // if the key is not assigned to any value, set the
  564                       // value to the same thing as the key, and continue.
  565                       // This permits GenericConfigurable instances to
  566                       // behave meaningfully. We might consider setting the
  567                       // value to some well-known "value was not set, but
  568                       // key is present" string so that instances getting
  569                       // values injected can differentiate between a mentioned
  570                       // property and one set to a particular value.
  571                       prop = props[i];
  572                       val = prop;
  573                   } else {
  574                       prop = props[i].substring(0, idx).trim();
  575                       val = props[i].substring(idx + 1).trim();
  576                   }
  577   
  578                   // if the value is quoted, read until the end quote
  579                   if (((val.startsWith("\"") && val.endsWith("\""))
  580                       || (val.startsWith("'") && val.endsWith("'")))
  581                       && val.length() > 1)
  582                       val = val.substring(1, val.length() - 1);
  583                   else if (val.startsWith("\"") || val.startsWith("'")) {
  584                       quote = val.charAt(0);
  585                       StringBuffer buf = new StringBuffer(val.substring(1));
  586                       int quotIdx;
  587                       while (++i < props.length) {
  588                           buf.append(",");
  589   
  590                           quotIdx = props[i].indexOf(quote);
  591                           if (quotIdx != -1) {
  592                               buf.append(props[i].substring(0, quotIdx));
  593                               if (quotIdx + 1 < props[i].length())
  594                                   buf.append(props[i].substring(quotIdx + 1));
  595                               break;
  596                           } else
  597                               buf.append(props[i]);
  598                       }
  599                       val = buf.toString();
  600                   }
  601                   opts.put(prop, val);
  602               }
  603               return opts;
  604           } catch (RuntimeException re) {
  605               throw new ParseException(_loc.get("prop-parse", properties), re);
  606           }
  607       }
  608   
  609       /**
  610        * Looks up the given name in JNDI. If the name is null, null is returned.
  611        */
  612       public static Object lookup(String name) {
  613           if (StringUtils.isEmpty(name))
  614               return null;
  615   
  616           Context ctx = null;
  617           try {
  618               ctx = new InitialContext();
  619               return ctx.lookup(name);
  620           } catch (NamingException ne) {
  621               throw new NestableRuntimeException(
  622                   _loc.get("naming-err", name).getMessage(), ne);
  623           } finally {
  624               if (ctx != null)
  625                   try { ctx.close(); } catch (Exception e) {}
  626           }
  627       }
  628   
  629       /**
  630        * Test whether the map contains the given partial key, prefixed with any
  631        * possible configuration prefix.
  632        */
  633       public static boolean containsProperty(String partialKey, Map props) {
  634           if (partialKey == null || props == null || props.isEmpty())
  635               return false;
  636           else
  637               return props.containsKey(
  638                   ProductDerivations.getConfigurationKey(partialKey, props));
  639       }
  640   
  641       /**
  642        * Get the property under the given partial key, prefixed with any possible
  643        * configuration prefix.
  644        */
  645       public static Object getProperty(String partialKey, Map m) {
  646           if (partialKey == null || m == null || m.isEmpty())
  647               return null;
  648           else 
  649               return m.get(ProductDerivations.getConfigurationKey(partialKey, m));
  650       }
  651   
  652       /**
  653        * Remove the property under the given partial key, prefixed with any
  654        * possible configuration prefix.
  655        */
  656       public static Object removeProperty(String partialKey, Map props) {
  657           if (partialKey == null || props == null || props.isEmpty())
  658               return null;
  659           if (containsProperty(partialKey, props))
  660               return props.remove(ProductDerivations.getConfigurationKey(
  661                   partialKey, props));
  662           else
  663               return null;
  664       }
  665   
  666       /**
  667        * Runs <code>runnable</code> against all the anchors in the configuration
  668        * pointed to by <code>opts</code>. Each invocation gets a fresh clone of 
  669        * <code>opts</code> with the <code>properties</code> option set
  670        * appropriately.
  671        *
  672        * @since 1.1.0
  673        */
  674       public static boolean runAgainstAllAnchors(Options opts,
  675           Configurations.Runnable runnable) {
  676           if (opts.containsKey("help") || opts.containsKey("-help")) {
  677               return false;
  678           }
  679           List anchors =
  680               Configurations.getFullyQualifiedAnchorsInPropertiesLocation(opts);
  681   
  682           // We use 'properties' below; get rid of 'p' to avoid conflicts. This
  683           // relies on knowing what getFullyQualifiedAnchorsInPropertiesLocation
  684           // looks for.
  685           if (opts.containsKey("p"))
  686               opts.remove("p");
  687   
  688           boolean ret = true;
  689           if (anchors.size() == 0) {
  690               ret = launchRunnable(opts, runnable);
  691           } else {
  692               for (Iterator iter = anchors.iterator(); iter.hasNext(); ) { 
  693                   Options clonedOptions = (Options) opts.clone();
  694                   clonedOptions.setProperty("properties", iter.next().toString());
  695                   ret &= launchRunnable(clonedOptions, runnable);
  696               }
  697           }
  698           return ret;
  699       }
  700   
  701       private static boolean launchRunnable(Options opts,
  702           Configurations.Runnable runnable) {
  703           boolean ret = true;
  704           try {
  705               ret = runnable.run(opts);
  706           } catch (Exception e) {
  707               if (!(e instanceof RuntimeException))
  708                   throw new RuntimeException(e);
  709               else
  710                   throw (RuntimeException) e;
  711           }
  712           return ret;
  713       }
  714   
  715       public interface Runnable {
  716           public boolean run(Options opts) throws Exception;
  717       }
  718   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa.lib » conf » [javadoc | source]