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.server.cxf.ejb;
018:
019: import org.apache.cxf.Bus;
020: import org.apache.cxf.binding.soap.SoapMessage;
021: import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
022: import org.apache.cxf.endpoint.Endpoint;
023: import org.apache.cxf.interceptor.AbstractInDatabindingInterceptor;
024: import org.apache.cxf.interceptor.Interceptor;
025: import org.apache.cxf.interceptor.InterceptorChain;
026: import org.apache.cxf.interceptor.OutgoingChainInterceptor;
027: import org.apache.cxf.interceptor.ServiceInvokerInterceptor;
028: import org.apache.cxf.jaxws.handler.logical.LogicalHandlerInInterceptor;
029: import org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor;
030: import org.apache.cxf.jaxws.support.JaxWsEndpointImpl;
031: import org.apache.cxf.message.Exchange;
032: import org.apache.cxf.message.Message;
033: import org.apache.cxf.phase.PhaseInterceptorChain;
034: import org.apache.cxf.phase.PhaseManager;
035: import org.apache.cxf.service.Service;
036: import org.apache.cxf.staxutils.StaxUtils;
037: import org.apache.openejb.util.LogCategory;
038: import org.apache.openejb.util.Logger;
039:
040: import javax.interceptor.AroundInvoke;
041: import javax.interceptor.InvocationContext;
042: import javax.xml.soap.SOAPMessage;
043: import javax.xml.stream.XMLStreamReader;
044: import javax.xml.transform.dom.DOMSource;
045: import javax.xml.ws.Binding;
046: import java.lang.reflect.Method;
047: import java.util.List;
048:
049: public class EjbInterceptor {
050: private static final Logger log = Logger.getInstance(
051: LogCategory.CXF, EjbInterceptor.class);
052:
053: private Exchange exchange;
054: private Bus bus;
055: private List<Object> params;
056: private Method method;
057:
058: public EjbInterceptor(List<Object> params, Method method, Bus bus,
059: Exchange exchange) {
060: this .params = params;
061: this .method = method;
062: this .bus = bus;
063: this .exchange = exchange;
064: }
065:
066: private static void copyDataBindingInterceptors(
067: PhaseInterceptorChain newChain, InterceptorChain oldChain) {
068: for (Interceptor interceptor : oldChain) {
069: if (interceptor instanceof AbstractInDatabindingInterceptor) {
070: log.debug("Added data binding interceptor: "
071: + interceptor);
072: newChain.add(interceptor);
073: }
074: }
075: }
076:
077: @AroundInvoke
078: public Object intercept(InvocationContext context) throws Exception {
079: Endpoint endpoint = this .exchange.get(Endpoint.class);
080: Service service = endpoint.getService();
081: Binding binding = ((JaxWsEndpointImpl) endpoint)
082: .getJaxwsBinding();
083:
084: this .exchange.put(InvocationContext.class, context);
085:
086: if (binding.getHandlerChain() == null
087: || binding.getHandlerChain().isEmpty()) {
088: // no handlers so let's just directly invoke the bean
089: log.debug("No handlers found.");
090:
091: EjbMethodInvoker invoker = (EjbMethodInvoker) service
092: .getInvoker();
093: return invoker.directEjbInvoke(this .exchange, this .method,
094: this .params);
095:
096: } else {
097: // have handlers so have to run handlers now and redo data binding
098: // as handlers can change the soap message
099: log.debug("Handlers found.");
100:
101: Message inMessage = exchange.getInMessage();
102: PhaseInterceptorChain chain = new PhaseInterceptorChain(bus
103: .getExtension(PhaseManager.class).getInPhases());
104:
105: chain.setFaultObserver(endpoint.getOutFaultObserver());
106:
107: /*
108: * Since we have to re-do data binding and the XMLStreamReader
109: * contents are already consumed by prior data binding step
110: * we have to reinitialize the XMLStreamReader from the SOAPMessage
111: * created by SAAJInInterceptor.
112: */
113: if (inMessage instanceof SoapMessage) {
114: try {
115: reserialize((SoapMessage) inMessage);
116: } catch (Exception e) {
117: throw new RuntimeException(
118: "Failed to reserialize soap message", e);
119: }
120: } else {
121: // TODO: how to handle XML/HTTP binding?
122: }
123:
124: this .exchange.setOutMessage(null);
125:
126: // install default interceptors
127: chain.add(new ServiceInvokerInterceptor());
128: chain.add(new OutgoingChainInterceptor());
129:
130: // install interceptors for handler processing
131: chain.add(new MustUnderstandInterceptor());
132: chain.add(new LogicalHandlerInInterceptor(binding));
133: chain.add(new SOAPHandlerInterceptor(binding));
134:
135: // install data binding interceptors
136: copyDataBindingInterceptors(chain, inMessage
137: .getInterceptorChain());
138:
139: InterceptorChain oldChain = inMessage.getInterceptorChain();
140: inMessage.setInterceptorChain(chain);
141: try {
142: chain.doIntercept(inMessage);
143: } finally {
144: inMessage.setInterceptorChain(oldChain);
145: }
146:
147: // TODO: the result should be deserialized from SOAPMessage
148: Object result = getResult();
149:
150: return result;
151: }
152: }
153:
154: private Object getResult() {
155: Message outMessage = this .exchange.getOutMessage();
156: if (outMessage == null) {
157: return null;
158: } else {
159: List<?> result = outMessage.getContent(List.class);
160: if (result == null) {
161: return outMessage.get(Object.class);
162: } else if (result.isEmpty()) {
163: return null;
164: } else {
165: return result.get(0);
166: }
167: }
168: }
169:
170: private void reserialize(SoapMessage message) throws Exception {
171: SOAPMessage soapMessage = message.getContent(SOAPMessage.class);
172: if (soapMessage == null) {
173: return;
174: }
175:
176: XMLStreamReader xmlReader = message
177: .getContent(XMLStreamReader.class);
178: StaxUtils.readDocElements(soapMessage.getSOAPBody(), xmlReader,
179: true);
180: DOMSource bodySource = new DOMSource(soapMessage.getSOAPPart()
181: .getEnvelope().getBody());
182: xmlReader = StaxUtils.createXMLStreamReader(bodySource);
183: xmlReader.nextTag();
184: xmlReader.nextTag(); // move past body tag
185: message.setContent(XMLStreamReader.class, xmlReader);
186: }
187: }
|