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

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

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2011, 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.api.server;
    28 import com.sun.xml.internal.ws.server.WSEndpointImpl;
    29 import java.util.HashSet;
    30 import java.util.Set;
    31 import com.sun.org.glassfish.external.amx.AMXGlassfish;
    32 import com.sun.org.glassfish.external.amx.MBeanListener;
    33 import com.sun.org.glassfish.gmbal.ManagedObjectManager;
    35 /**
    36  * The lazy provider is intended to defer Gmbal API calls until there is a JMX connection. The provider is scope
    37  * (environment) aware and behaves accordingly to actual scope. The default behaviour does not defers Gmbal API calls.
    38  *
    39  * There are two kind of method allowing registration of an object as a listener. One is for {@code WSEndpointImpl}
    40  * instances (implementing {@code WSEndpointScopeChangeListener}) and the other is for arbitrary objects
    41  * (implementing {@code DefaultScopeChangeListener}) that want to be notified about scope changes. The distinction is made
    42  * because of the fact that endpoints should be registered first and other objects (e.g. dependants on endpoints) must
    43  * be registered after all the endpoints are processed so no inconsistency is present.
    44  *
    45  * Glassfish:
    46  * {@link WebServicesContainer} is one of two classes for which a {@link ManagedObjectManager} instance (see Gmbal API)
    47  * is created when a webservice application is deployed into the Glassfish. For the purpose of postponing Gmbal API calls
    48  * the {@code WebServicesContainer} extends {@link MBeanListener.CallbackImpl} so it can register itself as a listener of
    49  * {@link AMXGlassfish} and receive a notification about a connection of a JMX client to the Glassfish server (see
    50  * {@code WebServicesContainer#postConstruct} for registration details). The moment the JMX client is connected a notification
    51  * is sent to the listeners of {@code AMXGlassfish}. When this event is received by {@code WebServiceContainer} (see the
    52  * callback method {@code mbeanRegistered}) a {@code ManagedObjectManager} instance is created and no further deferring
    53  * of Gmbal API calls is needed.
    54  *
    55  * Metro/JAX-WS:
    56  * The situation in Metro/JAX-WS is slightly different from the one described above. Metro/JAX-WS can be used as standalone
    57  * libraries (outside of Glassfish) so no notification from the Glassfish server can be expected in this case. This leads
    58  * to a situation when Metro/JAX-WS has to be aware of context in which it is used and acts appropriately. There are 3
    59  * scopes an application using Metro/JAX-WS can be in: {@code STANDALONE}, {@code GLASSFISH_NO_JMX}, {@code GLASSFISH_JMX}
    60  * ({@link LazyMOMProvider#scope}). The default scope is {@code STANDALONE} and all Gmbal API calls are invoked as they
    61  * are requested. The other two scopes are applied only when an application is deployed into a Glassfish server. The
    62  * {@code GLASSFISH_NO_JMX} is set at the moment the application is deployed (see below) and its purpose is to defer Gmbal
    63  * API calls for as long as possible. For some classes e.g. {@code ManagedObjectManager} proxy classes were introduced to
    64  * avoid the necessity of creating the real Gmbal objects but if a method is invoked on these proxies the creation of real
    65  * Gmbal objects is forced even in this scope. The {@code GLASSFISH_JMX} scope is set when a JMX client is connected to
    66  * the Glassfish server and it processes Gmbal API calls without deferring (as if the application was in the
    67  * {@code STANDALONE} scope). The entry point for postponing the Gmbal API calls / creating Gmbal objects in Metro/JAX-WS
    68  * is {@link LazyMOMProvider}. This class is capable of receiving notifications from the Glassfish server
    69  * ({@code LazyMOMProvider.initMOMForScope}) about the scope change and it also spread this information to its listeners.
    70  * The listeners of {@code LazyMOMProvider} are of two kinds: {@link LazyMOMProvider.WSEndpointScopeChangeListener} and
    71  * {@link LazyMOMProvider.DefaultScopeChangeListener}. Extensions of {@link WSEndpoint} (e.g. {@link WSEndpointImpl})
    72  * should implement the {@code LazyMOMProvider.WSEndpointScopeChangeListener} and register themselves as endpoint listeners
    73  * of {@code LazyMOMProvider}. Other classes should implement the latter mentioned interface and register themselves as
    74  * a non-endpoint listener. The differences between these two kind of listeners are described in {@code LazyMOMProvider}
    75  * class comment. An implementation of {@code LazyMOMProvider.DefaultScopeChangeListener} is provided in Metro
    76  * ({@link WSEndpointCollectionBasedMOMListener}). As mentioned above this listener register itself as a non-endpoint
    77  * listener of {@code LazyMOMProvider} ({@code WSEndpointCollectionBasedMOMListener.init}). An instance of this class is
    78  * used in these factories: {@link SessionManager}, {@link NonceManager} and {@link SequenceManagerFactory}.
    79  * {@code SessionManager}, {@code NonceManager}, {@code PersistentSequenceManager} and {@code InVmSequenceManager} also
    80  * (indirectly) implement {@link MOMRegistrationAware} for providing information whether a manager is registered at
    81  * {@code ManagedObjectManager} or not. Registration of a manager at {@code ManagedObjectManager} can be processed directly
    82  * (if {@code WSEndpointCollectionBasedMOMListener.canRegisterAtMOM} returns {@code true}) via
    83  * {@code WSEndpointCollectionBasedMOMListener.registerAtMOM} or is deferred by putting the manager into
    84  * {@code WSEndpointCollectionBasedMOMListener.registrationAwareMap}. Managers stored in for deferred registration are
    85  * processed at the moment the {@code LazyMOMProvider} notifies the {@code WSEndpointCollectionBasedMOMListener} about
    86  * the scope change.
    87  * The mentioned postponing of Gmbal API calls applies only to the server side of the webservice application.
    88  */
    89 public enum LazyMOMProvider {
    91     INSTANCE;
    93     /**
    94      * Possible scopes (environments) in which the provider (and object associated with it) could be in.
    95      * Default scope is STANDALONE - applied during initialization of classes. For now, only possible scope change for a
    96      * object can be in this direction: STANDALONE -> GLASSFISH_NO_JMX -> GLASSFISH_JMX.
    97      */
    98     public static enum Scope {
   100         //** Default scope where lazy flag is not applied and all Gmbal API calls are processed immediately. */
   101         STANDALONE,
   103         /** In this scope almost all Gmbal API call are deferred until a JMX connection to a Glassfish server is created */
   104         GLASSFISH_NO_JMX,
   106         /** Same as STANDALONE. Gmbal API calls are processed immediately. */
   107         GLASSFISH_JMX
   109     }
   111     /**
   112      * Interface for all object that want to be notified about scope change, introducing required methods.
   113      */
   114     public static interface ScopeChangeListener {
   116         void scopeChanged(Scope scope);
   118     }
   120     /**
   121      * Default interface for all object that want to be notified about scope change. This interface should not be
   122      * implemented directly.
   123      */
   124     public static interface DefaultScopeChangeListener extends ScopeChangeListener {
   125     }
   127     /**
   128      * Interface used for distinguishing between a registration of a WSEndpointImpl rather than of other classes.
   129      * Webservice Endpoints should get a notification about scope change sooner than the rest of the registered listeners
   130      * (there is a possibility that other listeners are dependant on Webservice Endpoints).
   131      */
   132     public static interface WSEndpointScopeChangeListener extends ScopeChangeListener {
   133     }
   135     private final Set<WSEndpointScopeChangeListener> endpointsWaitingForMOM = new HashSet<WSEndpointScopeChangeListener>();
   136     private final Set<DefaultScopeChangeListener> listeners = new HashSet<DefaultScopeChangeListener>();
   138     private volatile Scope scope = Scope.STANDALONE;
   140     /**
   141      * Initializes this provider with a given scope. If the given scope is different than the one this provider is
   142      * currently in and the transition between scopes is valid then a event is fired to all registered listeners.
   143      *
   144      * @param scope a scope to initialize this provider with
   145      */
   146     public void initMOMForScope(LazyMOMProvider.Scope scope) {
   147         // cannot go backwards between scopes, for possible scope changes see #Scope
   148         if ((this.scope == Scope.GLASSFISH_JMX)
   149                 || (scope == Scope.STANDALONE && (this.scope == Scope.GLASSFISH_JMX || this.scope == Scope.GLASSFISH_NO_JMX))
   150                 || this.scope == scope) {
   151             return;
   152         }
   154         this.scope = scope;
   156         fireScopeChanged();
   157     }
   159     /**
   160      * Notifies the registered listeners about the scope change.
   161      */
   162     private void fireScopeChanged() {
   163         for (ScopeChangeListener wsEndpoint : endpointsWaitingForMOM) {
   164             wsEndpoint.scopeChanged(this.scope);
   165         }
   167         for (ScopeChangeListener listener : listeners) {
   168             listener.scopeChanged(this.scope);
   169         }
   170     }
   172     /**
   173      * Registers the given object as a listener.
   174      *
   175      * @param listener a listener to be registered
   176      */
   177     public void registerListener(DefaultScopeChangeListener listener) {
   178         listeners.add(listener);
   180         if (!isProviderInDefaultScope()) {
   181             listener.scopeChanged(this.scope);
   182         }
   183     }
   185     /**
   186      * Returns {@code true} if this provider is in the default scope.
   187      *
   188      * @return {@code true} if this provider is in the default scope,
   189      *          {@code false} otherwise
   190      */
   191     private boolean isProviderInDefaultScope() {
   192         return this.scope == Scope.STANDALONE;
   193     }
   195     public Scope getScope() {
   196         return scope;
   197     }
   199     /**
   200      * Registers a Webservice Endpoint as a listener.
   201      * Webservice Endpoints should rather register through this method than through LazyMOMProvider#registerListener
   202      * because generally they need to be notified sooner than arbitrary listener (i.e. object that is dependant on
   203      * Webservice Endpoint)
   204      *
   205      * @param wsEndpoint a Webservice Endpoint to be registered
   206      */
   207     public void registerEndpoint(WSEndpointScopeChangeListener wsEndpoint) {
   208         endpointsWaitingForMOM.add(wsEndpoint);
   210         if (!isProviderInDefaultScope()) {
   211             wsEndpoint.scopeChanged(this.scope);
   212         }
   213     }
   215     /**
   216      * Unregisters a Webservice Endpoint from the list of listeners.
   217      *
   218      * @param wsEndpoint a Webservice Endpoint to be unregistered
   219      */
   220     public void unregisterEndpoint(WSEndpointScopeChangeListener wsEndpoint) {
   221         endpointsWaitingForMOM.remove(wsEndpoint);
   222     }
   224 }

mercurial