src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/InstanceResolver.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 418
43240b8b995b
parent 0
373ffda63c9a
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.api.server;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.xml.internal.ws.api.message.Message;
    30 import com.sun.xml.internal.ws.api.message.Packet;
    31 import com.sun.xml.internal.ws.resources.ServerMessages;
    32 import com.sun.xml.internal.ws.resources.WsservletMessages;
    33 import com.sun.xml.internal.ws.server.ServerRtException;
    34 import com.sun.xml.internal.ws.server.SingletonResolver;
    36 import javax.xml.ws.Provider;
    37 import javax.xml.ws.WebServiceContext;
    38 import javax.xml.ws.WebServiceException;
    39 import java.lang.annotation.Annotation;
    40 import java.lang.reflect.InvocationTargetException;
    41 import java.lang.reflect.Method;
    42 import java.util.logging.Level;
    43 import java.util.logging.Logger;
    45 /**
    46  * Determines the instance that serves
    47  * the given request packet.
    48  *
    49  * <p>
    50  * The JAX-WS spec always use a singleton instance
    51  * to serve all the requests, but this hook provides
    52  * a convenient way to route messages to a proper receiver.
    53  *
    54  * <p>
    55  * Externally, an instance of {@link InstanceResolver} is
    56  * associated with {@link WSEndpoint}.
    57  *
    58  * <h2>Possible Uses</h2>
    59  * <p>
    60  * One can use WS-Addressing message properties to
    61  * decide which instance to deliver a message. This
    62  * would be an important building block for a stateful
    63  * web services.
    64  *
    65  * <p>
    66  * One can associate an instance of a service
    67  * with a specific WS-RM session.
    68  *
    69  * @author Kohsuke Kawaguchi
    70  */
    71 public abstract class InstanceResolver<T> {
    72     /**
    73      * Decides which instance of 'T' serves the given request message.
    74      *
    75      * <p>
    76      * This method is called concurrently by multiple threads.
    77      * It is also on a criticail path that affects the performance.
    78      * A good implementation should try to avoid any synchronization,
    79      * and should minimize the amount of work as much as possible.
    80      *
    81      * @param request
    82      *      Always non-null. Represents the request message to be served.
    83      *      The caller may not consume the {@link Message}.
    84      */
    85     public abstract @NotNull T resolve(@NotNull Packet request);
    87     /**
    88      * Called by the default {@link Invoker} after the method call is done.
    89      * This gives {@link InstanceResolver} a chance to do clean up.
    90      *
    91      * <p>
    92      * Alternatively, one could override {@link #createInvoker()} to
    93      * create a custom invoker to do this in more flexible way.
    94      *
    95      * <p>
    96      * The default implementation is a no-op.
    97      *
    98      * @param request
    99      *      The same request packet given to {@link #resolve(Packet)} method.
   100      * @param servant
   101      *      The object returned from the {@link #resolve(Packet)} method.
   102      * @since 2.1.2
   103      */
   104     public void postInvoke(@NotNull Packet request, @NotNull T servant) {
   105     }
   107     /**
   108      * Called by {@link WSEndpoint} when it's set up.
   109      *
   110      * <p>
   111      * This is an opportunity for {@link InstanceResolver}
   112      * to do a endpoint-specific initialization process.
   113      *
   114      * @param wsc
   115      *      The {@link WebServiceContext} instance to be injected
   116      *      to the user instances (assuming {@link InstanceResolver}
   117      */
   118     public void start(@NotNull WSWebServiceContext wsc, @NotNull WSEndpoint endpoint) {
   119         // backward compatibility
   120         start(wsc);
   121     }
   123     /**
   124      * @deprecated
   125      *      Use {@link #start(WSWebServiceContext,WSEndpoint)}.
   126      */
   127     public void start(@NotNull WebServiceContext wsc) {}
   129     /**
   130      * Called by {@link WSEndpoint}
   131      * when {@link WSEndpoint#dispose()} is called.
   132      *
   133      * This allows {@link InstanceResolver} to do final clean up.
   134      *
   135      * <p>
   136      * This method is guaranteed to be only called once by {@link WSEndpoint}.
   137      */
   138     public void dispose() {}
   141     /**
   142      * Creates a {@link InstanceResolver} implementation that always
   143      * returns the specified singleton instance.
   144      */
   145     public static <T> InstanceResolver<T> createSingleton(T singleton) {
   146         assert singleton!=null;
   147         InstanceResolver ir = createFromInstanceResolverAnnotation(singleton.getClass());
   148         if(ir==null)
   149             ir = new SingletonResolver<T>(singleton);
   150         return ir;
   151     }
   153     /**
   154      * @deprecated
   155      *      This is added here because a Glassfish integration happened
   156      *      with this signature. Please do not use this. Will be removed
   157      *      after the next GF integration.
   158      */
   159     public static <T> InstanceResolver<T> createDefault(@NotNull Class<T> clazz, boolean bool) {
   160         return createDefault(clazz);
   161     }
   163     /**
   164      * Creates a default {@link InstanceResolver} that serves the given class.
   165      */
   166     public static <T> InstanceResolver<T> createDefault(@NotNull Class<T> clazz) {
   167         InstanceResolver<T> ir = createFromInstanceResolverAnnotation(clazz);
   168         if(ir==null)
   169             ir = new SingletonResolver<T>(createNewInstance(clazz));
   170         return ir;
   171     }
   173     /**
   174      * Checks for {@link InstanceResolverAnnotation} and creates an instance resolver from it if any.
   175      * Otherwise null.
   176      */
   177     public static <T> InstanceResolver<T> createFromInstanceResolverAnnotation(@NotNull Class<T> clazz) {
   178         for( Annotation a : clazz.getAnnotations() ) {
   179             InstanceResolverAnnotation ira = a.annotationType().getAnnotation(InstanceResolverAnnotation.class);
   180             if(ira==null)   continue;
   181             Class<? extends InstanceResolver> ir = ira.value();
   182             try {
   183                 return ir.getConstructor(Class.class).newInstance(clazz);
   184             } catch (InstantiationException e) {
   185                 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
   186                     ir.getName(),a.annotationType(),clazz.getName()));
   187             } catch (IllegalAccessException e) {
   188                 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
   189                     ir.getName(),a.annotationType(),clazz.getName()));
   190             } catch (InvocationTargetException e) {
   191                 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
   192                     ir.getName(),a.annotationType(),clazz.getName()));
   193             } catch (NoSuchMethodException e) {
   194                 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
   195                     ir.getName(),a.annotationType(),clazz.getName()));
   196             }
   197         }
   199         return null;
   200     }
   202     protected static <T> T createNewInstance(Class<T> cl) {
   203         try {
   204             return cl.newInstance();
   205         } catch (InstantiationException e) {
   206             logger.log(Level.SEVERE, e.getMessage(), e);
   207             throw new ServerRtException(
   208                 WsservletMessages.ERROR_IMPLEMENTOR_FACTORY_NEW_INSTANCE_FAILED(cl));
   209         } catch (IllegalAccessException e) {
   210             logger.log(Level.SEVERE, e.getMessage(), e);
   211             throw new ServerRtException(
   212                 WsservletMessages.ERROR_IMPLEMENTOR_FACTORY_NEW_INSTANCE_FAILED(cl));
   213         }
   214     }
   216     /**
   217      * Wraps this {@link InstanceResolver} into an {@link Invoker}.
   218      */
   219     public @NotNull Invoker createInvoker() {
   220         return new Invoker() {
   221             @Override
   222             public void start(@NotNull WSWebServiceContext wsc, @NotNull WSEndpoint endpoint) {
   223                 InstanceResolver.this.start(wsc,endpoint);
   224             }
   226             @Override
   227             public void dispose() {
   228                 InstanceResolver.this.dispose();
   229             }
   231             @Override
   232             public Object invoke(Packet p, Method m, Object... args) throws InvocationTargetException, IllegalAccessException {
   233                 T t = resolve(p);
   234                 try {
   235                     return MethodUtil.invoke(t, m, args );
   236                 } finally {
   237                     postInvoke(p,t);
   238                 }
   239             }
   241             @Override
   242             public <U> U invokeProvider(@NotNull Packet p, U arg) {
   243                 T t = resolve(p);
   244                 try {
   245                     return ((Provider<U>) t).invoke(arg);
   246                 } finally {
   247                     postInvoke(p,t);
   248                 }
   249             }
   251             public String toString() {
   252                 return "Default Invoker over "+InstanceResolver.this.toString();
   253             }
   254         };
   255     }
   257     private static final Logger logger =
   258         Logger.getLogger(
   259             com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server");
   260 }

mercurial