src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/PolicyUtils.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 637
9c07ef4934dd
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.policy.privateutil;
    28 import com.sun.xml.internal.ws.policy.PolicyException;
    29 import java.io.Closeable;
    30 import java.io.IOException;
    31 import java.io.UnsupportedEncodingException;
    32 import java.lang.reflect.InvocationTargetException;
    33 import java.lang.reflect.Method;
    34 import java.net.URL;
    35 import java.util.ArrayList;
    36 import java.util.Arrays;
    37 import java.util.Collection;
    38 import java.util.Comparator;
    39 import java.util.LinkedList;
    40 import java.util.List;
    41 import java.util.Queue;
    42 import javax.xml.namespace.QName;
    43 import javax.xml.stream.XMLStreamException;
    44 import javax.xml.stream.XMLStreamReader;
    46 /**
    47  * This is a wrapper class for various utilities that may be reused within Policy API implementation.
    48  * The class is not part of public Policy API. Do not use it from your client code!
    49  *
    50  * @author Marek Potociar
    51  */
    52 public final class PolicyUtils {
    53     private PolicyUtils() { }
    55     public static class Commons {
    56         /**
    57          * Method returns the name of the method that is on the {@code methodIndexInStack}
    58          * position in the call stack of the current {@link Thread}.
    59          *
    60          * @param methodIndexInStack index to the call stack to get the method name for.
    61          * @return the name of the method that is on the {@code methodIndexInStack}
    62          *         position in the call stack of the current {@link Thread}.
    63          */
    64         public static String getStackMethodName(final int methodIndexInStack) {
    65             final String methodName;
    67             final StackTraceElement[] stack = Thread.currentThread().getStackTrace();
    68             if (stack.length > methodIndexInStack + 1) {
    69                 methodName = stack[methodIndexInStack].getMethodName();
    70             } else {
    71                 methodName = "UNKNOWN METHOD";
    72             }
    74             return methodName;
    75         }
    77         /**
    78          * Function returns the name of the caller method for the method executing this
    79          * function.
    80          *
    81          * @return caller method name from the call stack of the current {@link Thread}.
    82          */
    83         public static String getCallerMethodName() {
    84             String result = getStackMethodName(5);
    85             if (result.equals("invoke0")) {
    86                 // We are likely running on Mac OS X, which returns a shorter stack trace
    87                 result = getStackMethodName(4);
    88             }
    89             return result;
    90         }
    91     }
    93     public static class IO {
    94         private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyUtils.IO.class);
    96         /**
    97          * If the {@code resource} is not {@code null}, this method will try to close the
    98          * {@code resource} instance and log warning about any unexpected
    99          * {@link IOException} that may occur.
   100          *
   101          * @param resource resource to be closed
   102          */
   103         public static void closeResource(Closeable resource) {
   104             if (resource != null) {
   105                 try {
   106                     resource.close();
   107                 } catch (IOException e) {
   108                     LOGGER.warning(LocalizationMessages.WSP_0023_UNEXPECTED_ERROR_WHILE_CLOSING_RESOURCE(resource.toString()), e);
   109                 }
   110             }
   111         }
   113         /**
   114          * If the {@code reader} is not {@code null}, this method will try to close the
   115          * {@code reader} instance and log warning about any unexpected
   116          * {@link IOException} that may occur.
   117          *
   118          * @param reader resource to be closed
   119          */
   120         public static void closeResource(XMLStreamReader reader) {
   121             if (reader != null) {
   122                 try {
   123                     reader.close();
   124                 } catch (XMLStreamException e) {
   125                     LOGGER.warning(LocalizationMessages.WSP_0023_UNEXPECTED_ERROR_WHILE_CLOSING_RESOURCE(reader.toString()), e);
   126                 }
   127             }
   128         }
   129     }
   131     /**
   132      * Text utilities wrapper.
   133      */
   134     public static class Text {
   135         /**
   136          * System-specific line separator character retrieved from the Java system property
   137          * <code>line.separator</code>
   138          */
   139         public final static String NEW_LINE = System.getProperty("line.separator");
   141         /**
   142          * Method creates indent string consisting of as many {@code TAB} characters as specified by {@code indentLevel} parameter
   143          *
   144          * @param indentLevel indentation level
   145          * @return indentation string as specified by indentation level
   146          *
   147          */
   148         public static String createIndent(final int indentLevel) {
   149             final char[] charData = new char[indentLevel * 4];
   150             Arrays.fill(charData, ' ');
   151             return String.valueOf(charData);
   152         }
   153     }
   155     public static class Comparison {
   156         /**
   157          * The comparator comapres QName objects according to their publicly accessible attributes, in the following
   158          * order of attributes:
   159          *
   160          * 1. namespace (not null String)
   161          * 2. local name (not null String)
   162          */
   163         public static final Comparator<QName> QNAME_COMPARATOR = new Comparator<QName>() {
   164             public int compare(final QName qn1, final QName qn2) {
   165                 if (qn1 == qn2 || qn1.equals(qn2)) {
   166                     return 0;
   167                 }
   169                 int result;
   171                 result = qn1.getNamespaceURI().compareTo(qn2.getNamespaceURI());
   172                 if (result != 0) {
   173                     return result;
   174                 }
   176                 return qn1.getLocalPart().compareTo(qn2.getLocalPart());
   177             }
   178         };
   180         /**
   181          * Compares two boolean values in the following way: {@code false < true}
   182          *
   183          * @return {@code -1} if {@code b1 < b2}, {@code 0} if {@code b1 == b2}, {@code 1} if {@code b1 > b2}
   184          */
   185         public static int compareBoolean(final boolean b1, final boolean b2) {
   186             final int i1 = (b1) ? 1 : 0;
   187             final int i2 = (b2) ? 1 : 0;
   189             return i1 - i2;
   190         }
   192         /**
   193          * Compares two String values, that may possibly be null in the following way: {@code null < "string value"}
   194          *
   195          * @return {@code -1} if {@code s1 < s2}, {@code 0} if {@code s1 == s2}, {@code 1} if {@code s1 > s2}
   196          */
   197         public static int compareNullableStrings(final String s1, final String s2) {
   198             return ((s1 == null) ? ((s2 == null) ? 0 : -1) : ((s2 == null) ? 1 : s1.compareTo(s2)));
   199         }
   200     }
   202     public static class Collections {
   203         /**
   204          * TODO javadocs
   205          *
   206          * @param initialBase the combination base that will be present in each combination. May be {@code null} or empty.
   207          * @param options options that should be combined. May be {@code null} or empty.
   208          * @param ignoreEmptyOption flag identifies whether empty options should be ignored or whether the method should halt
   209          *        processing and return {@code null} when an empty option is encountered
   210          * @return TODO
   211          */
   212         public static <E, T extends Collection<? extends E>, U extends Collection<? extends E>> Collection<Collection<E>> combine(final U initialBase, final Collection<T> options, final boolean ignoreEmptyOption) {
   213             List<Collection<E>> combinations = null;
   214             if (options == null || options.isEmpty()) {
   215                 // no combination creation needed
   216                 if (initialBase != null) {
   217                     combinations = new ArrayList<Collection<E>>(1);
   218                     combinations.add(new ArrayList<E>(initialBase));
   219                 }
   220                 return combinations;
   221             }
   223             // creating defensive and modifiable copy of the base
   224             final Collection<E> base = new LinkedList<E>();
   225             if (initialBase != null && !initialBase.isEmpty()) {
   226                 base.addAll(initialBase);
   227             }
   228             /**
   229              * now we iterate over all options and build up an option processing queue:
   230              *   1. if ignoreEmptyOption flag is not set and we found an empty option, we are going to stop processing and return null. Otherwise we
   231              *      ignore the empty option.
   232              *   2. if the option has one child only, we add the child directly to the base.
   233              *   3. if there are more children in examined node, we add it to the queue for further processing and precoumpute the final size of
   234              *      resulting collection of combinations.
   235              */
   236             int finalCombinationsSize = 1;
   237             final Queue<T> optionProcessingQueue = new LinkedList<T>();
   238             for (T option : options) {
   239                 final int optionSize =  option.size();
   241                 if (optionSize == 0) {
   242                     if (!ignoreEmptyOption) {
   243                         return null;
   244                     }
   245                 } else if (optionSize == 1) {
   246                     base.addAll(option);
   247                 } else {
   248                     optionProcessingQueue.offer(option);
   249                     finalCombinationsSize *= optionSize;
   250                 }
   251             }
   253             // creating final combinations
   254             combinations = new ArrayList<Collection<E>>(finalCombinationsSize);
   255             combinations.add(base);
   256             if (finalCombinationsSize > 1) {
   257                 T processedOption;
   258                 while ((processedOption = optionProcessingQueue.poll()) != null) {
   259                     final int actualSemiCombinationCollectionSize = combinations.size();
   260                     final int newSemiCombinationCollectionSize = actualSemiCombinationCollectionSize * processedOption.size();
   262                     int semiCombinationIndex = 0;
   263                     for (E optionElement : processedOption) {
   264                         for (int i = 0; i < actualSemiCombinationCollectionSize; i++) {
   265                             final Collection<E> semiCombination = combinations.get(semiCombinationIndex); // unfinished combination
   267                             if (semiCombinationIndex + actualSemiCombinationCollectionSize < newSemiCombinationCollectionSize) {
   268                                 // this is not the last optionElement => we create a new combination copy for the next child
   269                                 combinations.add(new LinkedList<E>(semiCombination));
   270                             }
   272                             semiCombination.add(optionElement);
   273                             semiCombinationIndex++;
   274                         }
   275                     }
   276                 }
   277             }
   278             return combinations;
   279         }
   280     }
   282     /**
   283      * Reflection utilities wrapper
   284      */
   285     static class Reflection {
   286         private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyUtils.Reflection.class);
   288         /**
   289          * Reflectively invokes specified method on the specified target
   290          */
   291         static <T> T invoke(final Object target, final String methodName,
   292                 final Class<T> resultClass, final Object... parameters) throws RuntimePolicyUtilsException {
   293             Class[] parameterTypes;
   294             if (parameters != null && parameters.length > 0) {
   295                 parameterTypes = new Class[parameters.length];
   296                 int i = 0;
   297                 for (Object parameter : parameters) {
   298                     parameterTypes[i++] = parameter.getClass();
   299                 }
   300             } else {
   301                 parameterTypes = null;
   302             }
   304             return invoke(target, methodName, resultClass, parameters, parameterTypes);
   305         }
   307         /**
   308          * Reflectively invokes specified method on the specified target
   309          */
   310         public static <T> T invoke(final Object target, final String methodName, final Class<T> resultClass,
   311                 final Object[] parameters, final Class[] parameterTypes) throws RuntimePolicyUtilsException {
   312             try {
   313                 final Method method = target.getClass().getMethod(methodName, parameterTypes);
   314                 final Object result = MethodUtil.invoke(target, method,parameters);
   316                 return resultClass.cast(result);
   317             } catch (IllegalArgumentException e) {
   318                 throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e));
   319             } catch (InvocationTargetException e) {
   320                 throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e));
   321             } catch (IllegalAccessException e) {
   322                 throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e.getCause()));
   323             } catch (SecurityException e) {
   324                 throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e));
   325             } catch (NoSuchMethodException e) {
   326                 throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e));
   327             }
   328         }
   330         private static String createExceptionMessage(final Object target, final Object[] parameters, final String methodName) {
   331             return LocalizationMessages.WSP_0061_METHOD_INVOCATION_FAILED(target.getClass().getName(), methodName,
   332                     parameters == null ? null : Arrays.asList(parameters).toString());
   333         }
   334     }
   336     public static class ConfigFile {
   337         /**
   338          * Generates a config file resource name from provided config file identifier.
   339          * The generated file name can be transformed into a URL instance using
   340          * {@link #loadFromContext(String, Object)} or {@link #loadFromClasspath(String)}
   341          * method.
   342          *
   343          * @param configFileIdentifier the string used to generate the config file URL that will be parsed. Each WSIT config
   344          *        file is in form of <code>wsit-<i>{configFileIdentifier}</i>.xml</code>. Must not be {@code null}.
   345          * @return generated config file resource name
   346          * @throw PolicyException If configFileIdentifier is null.
   347          */
   348         public static String generateFullName(final String configFileIdentifier) throws PolicyException {
   349             if (configFileIdentifier != null) {
   350                 final StringBuffer buffer = new StringBuffer("wsit-");
   351                 buffer.append(configFileIdentifier).append(".xml");
   352                 return buffer.toString();
   353             } else {
   354                 throw new PolicyException(LocalizationMessages.WSP_0080_IMPLEMENTATION_EXPECTED_NOT_NULL());
   355             }
   356         }
   358         /**
   359          * Returns a URL pointing to the given config file. The file name is
   360          * looked up as a resource from a ServletContext.
   361          *
   362          * May return null if the file can not be found.
   363          *
   364          * @param configFileName The name of the file resource
   365          * @param context A ServletContext object. May not be null.
   366          */
   367         public static URL loadFromContext(final String configFileName, final Object context) {
   368             return Reflection.invoke(context, "getResource", URL.class, configFileName);
   369         }
   371         /**
   372          * Returns a URL pointing to the given config file. The file is looked up as
   373          * a resource on the classpath.
   374          *
   375          * May return null if the file can not be found.
   376          *
   377          * @param configFileName the name of the file resource. May not be {@code null}.
   378          */
   379         public static URL loadFromClasspath(final String configFileName) {
   380             final ClassLoader cl = Thread.currentThread().getContextClassLoader();
   381             if (cl == null) {
   382                 return ClassLoader.getSystemResource(configFileName);
   383             } else {
   384                 return cl.getResource(configFileName);
   385             }
   386         }
   387     }
   389     /**
   390      * Wrapper for ServiceFinder class which is not part of the Java SE yet.
   391      */
   392     public static class ServiceProvider {
   393         /**
   394          * Locates and incrementally instantiates the available providers of a
   395          * given service using the given class loader.
   396          * <p/>
   397          * <p> This method transforms the name of the given service class into a
   398          * provider-configuration filename as described above and then uses the
   399          * <tt>getResources</tt> method of the given class loader to find all
   400          * available files with that name.  These files are then read and parsed to
   401          * produce a list of provider-class names. Eventually each provider class is
   402          * instantiated and array of those instances is returned.
   403          * <p/>
   404          * <p> Because it is possible for extensions to be installed into a running
   405          * Java virtual machine, this method may return different results each time
   406          * it is invoked. <p>
   407          *
   408          * @param serviceClass The service's abstract service class. Must not be {@code null}.
   409          * @param loader  The class loader to be used to load provider-configuration files
   410          *                and instantiate provider classes, or <tt>null</tt> if the system
   411          *                class loader (or, failing that the bootstrap class loader) is to
   412          *                be used
   413          * @throws NullPointerException in case {@code service} input parameter is {@code null}.
   414          * @throws ServiceConfigurationError If a provider-configuration file violates the specified format
   415          *                                   or names a provider class that cannot be found and instantiated
   416          * @see #load(Class)
   417          */
   418         public static <T> T[] load(final Class<T> serviceClass, final ClassLoader loader) {
   419             return ServiceFinder.find(serviceClass, loader).toArray();
   420         }
   422         /**
   423          * Locates and incrementally instantiates the available providers of a
   424          * given service using the context class loader.  This convenience method
   425          * is equivalent to
   426          * <p/>
   427          * <pre>
   428          *   ClassLoader cl = Thread.currentThread().getContextClassLoader();
   429          *   return PolicyUtils.ServiceProvider.load(service, cl);
   430          * </pre>
   431          *
   432          * @param serviceClass The service's abstract service class. Must not be {@code null}.
   433          *
   434          * @throws NullPointerException in case {@code service} input parameter is {@code null}.
   435          * @throws ServiceConfigurationError If a provider-configuration file violates the specified format
   436          *                                   or names a provider class that cannot be found and instantiated
   437          * @see #load(Class, ClassLoader)
   438          */
   439         public static <T> T[] load(final Class<T> serviceClass) {
   440             return ServiceFinder.find(serviceClass).toArray();
   441         }
   442     }
   444     public static class Rfc2396 {
   446         private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyUtils.Reflection.class);
   448         // converts "hello%20world" into "hello world"
   449         public static String unquote(final String quoted) {
   450             if (null == quoted) {
   451                 return null;
   452             }
   453             final byte[] unquoted = new byte[quoted.length()]; // result cannot be longer than original string
   454             int newLength = 0;
   455             char c;
   456             int hi, lo;
   457             for (int i=0; i < quoted.length(); i++) {    // iterarate over all chars in the input
   458                 c = quoted.charAt(i);
   459                 if ('%' == c) {                         // next escape sequence found
   460                     if ((i + 2) >= quoted.length()) {
   461                         throw LOGGER.logSevereException(new RuntimePolicyUtilsException(LocalizationMessages.WSP_0079_ERROR_WHILE_RFC_2396_UNESCAPING(quoted)), false);
   462                     }
   463                     hi = Character.digit(quoted.charAt(++i), 16);
   464                     lo = Character.digit(quoted.charAt(++i), 16);
   465                     if ((0 > hi) || (0 > lo)) {
   466                         throw LOGGER.logSevereException(new RuntimePolicyUtilsException(LocalizationMessages.WSP_0079_ERROR_WHILE_RFC_2396_UNESCAPING(quoted)), false);
   467                     }
   468                     unquoted[newLength++] = (byte) (hi * 16 + lo);
   469                 } else { // regular character found
   470                     unquoted[newLength++] = (byte) c;
   471                 }
   472             }
   473             try {
   474                 return new String(unquoted, 0, newLength, "utf-8");
   475             } catch (UnsupportedEncodingException uee) {
   476                 throw LOGGER.logSevereException(new RuntimePolicyUtilsException(LocalizationMessages.WSP_0079_ERROR_WHILE_RFC_2396_UNESCAPING(quoted), uee));
   477             }
   478         }
   479     }
   480 }

mercurial