1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.ws.db; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.OutputStream; 31 import java.lang.reflect.Method; 32 import java.util.HashMap; 33 import java.util.Map; 34 35 import javax.xml.ws.WebServiceFeature; 36 37 import com.oracle.webservices.internal.api.databinding.JavaCallInfo; 38 import com.oracle.webservices.internal.api.message.MessageContext; 39 import com.sun.xml.internal.ws.api.databinding.EndpointCallBridge; 40 import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo; 41 import com.sun.xml.internal.ws.api.databinding.Databinding; 42 import com.sun.xml.internal.ws.api.databinding.DatabindingConfig; 43 import com.sun.xml.internal.ws.api.databinding.ClientCallBridge; 44 import com.sun.xml.internal.ws.api.message.Message; 45 import com.sun.xml.internal.ws.api.message.MessageContextFactory; 46 import com.sun.xml.internal.ws.api.message.Packet; 47 import com.sun.xml.internal.ws.api.model.MEP; 48 import com.sun.xml.internal.ws.api.model.SEIModel; 49 import com.sun.xml.internal.ws.api.model.WSDLOperationMapping; 50 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; 51 import com.sun.xml.internal.ws.api.pipe.Codec; 52 import com.sun.xml.internal.ws.api.pipe.ContentType; 53 import com.sun.xml.internal.ws.binding.BindingImpl; 54 import com.sun.xml.internal.ws.client.sei.StubAsyncHandler; 55 import com.sun.xml.internal.ws.client.sei.StubHandler; 56 import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; 57 import com.sun.xml.internal.ws.model.JavaMethodImpl; 58 import com.sun.xml.internal.ws.model.RuntimeModeler; 59 import com.sun.xml.internal.ws.server.sei.TieHandler; 60 import com.sun.xml.internal.ws.wsdl.ActionBasedOperationSignature; 61 import com.sun.xml.internal.ws.wsdl.DispatchException; 62 import com.sun.xml.internal.ws.wsdl.OperationDispatcher; 63 64 /** 65 * WsRuntimeImpl is the databinding processor built on SEIModel 66 * 67 * @author shih-chang.chen@oracle.com 68 */ 69 public final class DatabindingImpl implements Databinding { 70 71 AbstractSEIModelImpl seiModel; 72 Map<Method, StubHandler> stubHandlers; 73 // QNameMap<TieHandler> wsdlOpMap = new QNameMap<TieHandler>(); 74 Map<JavaMethodImpl, TieHandler> wsdlOpMap = new HashMap<JavaMethodImpl, TieHandler>(); 75 Map<Method, TieHandler> tieHandlers = new HashMap<Method, TieHandler>(); 76 OperationDispatcher operationDispatcher; 77 OperationDispatcher operationDispatcherNoWsdl; 78 boolean clientConfig = false; 79 Codec codec; 80 MessageContextFactory packetFactory = null; 81 82 public DatabindingImpl(DatabindingProviderImpl p, DatabindingConfig config) { 83 RuntimeModeler modeler = new RuntimeModeler(config); 84 modeler.setClassLoader(config.getClassLoader()); 85 seiModel = modeler.buildRuntimeModel(); 86 WSDLPort wsdlport = config.getWsdlPort(); 87 Object facProp = config.properties().get("com.sun.xml.internal.ws.api.message.MessageContextFactory"); 88 packetFactory = (facProp != null && facProp instanceof MessageContextFactory)? (MessageContextFactory)facProp : 89 new MessageContextFactory(seiModel.getWSBinding().getFeatures()); 90 clientConfig = isClientConfig(config); 91 if (clientConfig) { 92 initStubHandlers(); 93 } 94 seiModel.setDatabinding(this); 95 if (wsdlport != null) { 96 freeze(wsdlport); 97 } 98 if (operationDispatcher == null) { 99 operationDispatcherNoWsdl = new OperationDispatcher(null, seiModel.getWSBinding(), seiModel); 100 } 101 // if(!clientConfig) { 102 for (JavaMethodImpl jm : seiModel.getJavaMethods()) { 103 if (!jm.isAsync()) { 104 TieHandler th = new TieHandler(jm, seiModel.getWSBinding(), packetFactory); 105 wsdlOpMap.put(jm, th); 106 tieHandlers.put(th.getMethod(), th); 107 } 108 } 109 // } 110 } 111 112 //TODO isClientConfig 113 private boolean isClientConfig(DatabindingConfig config) { 114 if (config.getContractClass() == null) { 115 return false; 116 } 117 if (!config.getContractClass().isInterface()) { 118 return false; 119 } 120 return (config.getEndpointClass() == null || config.getEndpointClass().isInterface()); 121 } 122 //TODO fix freeze 123 124 public void freeze(WSDLPort port) { 125 if (clientConfig) { 126 return; 127 } 128 synchronized(this) { 129 if (operationDispatcher == null) { 130 operationDispatcher = (port == null) ? null : new OperationDispatcher(port, seiModel.getWSBinding(), seiModel); 131 } 132 } 133 } 134 135 public SEIModel getModel() { 136 return seiModel; 137 } 138 //Refactored from SEIStub 139 140 private void initStubHandlers() { 141 stubHandlers = new HashMap<Method, StubHandler>(); 142 Map<ActionBasedOperationSignature, JavaMethodImpl> syncs = new HashMap<ActionBasedOperationSignature, JavaMethodImpl>(); 143 // fill in methodHandlers. 144 // first fill in sychronized versions 145 for (JavaMethodImpl m : seiModel.getJavaMethods()) { 146 if (!m.getMEP().isAsync) { 147 StubHandler handler = new StubHandler(m, packetFactory); 148 syncs.put(m.getOperationSignature(), m); 149 stubHandlers.put(m.getMethod(), handler); 150 } 151 } 152 for (JavaMethodImpl jm : seiModel.getJavaMethods()) { 153 JavaMethodImpl sync = syncs.get(jm.getOperationSignature()); 154 if (jm.getMEP() == MEP.ASYNC_CALLBACK || jm.getMEP() == MEP.ASYNC_POLL) { 155 Method m = jm.getMethod(); 156 StubAsyncHandler handler = new StubAsyncHandler(jm, sync, packetFactory); 157 stubHandlers.put(m, handler); 158 } 159 } 160 } 161 162 JavaMethodImpl resolveJavaMethod(Packet req) throws DispatchException { 163 WSDLOperationMapping m = req.getWSDLOperationMapping(); 164 if (m == null) { 165 synchronized (this) { 166 m = (operationDispatcher != null) 167 ? operationDispatcher.getWSDLOperationMapping(req) 168 : operationDispatcherNoWsdl.getWSDLOperationMapping(req); 169 } 170 } 171 return (JavaMethodImpl) m.getJavaMethod(); 172 } 173 174 public JavaCallInfo deserializeRequest(Packet req) { 175 com.sun.xml.internal.ws.api.databinding.JavaCallInfo call = new com.sun.xml.internal.ws.api.databinding.JavaCallInfo(); 176 try { 177 JavaMethodImpl wsdlOp = resolveJavaMethod(req); 178 TieHandler tie = wsdlOpMap.get(wsdlOp); 179 call.setMethod(tie.getMethod()); 180 Object[] args = tie.readRequest(req.getMessage()); 181 call.setParameters(args); 182 } catch (DispatchException e) { 183 call.setException(e); 184 } 185 return call; 186 } 187 188 public JavaCallInfo deserializeResponse(Packet res, JavaCallInfo call) { 189 StubHandler stubHandler = stubHandlers.get(call.getMethod()); 190 try { 191 return stubHandler.readResponse(res, call); 192 } catch (Throwable e) { 193 call.setException(e); 194 return call; 195 } 196 } 197 198 public WebServiceFeature[] getFeatures() { 199 // TODO Auto-generated method stub 200 return null; 201 } 202 203 @Override 204 public Packet serializeRequest(JavaCallInfo call) { 205 StubHandler stubHandler = stubHandlers.get(call.getMethod()); 206 Packet p = stubHandler.createRequestPacket(call); 207 p.setState(Packet.State.ClientRequest); 208 return p; 209 } 210 211 @Override 212 public Packet serializeResponse(JavaCallInfo call) { 213 Method method = call.getMethod(); 214 Message message = null; 215 if (method != null) { 216 TieHandler th = tieHandlers.get(method); 217 if (th != null) { 218 return th.serializeResponse(call); 219 } 220 } 221 if (call.getException() instanceof DispatchException) { 222 message = ((DispatchException) call.getException()).fault; 223 } 224 Packet p = (Packet) packetFactory.createContext(message); 225 p.setState(Packet.State.ServerResponse); 226 return p; 227 } 228 229 @Override 230 public ClientCallBridge getClientBridge(Method method) { 231 return stubHandlers.get(method); 232 } 233 234 @Override 235 public void generateWSDL(WSDLGenInfo info) { 236 com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator wsdlGen = new com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator( 237 seiModel, 238 info.getWsdlResolver(), 239 seiModel.getWSBinding(), 240 info.getContainer(), seiModel.getEndpointClass(), 241 info.isInlineSchemas(), 242 info.isSecureXmlProcessingDisabled(), 243 info.getExtensions()); 244 wsdlGen.doGeneration(); 245 } 246 247 @Override 248 public EndpointCallBridge getEndpointBridge(Packet req) throws DispatchException { 249 JavaMethodImpl wsdlOp = resolveJavaMethod(req); 250 return wsdlOpMap.get(wsdlOp); 251 } 252 253 Codec getCodec() { 254 if (codec == null) { 255 codec = ((BindingImpl) seiModel.getWSBinding()).createCodec(); 256 } 257 return codec; 258 } 259 260 @Override 261 public ContentType encode(Packet packet, OutputStream out) throws IOException { 262 return getCodec().encode(packet, out); 263 } 264 265 @Override 266 public void decode(InputStream in, String ct, Packet p) throws IOException { 267 getCodec().decode(in, ct, p); 268 } 269 270 @Override 271 public com.oracle.webservices.internal.api.databinding.JavaCallInfo createJavaCallInfo(Method method, Object[] args) { 272 return new com.sun.xml.internal.ws.api.databinding.JavaCallInfo(method, args); 273 } 274 275 @Override 276 public com.oracle.webservices.internal.api.databinding.JavaCallInfo deserializeResponse( 277 MessageContext message, com.oracle.webservices.internal.api.databinding.JavaCallInfo call) { 278 return deserializeResponse((Packet) message, (JavaCallInfo) call); 279 } 280 281 @Override 282 public com.oracle.webservices.internal.api.databinding.JavaCallInfo deserializeRequest(MessageContext message) { 283 return deserializeRequest((Packet) message); 284 } 285 286 @Override 287 public MessageContextFactory getMessageContextFactory() { 288 return packetFactory; 289 } 290 }