001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.client;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.client.WSPortInfo;
042: import com.sun.xml.ws.binding.BindingImpl;
043: import com.sun.xml.ws.handler.HandlerChainsModel;
044: import com.sun.xml.ws.util.HandlerAnnotationInfo;
045: import com.sun.xml.ws.util.HandlerAnnotationProcessor;
046:
047: import javax.jws.HandlerChain;
048: import javax.xml.ws.Service;
049: import javax.xml.ws.handler.Handler;
050: import javax.xml.ws.handler.HandlerResolver;
051: import javax.xml.ws.handler.PortInfo;
052: import javax.xml.ws.soap.SOAPBinding;
053: import java.util.ArrayList;
054: import java.util.HashMap;
055: import java.util.List;
056: import java.util.Map;
057: import java.util.logging.Level;
058: import java.util.logging.Logger;
059:
060: /**
061: * Used by {@link WSServiceDelegate} to configure {@link BindingImpl}
062: * with handlers. The two mechanisms encapsulated by this abstraction
063: * is {@link HandlerChain} annotaion and {@link HandlerResolver}
064: * interface.
065: *
066: * @author Kohsuke Kawaguchi
067: */
068: abstract class HandlerConfigurator {
069: /**
070: * Configures the given {@link BindingImpl} object by adding handlers to it.
071: */
072: abstract void configureHandlers(@NotNull
073: WSPortInfo port, @NotNull
074: BindingImpl binding);
075:
076: /**
077: * Returns a {@link HandlerResolver}, if this object encapsulates any {@link HandlerResolver}.
078: * Otherwise null.
079: */
080: abstract HandlerResolver getResolver();
081:
082: /**
083: * Configures handlers by calling {@link HandlerResolver}.
084: * <p>
085: * When a null {@link HandlerResolver} is set by the user to
086: * {@link Service#setHandlerResolver(HandlerResolver)}, we'll use this object
087: * with null {@link #resolver}.
088: */
089: static final class HandlerResolverImpl extends HandlerConfigurator {
090: private final @Nullable
091: HandlerResolver resolver;
092:
093: public HandlerResolverImpl(HandlerResolver resolver) {
094: this .resolver = resolver;
095: }
096:
097: void configureHandlers(@NotNull
098: WSPortInfo port, @NotNull
099: BindingImpl binding) {
100: if (resolver != null)
101: binding.setHandlerChain(resolver.getHandlerChain(port));
102: }
103:
104: HandlerResolver getResolver() {
105: return resolver;
106: }
107: }
108:
109: /**
110: * Configures handlers from {@link HandlerChain} annotation.
111: *
112: * <p>
113: * This class is a simple
114: * map of PortInfo objects to handler chains. It is used by a
115: * {@link WSServiceDelegate} object, and can
116: * be replaced by user code with a different class implementing
117: * HandlerResolver. This class is only used on the client side, and
118: * it includes a lot of logging to help when there are issues since
119: * it deals with port names, service names, and bindings. All three
120: * must match when getting a handler chain from the map.
121: *
122: * <p>It is created by the {@link WSServiceDelegate}
123: * class , which uses {@link HandlerAnnotationProcessor} to create
124: * a handler chain and then it sets the chains on this class and they
125: * are put into the map. The ServiceContext uses the map to set handler
126: * chains on bindings when they are created.
127: */
128: static final class AnnotationConfigurator extends
129: HandlerConfigurator {
130: private final HandlerChainsModel handlerModel;
131: private final Map<WSPortInfo, HandlerAnnotationInfo> chainMap = new HashMap<WSPortInfo, HandlerAnnotationInfo>();
132: private static final Logger logger = Logger
133: .getLogger(com.sun.xml.ws.util.Constants.LoggingDomain
134: + ".handler");
135:
136: AnnotationConfigurator(WSServiceDelegate delegate) {
137: handlerModel = HandlerAnnotationProcessor
138: .buildHandlerChainsModel(delegate.getServiceClass());
139: assert handlerModel != null; // this class is suppeod to be called only when there's @HandlerCHain
140: }
141:
142: void configureHandlers(WSPortInfo port, BindingImpl binding) {
143: //Check in cache first
144: HandlerAnnotationInfo chain = chainMap.get(port);
145:
146: if (chain == null) {
147: logGetChain(port);
148: // Put it in cache
149: chain = handlerModel.getHandlersForPortInfo(port);
150: chainMap.put(port, chain);
151: }
152:
153: if (binding instanceof SOAPBinding) {
154: ((SOAPBinding) binding).setRoles(chain.getRoles());
155: }
156:
157: logSetChain(port, chain);
158: binding.setHandlerChain(chain.getHandlers());
159: }
160:
161: HandlerResolver getResolver() {
162: return new HandlerResolver() {
163: public List<Handler> getHandlerChain(PortInfo portInfo) {
164: return new ArrayList<Handler>(handlerModel
165: .getHandlersForPortInfo(portInfo)
166: .getHandlers());
167: }
168: };
169: }
170:
171: // logged at finer level
172: private void logSetChain(WSPortInfo info,
173: HandlerAnnotationInfo chain) {
174: logger.finer("Setting chain of length "
175: + chain.getHandlers().size() + " for port info");
176: logPortInfo(info, Level.FINER);
177: }
178:
179: // logged at fine level
180: private void logGetChain(WSPortInfo info) {
181: logger.fine("No handler chain found for port info:");
182: logPortInfo(info, Level.FINE);
183: logger.fine("Existing handler chains:");
184: if (chainMap.isEmpty()) {
185: logger.fine("none");
186: } else {
187: for (WSPortInfo key : chainMap.keySet()) {
188: logger.fine(chainMap.get(key).getHandlers().size()
189: + " handlers for port info ");
190: logPortInfo(key, Level.FINE);
191: }
192: }
193: }
194:
195: private void logPortInfo(WSPortInfo info, Level level) {
196: logger.log(level, "binding: " + info.getBindingID()
197: + "\nservice: " + info.getServiceName()
198: + "\nport: " + info.getPortName());
199: }
200: }
201: }
|