001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.wsn.component;
018
019 import java.io.StringWriter;
020 import java.lang.reflect.InvocationTargetException;
021 import java.lang.reflect.Method;
022 import java.util.ArrayList;
023 import java.util.Arrays;
024 import java.util.List;
025
026 import javax.jbi.messaging.ExchangeStatus;
027 import javax.jbi.messaging.Fault;
028 import javax.jbi.messaging.InOnly;
029 import javax.jbi.messaging.MessageExchange;
030 import javax.jbi.messaging.NormalizedMessage;
031 import javax.jws.Oneway;
032 import javax.jws.WebMethod;
033 import javax.jws.WebService;
034 import javax.xml.bind.JAXBContext;
035 import javax.xml.bind.JAXBException;
036 import javax.xml.bind.annotation.XmlRootElement;
037 import javax.xml.namespace.QName;
038 import javax.xml.ws.WebFault;
039
040 import org.apache.servicemix.common.ExchangeProcessor;
041 import org.apache.servicemix.common.endpoints.ProviderEndpoint;
042 import org.apache.servicemix.jbi.jaxp.StringSource;
043 import org.apache.servicemix.jbi.resolver.URIResolver;
044 import org.apache.servicemix.wsn.ComponentContextAware;
045 import org.oasis_open.docs.wsrf.bf_2.BaseFaultType;
046
047 public class WSNEndpoint extends ProviderEndpoint implements ExchangeProcessor {
048
049 protected String address;
050
051 protected Object pojo;
052
053 protected JAXBContext jaxbContext;
054
055 protected Class endpointInterface;
056
057 public WSNEndpoint(String address, Object pojo) {
058 this.address = address;
059 this.pojo = pojo;
060 String[] parts = URIResolver.split3(address);
061 service = new QName(parts[0], parts[1]);
062 endpoint = parts[2];
063 }
064
065 @Override
066 public void start() throws Exception {
067 if (pojo instanceof ComponentContextAware) {
068 ((ComponentContextAware) pojo).setContext(getContext());
069 }
070 logger = this.serviceUnit.getComponent().getLogger();
071 WebService ws = getWebServiceAnnotation(pojo.getClass());
072 if (ws == null) {
073 throw new IllegalStateException("Unable to find WebService annotation");
074 }
075 endpointInterface = Class.forName(ws.endpointInterface());
076 jaxbContext = createJAXBContext(endpointInterface);
077 ws = getWebServiceAnnotation(endpointInterface);
078 if (ws != null) {
079 interfaceName = new QName(ws.targetNamespace(), ws.name());
080 }
081 super.start();
082 }
083
084 public static JAXBContext createJAXBContext(Class interfaceClass) throws JAXBException {
085 List<Class> classes = new ArrayList<Class>();
086 classes.add(JbiFault.class);
087 for (Method mth : interfaceClass.getMethods()) {
088 WebMethod wm = (WebMethod) mth.getAnnotation(WebMethod.class);
089 if (wm != null) {
090 classes.add(mth.getReturnType());
091 classes.addAll(Arrays.asList(mth.getParameterTypes()));
092 }
093 }
094 return JAXBContext.newInstance(classes.toArray(new Class[classes.size()]));
095 }
096
097 @SuppressWarnings("unchecked")
098 public void process(MessageExchange exchange) throws Exception {
099 if (exchange.getStatus() == ExchangeStatus.DONE) {
100 return;
101 } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
102 return;
103 }
104 Object input = jaxbContext.createUnmarshaller().unmarshal(exchange.getMessage("in").getContent());
105 Method webMethod = null;
106 for (Method mth : endpointInterface.getMethods()) {
107 Class[] params = mth.getParameterTypes();
108 if (params.length == 1 && params[0].isAssignableFrom(input.getClass())) {
109 webMethod = mth;
110 break;
111 }
112 }
113 if (webMethod == null) {
114 throw new IllegalStateException("Could not determine invoked web method");
115 }
116 boolean oneWay = webMethod.getAnnotation(Oneway.class) != null;
117 Object output;
118 try {
119 output = webMethod.invoke(pojo, new Object[] {input });
120 } catch (InvocationTargetException e) {
121 if (e.getCause() instanceof Exception) {
122 WebFault fa = (WebFault) e.getCause().getClass().getAnnotation(WebFault.class);
123 if (!(exchange instanceof InOnly) && fa != null) {
124 BaseFaultType info = (BaseFaultType) e.getCause().getClass().getMethod("getFaultInfo").invoke(
125 e.getCause());
126 Fault fault = exchange.createFault();
127 exchange.setFault(fault);
128 exchange.setError((Exception) e.getCause());
129 StringWriter writer = new StringWriter();
130 jaxbContext.createMarshaller().marshal(new JbiFault(info), writer);
131 fault.setContent(new StringSource(writer.toString()));
132 send(exchange);
133 return;
134 } else {
135 throw (Exception) e.getCause();
136 }
137 } else if (e.getCause() instanceof Error) {
138 throw (Error) e.getCause();
139 } else {
140 throw new RuntimeException(e.getCause());
141 }
142 }
143 if (oneWay) {
144 exchange.setStatus(ExchangeStatus.DONE);
145 send(exchange);
146 } else {
147 NormalizedMessage msg = exchange.createMessage();
148 exchange.setMessage(msg, "out");
149 StringWriter writer = new StringWriter();
150 jaxbContext.createMarshaller().marshal(output, writer);
151 msg.setContent(new StringSource(writer.toString()));
152 send(exchange);
153 }
154 }
155
156 @XmlRootElement(name = "Fault")
157 public static class JbiFault {
158 private BaseFaultType info;
159
160 public JbiFault() {
161 }
162
163 public JbiFault(BaseFaultType info) {
164 this.info = info;
165 }
166
167 public BaseFaultType getInfo() {
168 return info;
169 }
170
171 public void setInfo(BaseFaultType info) {
172 this.info = info;
173 }
174 }
175
176 protected Method getWebServiceMethod(QName interfaceName, QName operation) throws Exception {
177 WebService ws = getWebServiceAnnotation(pojo.getClass());
178 if (ws == null) {
179 throw new IllegalStateException("Unable to find WebService annotation");
180 }
181 Class itf = Class.forName(ws.endpointInterface());
182 for (Method mth : itf.getMethods()) {
183 WebMethod wm = (WebMethod) mth.getAnnotation(WebMethod.class);
184 if (wm != null) {
185 // TODO: get name ?
186 }
187 }
188 return null;
189 }
190
191 @SuppressWarnings("unchecked")
192 protected WebService getWebServiceAnnotation(Class clazz) {
193 for (Class cl = clazz; cl != null; cl = cl.getSuperclass()) {
194 WebService ws = (WebService) cl.getAnnotation(WebService.class);
195 if (ws != null) {
196 return ws;
197 }
198 }
199 return null;
200 }
201
202 }