001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with 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,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.geronimo.cxf.ejb;
019:
020: import java.lang.reflect.Method;
021: import java.util.List;
022:
023: import javax.interceptor.AroundInvoke;
024: import javax.interceptor.InvocationContext;
025: import javax.xml.soap.SOAPMessage;
026: import javax.xml.stream.XMLStreamReader;
027: import javax.xml.transform.dom.DOMSource;
028: import javax.xml.ws.Binding;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.apache.cxf.Bus;
033: import org.apache.cxf.binding.soap.SoapMessage;
034: import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
035: import org.apache.cxf.endpoint.Endpoint;
036: import org.apache.cxf.interceptor.AbstractInDatabindingInterceptor;
037: import org.apache.cxf.interceptor.Interceptor;
038: import org.apache.cxf.interceptor.InterceptorChain;
039: import org.apache.cxf.interceptor.OutgoingChainInterceptor;
040: import org.apache.cxf.interceptor.ServiceInvokerInterceptor;
041: import org.apache.cxf.jaxws.handler.logical.LogicalHandlerInInterceptor;
042: import org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor;
043: import org.apache.cxf.jaxws.support.JaxWsEndpointImpl;
044: import org.apache.cxf.message.Exchange;
045: import org.apache.cxf.message.Message;
046: import org.apache.cxf.phase.PhaseInterceptorChain;
047: import org.apache.cxf.phase.PhaseManager;
048: import org.apache.cxf.service.Service;
049: import org.apache.cxf.staxutils.StaxUtils;
050: import org.w3c.dom.Element;
051:
052: public class EJBInterceptor {
053:
054: private static final Log LOG = LogFactory
055: .getLog(EJBInterceptor.class);
056:
057: private Exchange exchange;
058: private Bus bus;
059: private EJBEndpoint ejbEndpoint;
060: private List<Object> params;
061: private Method method;
062:
063: public EJBInterceptor(List<Object> params, Method method,
064: EJBEndpoint endpoint, Bus bus, Exchange exchange) {
065: this .params = params;
066: this .method = method;
067: this .ejbEndpoint = endpoint;
068: this .bus = bus;
069: this .exchange = exchange;
070: }
071:
072: private static void copyDataBindingInterceptors(
073: PhaseInterceptorChain newChain, InterceptorChain oldChain) {
074: for (Interceptor interceptor : oldChain) {
075: if (interceptor instanceof AbstractInDatabindingInterceptor) {
076: LOG.debug("Added data binding interceptor: "
077: + interceptor);
078: newChain.add(interceptor);
079: }
080: }
081: }
082:
083: @AroundInvoke
084: public Object intercept(InvocationContext context) throws Exception {
085: Endpoint endpoint = this .exchange.get(Endpoint.class);
086: Service service = endpoint.getService();
087: Binding binding = ((JaxWsEndpointImpl) endpoint)
088: .getJaxwsBinding();
089:
090: this .exchange.put(InvocationContext.class, context);
091:
092: if (binding.getHandlerChain() == null
093: || binding.getHandlerChain().isEmpty()) {
094: // no handlers so let's just directly invoke the bean
095: LOG.debug("No handlers found.");
096:
097: EJBMethodInvoker invoker = (EJBMethodInvoker) service
098: .getInvoker();
099: return invoker.directEjbInvoke(this .exchange, this .method,
100: this .params);
101:
102: } else {
103: // have handlers so have to run handlers now and redo data binding
104: // as handlers can change the soap message
105: LOG.debug("Handlers found.");
106:
107: // inject handlers (on first call only)
108: this .ejbEndpoint.injectHandlers();
109:
110: Message inMessage = this .exchange.getInMessage();
111: PhaseInterceptorChain chain = new PhaseInterceptorChain(
112: this .bus.getExtension(PhaseManager.class)
113: .getInPhases());
114:
115: chain.setFaultObserver(endpoint.getOutFaultObserver());
116:
117: /*
118: * Since we have to re-do data binding and the XMLStreamReader
119: * contents are already consumed by prior data binding step
120: * we have to reinitialize the XMLStreamReader from the SOAPMessage
121: * created by SAAJInInterceptor.
122: */
123: if (inMessage instanceof SoapMessage) {
124: try {
125: reserialize((SoapMessage) inMessage);
126: } catch (Exception e) {
127: throw new RuntimeException(
128: "Failed to reserialize soap message", e);
129: }
130: } else {
131: // TODO: how to handle XML/HTTP binding?
132: }
133:
134: this .exchange.setOutMessage(null);
135:
136: // install default interceptors
137: chain.add(new ServiceInvokerInterceptor());
138: chain.add(new OutgoingChainInterceptor());
139:
140: // install interceptors for handler processing
141: chain.add(new MustUnderstandInterceptor());
142: chain.add(new LogicalHandlerInInterceptor(binding));
143: chain.add(new SOAPHandlerInterceptor(binding));
144:
145: // install data binding interceptors
146: copyDataBindingInterceptors(chain, inMessage
147: .getInterceptorChain());
148:
149: InterceptorChain oldChain = inMessage.getInterceptorChain();
150: inMessage.setInterceptorChain(chain);
151: try {
152: chain.doIntercept(inMessage);
153: } finally {
154: inMessage.setInterceptorChain(oldChain);
155: }
156:
157: // TODO: the result should be deserialized from SOAPMessage
158: Object result = getResult();
159:
160: return result;
161: }
162: }
163:
164: private Object getResult() {
165: Message outMessage = this .exchange.getOutMessage();
166: if (outMessage == null) {
167: return null;
168: } else {
169: List<?> result = outMessage.getContent(List.class);
170: if (result == null) {
171: return outMessage.get(Object.class);
172: } else if (result.isEmpty()) {
173: return null;
174: } else {
175: return result.get(0);
176: }
177: }
178: }
179:
180: private void reserialize(SoapMessage message) throws Exception {
181: SOAPMessage soapMessage = message.getContent(SOAPMessage.class);
182: if (soapMessage == null) {
183: return;
184: }
185:
186: XMLStreamReader xmlReader = message
187: .getContent(XMLStreamReader.class);
188: StaxUtils.readDocElements(soapMessage.getSOAPBody(), xmlReader,
189: true);
190: DOMSource bodySource = new DOMSource(soapMessage.getSOAPPart()
191: .getEnvelope().getBody());
192: xmlReader = StaxUtils.createXMLStreamReader(bodySource);
193: xmlReader.nextTag();
194: xmlReader.nextTag(); // move past body tag
195: message.setContent(XMLStreamReader.class, xmlReader);
196: }
197:
198: }
|