001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.client;
018:
019: import javax.naming.Context;
020: import javax.xml.namespace.QName;
021: import javax.xml.ws.WebServiceException;
022: import javax.xml.ws.handler.Handler;
023: import javax.xml.ws.handler.HandlerResolver;
024: import javax.xml.ws.handler.LogicalHandler;
025: import javax.xml.ws.handler.PortInfo;
026: import java.util.ArrayList;
027: import java.util.Collections;
028: import java.util.HashMap;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Map;
032:
033: public class ClientHandlerResolverImpl implements HandlerResolver {
034: private final List<HandlerChainMetaData> handlerChains;
035: private final List<Injection> injections;
036: private final Context context;
037: private final List<ClientInjectionProcessor<Handler>> handlerInstances = new ArrayList<ClientInjectionProcessor<Handler>>();
038:
039: public ClientHandlerResolverImpl(
040: List<HandlerChainMetaData> handlerChains,
041: List<Injection> injections, Context context) {
042: this .handlerChains = handlerChains;
043: this .injections = injections;
044: this .context = context;
045: }
046:
047: public void destroyHandlers() {
048: List<ClientInjectionProcessor<Handler>> handlerInstances = new ArrayList<ClientInjectionProcessor<Handler>>(
049: this .handlerInstances);
050: this .handlerInstances.clear();
051: for (ClientInjectionProcessor<Handler> handlerInstance : handlerInstances) {
052: handlerInstance.preDestroy();
053: }
054: }
055:
056: public List<Handler> getHandlerChain(
057: javax.xml.ws.handler.PortInfo portInfo) {
058: List<Handler> chain = new ArrayList<Handler>();
059: for (HandlerChainMetaData handlerChain : handlerChains) {
060: List<Handler> handlers = buildHandlers(portInfo,
061: handlerChain);
062: handlers = sortHandlers(handlers);
063: chain.addAll(handlers);
064: }
065: chain = sortHandlers(chain);
066: return chain;
067: }
068:
069: private List<Handler> buildHandlers(
070: javax.xml.ws.handler.PortInfo portInfo,
071: HandlerChainMetaData handlerChain) {
072: if (!matchServiceName(portInfo, handlerChain
073: .getServiceNamePattern())
074: || !matchPortName(portInfo, handlerChain
075: .getPortNamePattern())
076: || !matchBinding(portInfo, handlerChain
077: .getProtocolBindings())) {
078: return Collections.emptyList();
079: }
080:
081: List<Handler> handlers = new ArrayList<Handler>(handlerChain
082: .getHandlers().size());
083: for (HandlerMetaData handler : handlerChain.getHandlers()) {
084: try {
085: Class<? extends Handler> handlerClass = loadClass(
086: handler.getHandlerClass()).asSubclass(
087: Handler.class);
088: ClientInjectionProcessor<Handler> processor = new ClientInjectionProcessor<Handler>(
089: handlerClass, injections, handler
090: .getPostConstruct(), handler
091: .getPreDestroy(), context);
092: processor.createInstance();
093: processor.postConstruct();
094: Handler handlerInstance = processor.getInstance();
095:
096: handlers.add(handlerInstance);
097: handlerInstances.add(processor);
098: } catch (Exception e) {
099: throw new WebServiceException(
100: "Failed to instantiate handler", e);
101: }
102: }
103: return handlers;
104: }
105:
106: private boolean matchServiceName(PortInfo info, String namePattern) {
107: return match((info == null ? null : info.getServiceName()),
108: namePattern);
109: }
110:
111: private boolean matchPortName(PortInfo info, String namePattern) {
112: return match((info == null ? null : info.getPortName()),
113: namePattern);
114: }
115:
116: private boolean matchBinding(PortInfo info, List bindings) {
117: return match((info == null ? null : info.getBindingID()),
118: bindings);
119: }
120:
121: private boolean match(String binding, List bindings) {
122: if (binding == null) {
123: return (bindings == null || bindings.isEmpty());
124: } else {
125: if (bindings == null || bindings.isEmpty()) {
126: return true;
127: } else {
128: String actualBindingURI = getBindingURI(binding);
129: Iterator iter = bindings.iterator();
130: while (iter.hasNext()) {
131: String bindingToken = (String) iter.next();
132: String bindingURI = getBindingURI(bindingToken);
133: if (actualBindingURI.equals(bindingURI)) {
134: return true;
135: }
136: }
137: return false;
138: }
139: }
140: }
141:
142: /**
143: * Performs basic localName matching, namespaces are not checked!
144: */
145: private boolean match(QName name, String namePattern) {
146: if (name == null) {
147: return (namePattern == null || namePattern.equals("*"));
148: } else {
149: if (namePattern == null) {
150: return true;
151: } else {
152: String localNamePattern;
153:
154: // get the local name from pattern
155: int pos = namePattern.indexOf(':');
156: localNamePattern = (pos == -1) ? namePattern
157: : namePattern.substring(pos + 1);
158: localNamePattern = localNamePattern.trim();
159:
160: if (localNamePattern.equals("*")) {
161: // matches anything
162: return true;
163: } else if (localNamePattern.endsWith("*")) {
164: // match start
165: localNamePattern = localNamePattern.substring(0,
166: localNamePattern.length() - 1);
167: return name.getLocalPart().startsWith(
168: localNamePattern);
169: } else {
170: // match exact
171: return name.getLocalPart().equals(localNamePattern);
172: }
173: }
174: }
175: }
176:
177: /**
178: * sorts the handlers into correct order. All of the logical handlers first
179: * followed by the protocol handlers
180: *
181: * @param handlers
182: * @return sorted list of handlers
183: */
184: private List<Handler> sortHandlers(List<Handler> handlers) {
185: List<LogicalHandler> logicalHandlers = new ArrayList<LogicalHandler>();
186: List<Handler> protocolHandlers = new ArrayList<Handler>();
187:
188: for (Handler handler : handlers) {
189: if (handler instanceof LogicalHandler) {
190: logicalHandlers.add((LogicalHandler) handler);
191: } else {
192: protocolHandlers.add(handler);
193: }
194: }
195:
196: List<Handler> sortedHandlers = new ArrayList<Handler>();
197: sortedHandlers.addAll(logicalHandlers);
198: sortedHandlers.addAll(protocolHandlers);
199: return sortedHandlers;
200: }
201:
202: private static final Map<String, String> BINDING_MAP = new HashMap<String, String>();
203:
204: static {
205: BINDING_MAP.put("##SOAP11_HTTP",
206: "http://schemas.xmlsoap.org/wsdl/soap/http");
207: BINDING_MAP.put("##SOAP12_HTTP",
208: "http://www.w3.org/2003/05/soap/bindings/HTTP/");
209: BINDING_MAP.put("##SOAP11_HTTP_MTOM",
210: "http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true");
211: BINDING_MAP
212: .put("##SOAP12_HTTP_MTOM",
213: "http://www.w3.org/2003/05/soap/bindings/HTTP/?mtom=true");
214: BINDING_MAP.put("##XML_HTTP",
215: "http://www.w3.org/2004/08/wsdl/http");
216: }
217:
218: private static String getBindingURI(String token) {
219: if (token != null) {
220: if (token.startsWith("##")) {
221: String uri = BINDING_MAP.get(token);
222: if (uri == null) {
223: throw new IllegalArgumentException(
224: "Unsupported binding token: " + token);
225: }
226: return uri;
227: }
228: return token;
229: }
230: return BINDING_MAP.get("##SOAP11_HTTP");
231: }
232:
233: private Class<?> loadClass(String name)
234: throws ClassNotFoundException {
235: ClassLoader classLoader = Thread.currentThread()
236: .getContextClassLoader();
237: if (classLoader != null) {
238: return classLoader.loadClass(name);
239: }
240: return Class.forName(name);
241: }
242: }
|