1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/PolicyUtils.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,480 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.policy.privateutil; 1.30 + 1.31 +import com.sun.xml.internal.ws.policy.PolicyException; 1.32 +import java.io.Closeable; 1.33 +import java.io.IOException; 1.34 +import java.io.UnsupportedEncodingException; 1.35 +import java.lang.reflect.InvocationTargetException; 1.36 +import java.lang.reflect.Method; 1.37 +import java.net.URL; 1.38 +import java.util.ArrayList; 1.39 +import java.util.Arrays; 1.40 +import java.util.Collection; 1.41 +import java.util.Comparator; 1.42 +import java.util.LinkedList; 1.43 +import java.util.List; 1.44 +import java.util.Queue; 1.45 +import javax.xml.namespace.QName; 1.46 +import javax.xml.stream.XMLStreamException; 1.47 +import javax.xml.stream.XMLStreamReader; 1.48 + 1.49 +/** 1.50 + * This is a wrapper class for various utilities that may be reused within Policy API implementation. 1.51 + * The class is not part of public Policy API. Do not use it from your client code! 1.52 + * 1.53 + * @author Marek Potociar 1.54 + */ 1.55 +public final class PolicyUtils { 1.56 + private PolicyUtils() { } 1.57 + 1.58 + public static class Commons { 1.59 + /** 1.60 + * Method returns the name of the method that is on the {@code methodIndexInStack} 1.61 + * position in the call stack of the current {@link Thread}. 1.62 + * 1.63 + * @param methodIndexInStack index to the call stack to get the method name for. 1.64 + * @return the name of the method that is on the {@code methodIndexInStack} 1.65 + * position in the call stack of the current {@link Thread}. 1.66 + */ 1.67 + public static String getStackMethodName(final int methodIndexInStack) { 1.68 + final String methodName; 1.69 + 1.70 + final StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 1.71 + if (stack.length > methodIndexInStack + 1) { 1.72 + methodName = stack[methodIndexInStack].getMethodName(); 1.73 + } else { 1.74 + methodName = "UNKNOWN METHOD"; 1.75 + } 1.76 + 1.77 + return methodName; 1.78 + } 1.79 + 1.80 + /** 1.81 + * Function returns the name of the caller method for the method executing this 1.82 + * function. 1.83 + * 1.84 + * @return caller method name from the call stack of the current {@link Thread}. 1.85 + */ 1.86 + public static String getCallerMethodName() { 1.87 + String result = getStackMethodName(5); 1.88 + if (result.equals("invoke0")) { 1.89 + // We are likely running on Mac OS X, which returns a shorter stack trace 1.90 + result = getStackMethodName(4); 1.91 + } 1.92 + return result; 1.93 + } 1.94 + } 1.95 + 1.96 + public static class IO { 1.97 + private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyUtils.IO.class); 1.98 + 1.99 + /** 1.100 + * If the {@code resource} is not {@code null}, this method will try to close the 1.101 + * {@code resource} instance and log warning about any unexpected 1.102 + * {@link IOException} that may occur. 1.103 + * 1.104 + * @param resource resource to be closed 1.105 + */ 1.106 + public static void closeResource(Closeable resource) { 1.107 + if (resource != null) { 1.108 + try { 1.109 + resource.close(); 1.110 + } catch (IOException e) { 1.111 + LOGGER.warning(LocalizationMessages.WSP_0023_UNEXPECTED_ERROR_WHILE_CLOSING_RESOURCE(resource.toString()), e); 1.112 + } 1.113 + } 1.114 + } 1.115 + 1.116 + /** 1.117 + * If the {@code reader} is not {@code null}, this method will try to close the 1.118 + * {@code reader} instance and log warning about any unexpected 1.119 + * {@link IOException} that may occur. 1.120 + * 1.121 + * @param reader resource to be closed 1.122 + */ 1.123 + public static void closeResource(XMLStreamReader reader) { 1.124 + if (reader != null) { 1.125 + try { 1.126 + reader.close(); 1.127 + } catch (XMLStreamException e) { 1.128 + LOGGER.warning(LocalizationMessages.WSP_0023_UNEXPECTED_ERROR_WHILE_CLOSING_RESOURCE(reader.toString()), e); 1.129 + } 1.130 + } 1.131 + } 1.132 + } 1.133 + 1.134 + /** 1.135 + * Text utilities wrapper. 1.136 + */ 1.137 + public static class Text { 1.138 + /** 1.139 + * System-specific line separator character retrieved from the Java system property 1.140 + * <code>line.separator</code> 1.141 + */ 1.142 + public final static String NEW_LINE = System.getProperty("line.separator"); 1.143 + 1.144 + /** 1.145 + * Method creates indent string consisting of as many {@code TAB} characters as specified by {@code indentLevel} parameter 1.146 + * 1.147 + * @param indentLevel indentation level 1.148 + * @return indentation string as specified by indentation level 1.149 + * 1.150 + */ 1.151 + public static String createIndent(final int indentLevel) { 1.152 + final char[] charData = new char[indentLevel * 4]; 1.153 + Arrays.fill(charData, ' '); 1.154 + return String.valueOf(charData); 1.155 + } 1.156 + } 1.157 + 1.158 + public static class Comparison { 1.159 + /** 1.160 + * The comparator comapres QName objects according to their publicly accessible attributes, in the following 1.161 + * order of attributes: 1.162 + * 1.163 + * 1. namespace (not null String) 1.164 + * 2. local name (not null String) 1.165 + */ 1.166 + public static final Comparator<QName> QNAME_COMPARATOR = new Comparator<QName>() { 1.167 + public int compare(final QName qn1, final QName qn2) { 1.168 + if (qn1 == qn2 || qn1.equals(qn2)) { 1.169 + return 0; 1.170 + } 1.171 + 1.172 + int result; 1.173 + 1.174 + result = qn1.getNamespaceURI().compareTo(qn2.getNamespaceURI()); 1.175 + if (result != 0) { 1.176 + return result; 1.177 + } 1.178 + 1.179 + return qn1.getLocalPart().compareTo(qn2.getLocalPart()); 1.180 + } 1.181 + }; 1.182 + 1.183 + /** 1.184 + * Compares two boolean values in the following way: {@code false < true} 1.185 + * 1.186 + * @return {@code -1} if {@code b1 < b2}, {@code 0} if {@code b1 == b2}, {@code 1} if {@code b1 > b2} 1.187 + */ 1.188 + public static int compareBoolean(final boolean b1, final boolean b2) { 1.189 + final int i1 = (b1) ? 1 : 0; 1.190 + final int i2 = (b2) ? 1 : 0; 1.191 + 1.192 + return i1 - i2; 1.193 + } 1.194 + 1.195 + /** 1.196 + * Compares two String values, that may possibly be null in the following way: {@code null < "string value"} 1.197 + * 1.198 + * @return {@code -1} if {@code s1 < s2}, {@code 0} if {@code s1 == s2}, {@code 1} if {@code s1 > s2} 1.199 + */ 1.200 + public static int compareNullableStrings(final String s1, final String s2) { 1.201 + return ((s1 == null) ? ((s2 == null) ? 0 : -1) : ((s2 == null) ? 1 : s1.compareTo(s2))); 1.202 + } 1.203 + } 1.204 + 1.205 + public static class Collections { 1.206 + /** 1.207 + * TODO javadocs 1.208 + * 1.209 + * @param initialBase the combination base that will be present in each combination. May be {@code null} or empty. 1.210 + * @param options options that should be combined. May be {@code null} or empty. 1.211 + * @param ignoreEmptyOption flag identifies whether empty options should be ignored or whether the method should halt 1.212 + * processing and return {@code null} when an empty option is encountered 1.213 + * @return TODO 1.214 + */ 1.215 + 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) { 1.216 + List<Collection<E>> combinations = null; 1.217 + if (options == null || options.isEmpty()) { 1.218 + // no combination creation needed 1.219 + if (initialBase != null) { 1.220 + combinations = new ArrayList<Collection<E>>(1); 1.221 + combinations.add(new ArrayList<E>(initialBase)); 1.222 + } 1.223 + return combinations; 1.224 + } 1.225 + 1.226 + // creating defensive and modifiable copy of the base 1.227 + final Collection<E> base = new LinkedList<E>(); 1.228 + if (initialBase != null && !initialBase.isEmpty()) { 1.229 + base.addAll(initialBase); 1.230 + } 1.231 + /** 1.232 + * now we iterate over all options and build up an option processing queue: 1.233 + * 1. if ignoreEmptyOption flag is not set and we found an empty option, we are going to stop processing and return null. Otherwise we 1.234 + * ignore the empty option. 1.235 + * 2. if the option has one child only, we add the child directly to the base. 1.236 + * 3. if there are more children in examined node, we add it to the queue for further processing and precoumpute the final size of 1.237 + * resulting collection of combinations. 1.238 + */ 1.239 + int finalCombinationsSize = 1; 1.240 + final Queue<T> optionProcessingQueue = new LinkedList<T>(); 1.241 + for (T option : options) { 1.242 + final int optionSize = option.size(); 1.243 + 1.244 + if (optionSize == 0) { 1.245 + if (!ignoreEmptyOption) { 1.246 + return null; 1.247 + } 1.248 + } else if (optionSize == 1) { 1.249 + base.addAll(option); 1.250 + } else { 1.251 + optionProcessingQueue.offer(option); 1.252 + finalCombinationsSize *= optionSize; 1.253 + } 1.254 + } 1.255 + 1.256 + // creating final combinations 1.257 + combinations = new ArrayList<Collection<E>>(finalCombinationsSize); 1.258 + combinations.add(base); 1.259 + if (finalCombinationsSize > 1) { 1.260 + T processedOption; 1.261 + while ((processedOption = optionProcessingQueue.poll()) != null) { 1.262 + final int actualSemiCombinationCollectionSize = combinations.size(); 1.263 + final int newSemiCombinationCollectionSize = actualSemiCombinationCollectionSize * processedOption.size(); 1.264 + 1.265 + int semiCombinationIndex = 0; 1.266 + for (E optionElement : processedOption) { 1.267 + for (int i = 0; i < actualSemiCombinationCollectionSize; i++) { 1.268 + final Collection<E> semiCombination = combinations.get(semiCombinationIndex); // unfinished combination 1.269 + 1.270 + if (semiCombinationIndex + actualSemiCombinationCollectionSize < newSemiCombinationCollectionSize) { 1.271 + // this is not the last optionElement => we create a new combination copy for the next child 1.272 + combinations.add(new LinkedList<E>(semiCombination)); 1.273 + } 1.274 + 1.275 + semiCombination.add(optionElement); 1.276 + semiCombinationIndex++; 1.277 + } 1.278 + } 1.279 + } 1.280 + } 1.281 + return combinations; 1.282 + } 1.283 + } 1.284 + 1.285 + /** 1.286 + * Reflection utilities wrapper 1.287 + */ 1.288 + static class Reflection { 1.289 + private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyUtils.Reflection.class); 1.290 + 1.291 + /** 1.292 + * Reflectively invokes specified method on the specified target 1.293 + */ 1.294 + static <T> T invoke(final Object target, final String methodName, 1.295 + final Class<T> resultClass, final Object... parameters) throws RuntimePolicyUtilsException { 1.296 + Class[] parameterTypes; 1.297 + if (parameters != null && parameters.length > 0) { 1.298 + parameterTypes = new Class[parameters.length]; 1.299 + int i = 0; 1.300 + for (Object parameter : parameters) { 1.301 + parameterTypes[i++] = parameter.getClass(); 1.302 + } 1.303 + } else { 1.304 + parameterTypes = null; 1.305 + } 1.306 + 1.307 + return invoke(target, methodName, resultClass, parameters, parameterTypes); 1.308 + } 1.309 + 1.310 + /** 1.311 + * Reflectively invokes specified method on the specified target 1.312 + */ 1.313 + public static <T> T invoke(final Object target, final String methodName, final Class<T> resultClass, 1.314 + final Object[] parameters, final Class[] parameterTypes) throws RuntimePolicyUtilsException { 1.315 + try { 1.316 + final Method method = target.getClass().getMethod(methodName, parameterTypes); 1.317 + final Object result = MethodUtil.invoke(target, method,parameters); 1.318 + 1.319 + return resultClass.cast(result); 1.320 + } catch (IllegalArgumentException e) { 1.321 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e)); 1.322 + } catch (InvocationTargetException e) { 1.323 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e)); 1.324 + } catch (IllegalAccessException e) { 1.325 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e.getCause())); 1.326 + } catch (SecurityException e) { 1.327 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e)); 1.328 + } catch (NoSuchMethodException e) { 1.329 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(createExceptionMessage(target, parameters, methodName), e)); 1.330 + } 1.331 + } 1.332 + 1.333 + private static String createExceptionMessage(final Object target, final Object[] parameters, final String methodName) { 1.334 + return LocalizationMessages.WSP_0061_METHOD_INVOCATION_FAILED(target.getClass().getName(), methodName, 1.335 + parameters == null ? null : Arrays.asList(parameters).toString()); 1.336 + } 1.337 + } 1.338 + 1.339 + public static class ConfigFile { 1.340 + /** 1.341 + * Generates a config file resource name from provided config file identifier. 1.342 + * The generated file name can be transformed into a URL instance using 1.343 + * {@link #loadFromContext(String, Object)} or {@link #loadFromClasspath(String)} 1.344 + * method. 1.345 + * 1.346 + * @param configFileIdentifier the string used to generate the config file URL that will be parsed. Each WSIT config 1.347 + * file is in form of <code>wsit-<i>{configFileIdentifier}</i>.xml</code>. Must not be {@code null}. 1.348 + * @return generated config file resource name 1.349 + * @throw PolicyException If configFileIdentifier is null. 1.350 + */ 1.351 + public static String generateFullName(final String configFileIdentifier) throws PolicyException { 1.352 + if (configFileIdentifier != null) { 1.353 + final StringBuffer buffer = new StringBuffer("wsit-"); 1.354 + buffer.append(configFileIdentifier).append(".xml"); 1.355 + return buffer.toString(); 1.356 + } else { 1.357 + throw new PolicyException(LocalizationMessages.WSP_0080_IMPLEMENTATION_EXPECTED_NOT_NULL()); 1.358 + } 1.359 + } 1.360 + 1.361 + /** 1.362 + * Returns a URL pointing to the given config file. The file name is 1.363 + * looked up as a resource from a ServletContext. 1.364 + * 1.365 + * May return null if the file can not be found. 1.366 + * 1.367 + * @param configFileName The name of the file resource 1.368 + * @param context A ServletContext object. May not be null. 1.369 + */ 1.370 + public static URL loadFromContext(final String configFileName, final Object context) { 1.371 + return Reflection.invoke(context, "getResource", URL.class, configFileName); 1.372 + } 1.373 + 1.374 + /** 1.375 + * Returns a URL pointing to the given config file. The file is looked up as 1.376 + * a resource on the classpath. 1.377 + * 1.378 + * May return null if the file can not be found. 1.379 + * 1.380 + * @param configFileName the name of the file resource. May not be {@code null}. 1.381 + */ 1.382 + public static URL loadFromClasspath(final String configFileName) { 1.383 + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); 1.384 + if (cl == null) { 1.385 + return ClassLoader.getSystemResource(configFileName); 1.386 + } else { 1.387 + return cl.getResource(configFileName); 1.388 + } 1.389 + } 1.390 + } 1.391 + 1.392 + /** 1.393 + * Wrapper for ServiceFinder class which is not part of the Java SE yet. 1.394 + */ 1.395 + public static class ServiceProvider { 1.396 + /** 1.397 + * Locates and incrementally instantiates the available providers of a 1.398 + * given service using the given class loader. 1.399 + * <p/> 1.400 + * <p> This method transforms the name of the given service class into a 1.401 + * provider-configuration filename as described above and then uses the 1.402 + * <tt>getResources</tt> method of the given class loader to find all 1.403 + * available files with that name. These files are then read and parsed to 1.404 + * produce a list of provider-class names. Eventually each provider class is 1.405 + * instantiated and array of those instances is returned. 1.406 + * <p/> 1.407 + * <p> Because it is possible for extensions to be installed into a running 1.408 + * Java virtual machine, this method may return different results each time 1.409 + * it is invoked. <p> 1.410 + * 1.411 + * @param serviceClass The service's abstract service class. Must not be {@code null}. 1.412 + * @param loader The class loader to be used to load provider-configuration files 1.413 + * and instantiate provider classes, or <tt>null</tt> if the system 1.414 + * class loader (or, failing that the bootstrap class loader) is to 1.415 + * be used 1.416 + * @throws NullPointerException in case {@code service} input parameter is {@code null}. 1.417 + * @throws ServiceConfigurationError If a provider-configuration file violates the specified format 1.418 + * or names a provider class that cannot be found and instantiated 1.419 + * @see #load(Class) 1.420 + */ 1.421 + public static <T> T[] load(final Class<T> serviceClass, final ClassLoader loader) { 1.422 + return ServiceFinder.find(serviceClass, loader).toArray(); 1.423 + } 1.424 + 1.425 + /** 1.426 + * Locates and incrementally instantiates the available providers of a 1.427 + * given service using the context class loader. This convenience method 1.428 + * is equivalent to 1.429 + * <p/> 1.430 + * <pre> 1.431 + * ClassLoader cl = Thread.currentThread().getContextClassLoader(); 1.432 + * return PolicyUtils.ServiceProvider.load(service, cl); 1.433 + * </pre> 1.434 + * 1.435 + * @param serviceClass The service's abstract service class. Must not be {@code null}. 1.436 + * 1.437 + * @throws NullPointerException in case {@code service} input parameter is {@code null}. 1.438 + * @throws ServiceConfigurationError If a provider-configuration file violates the specified format 1.439 + * or names a provider class that cannot be found and instantiated 1.440 + * @see #load(Class, ClassLoader) 1.441 + */ 1.442 + public static <T> T[] load(final Class<T> serviceClass) { 1.443 + return ServiceFinder.find(serviceClass).toArray(); 1.444 + } 1.445 + } 1.446 + 1.447 + public static class Rfc2396 { 1.448 + 1.449 + private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyUtils.Reflection.class); 1.450 + 1.451 + // converts "hello%20world" into "hello world" 1.452 + public static String unquote(final String quoted) { 1.453 + if (null == quoted) { 1.454 + return null; 1.455 + } 1.456 + final byte[] unquoted = new byte[quoted.length()]; // result cannot be longer than original string 1.457 + int newLength = 0; 1.458 + char c; 1.459 + int hi, lo; 1.460 + for (int i=0; i < quoted.length(); i++) { // iterarate over all chars in the input 1.461 + c = quoted.charAt(i); 1.462 + if ('%' == c) { // next escape sequence found 1.463 + if ((i + 2) >= quoted.length()) { 1.464 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(LocalizationMessages.WSP_0079_ERROR_WHILE_RFC_2396_UNESCAPING(quoted)), false); 1.465 + } 1.466 + hi = Character.digit(quoted.charAt(++i), 16); 1.467 + lo = Character.digit(quoted.charAt(++i), 16); 1.468 + if ((0 > hi) || (0 > lo)) { 1.469 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(LocalizationMessages.WSP_0079_ERROR_WHILE_RFC_2396_UNESCAPING(quoted)), false); 1.470 + } 1.471 + unquoted[newLength++] = (byte) (hi * 16 + lo); 1.472 + } else { // regular character found 1.473 + unquoted[newLength++] = (byte) c; 1.474 + } 1.475 + } 1.476 + try { 1.477 + return new String(unquoted, 0, newLength, "utf-8"); 1.478 + } catch (UnsupportedEncodingException uee) { 1.479 + throw LOGGER.logSevereException(new RuntimePolicyUtilsException(LocalizationMessages.WSP_0079_ERROR_WHILE_RFC_2396_UNESCAPING(quoted), uee)); 1.480 + } 1.481 + } 1.482 + } 1.483 +}