src/share/jaxws_classes/com/sun/xml/internal/ws/util/InjectionPlan.java

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

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2012, 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.util;
    28 import java.lang.reflect.Field;
    29 import java.lang.reflect.InvocationTargetException;
    30 import java.lang.reflect.Method;
    31 import java.lang.reflect.Modifier;
    32 import java.security.AccessController;
    33 import java.security.PrivilegedAction;
    34 import java.util.ArrayList;
    35 import java.util.Collection;
    36 import java.util.List;
    37 import java.util.concurrent.Callable;
    39 import javax.annotation.Resource;
    40 import javax.xml.ws.WebServiceException;
    42 /**
    43  * Encapsulates which field/method the injection is done, and performs the
    44  * injection.
    45  */
    46 public abstract class InjectionPlan<T, R> {
    47     /**
    48      * Perform injection
    49      *
    50      * @param instance
    51      *            Instance
    52      * @param resource
    53      *            Resource
    54      */
    55     public abstract void inject(T instance, R resource);
    57     /**
    58      * Perform injection, but resource is only generated if injection is
    59      * necessary.
    60      *
    61      * @param instance
    62      * @param resource
    63      */
    64     public void inject(T instance, Callable<R> resource) {
    65         try {
    66             inject(instance, resource.call());
    67         } catch(Exception e) {
    68             throw new WebServiceException(e);
    69         }
    70     }
    72     /*
    73      * Injects to a field.
    74      */
    75     public static class FieldInjectionPlan<T, R> extends
    76             InjectionPlan<T, R> {
    77         private final Field field;
    79         public FieldInjectionPlan(Field field) {
    80             this.field = field;
    81         }
    83         public void inject(final T instance, final R resource) {
    84             AccessController.doPrivileged(new PrivilegedAction<Object>() {
    85                 public Object run() {
    86                     try {
    87                         if (!field.isAccessible()) {
    88                             field.setAccessible(true);
    89                         }
    90                         field.set(instance, resource);
    91                         return null;
    92                     } catch (IllegalAccessException e) {
    93                         throw new WebServiceException(e);
    94                     }
    95                 }
    96             });
    97         }
    98     }
   100     /*
   101      * Injects to a method.
   102      */
   103     public static class MethodInjectionPlan<T, R> extends
   104             InjectionPlan<T, R> {
   105         private final Method method;
   107         public MethodInjectionPlan(Method method) {
   108             this.method = method;
   109         }
   111         public void inject(T instance, R resource) {
   112             invokeMethod(method, instance, resource);
   113         }
   114     }
   116     /*
   117      * Helper for invoking a method with elevated privilege.
   118      */
   119     private static void invokeMethod(final Method method, final Object instance, final Object... args) {
   120         if(method==null)    return;
   121         AccessController.doPrivileged(new PrivilegedAction<Void>() {
   122             public Void run() {
   123                 try {
   124                     if (!method.isAccessible()) {
   125                         method.setAccessible(true);
   126                     }
   127                     method.invoke(instance,args);
   128                 } catch (IllegalAccessException e) {
   129                     throw new WebServiceException(e);
   130                 } catch (InvocationTargetException e) {
   131                     throw new WebServiceException(e);
   132                 }
   133                 return null;
   134             }
   135         });
   136     }
   138     /*
   139      * Combines multiple {@link InjectionPlan}s into one.
   140      */
   141     private static class Compositor<T, R> extends InjectionPlan<T, R> {
   142         private final Collection<InjectionPlan<T, R>> children;
   144         public Compositor(Collection<InjectionPlan<T, R>> children) {
   145             this.children = children;
   146         }
   148         public void inject(T instance, R res) {
   149             for (InjectionPlan<T, R> plan : children)
   150                 plan.inject(instance, res);
   151         }
   153         public void inject(T instance, Callable<R> resource) {
   154             if (!children.isEmpty()) {
   155                 super.inject(instance, resource);
   156             }
   157         }
   158     }
   160     /*
   161      * Creates an {@link InjectionPlan} that injects the given resource type to the given class.
   162      *
   163      * @param isStatic
   164      *      Only look for static field/method
   165      *
   166      */
   167     public static <T,R>
   168     InjectionPlan<T,R> buildInjectionPlan(Class<? extends T> clazz, Class<R> resourceType, boolean isStatic) {
   169         List<InjectionPlan<T,R>> plan = new ArrayList<InjectionPlan<T,R>>();
   171         Class<?> cl = clazz;
   172         while(cl != Object.class) {
   173             for(Field field: cl.getDeclaredFields()) {
   174                 Resource resource = field.getAnnotation(Resource.class);
   175                 if (resource != null) {
   176                     if(isInjectionPoint(resource, field.getType(),
   177                         "Incorrect type for field"+field.getName(),
   178                         resourceType)) {
   180                         if(isStatic && !Modifier.isStatic(field.getModifiers()))
   181                             throw new WebServiceException("Static resource "+resourceType+" cannot be injected to non-static "+field);
   183                         plan.add(new FieldInjectionPlan<T,R>(field));
   184                     }
   185                 }
   186             }
   187             cl = cl.getSuperclass();
   188         }
   190         cl = clazz;
   191         while(cl != Object.class) {
   192             for(Method method : cl.getDeclaredMethods()) {
   193                 Resource resource = method.getAnnotation(Resource.class);
   194                 if (resource != null) {
   195                     Class[] paramTypes = method.getParameterTypes();
   196                     if (paramTypes.length != 1)
   197                         throw new WebServiceException("Incorrect no of arguments for method "+method);
   198                     if(isInjectionPoint(resource,paramTypes[0],
   199                         "Incorrect argument types for method"+method.getName(),
   200                         resourceType)) {
   202                         if(isStatic && !Modifier.isStatic(method.getModifiers()))
   203                             throw new WebServiceException("Static resource "+resourceType+" cannot be injected to non-static "+method);
   205                         plan.add(new MethodInjectionPlan<T,R>(method));
   206                     }
   207                 }
   208             }
   209             cl = cl.getSuperclass();
   210         }
   212         return new Compositor<T,R>(plan);
   213     }
   215     /*
   216      * Returns true if the combination of {@link Resource} and the field/method type
   217      * are consistent for {@link WebServiceContext} injection.
   218      */
   219     private static boolean isInjectionPoint(Resource resource, Class fieldType, String errorMessage, Class resourceType ) {
   220         Class t = resource.type();
   221         if (t.equals(Object.class)) {
   222             return fieldType.equals(resourceType);
   223         } else if (t.equals(resourceType)) {
   224             if (fieldType.isAssignableFrom(resourceType)) {
   225                 return true;
   226             } else {
   227                 // type compatibility error
   228                 throw new WebServiceException(errorMessage);
   229             }
   230         }
   231         return false;
   232     }
   233 }

mercurial