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