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         packetFactory = new MessageContextFactory(seiModel.getWSBinding().getFeatures());
  88         clientConfig = isClientConfig(config);
  89         if (clientConfig) {
  90             initStubHandlers();
  91         }
  92         seiModel.setDatabinding(this);
  93         if (wsdlport != null) {
  94             freeze(wsdlport);
  95         }
  96         if (operationDispatcher == null) {
  97             operationDispatcherNoWsdl = new OperationDispatcher(null, seiModel.getWSBinding(), seiModel);
  98         }
  99 //    if(!clientConfig) {
 100         for (JavaMethodImpl jm : seiModel.getJavaMethods()) {
 101             if (!jm.isAsync()) {
 102                 TieHandler th = new TieHandler(jm, seiModel.getWSBinding(), packetFactory);
 103                 wsdlOpMap.put(jm, th);
 104                 tieHandlers.put(th.getMethod(), th);
 105             }
 106         }
 107 //    }
 108     }
 109 
 110     //TODO isClientConfig
 111     private boolean isClientConfig(DatabindingConfig config) {
 112         if (config.getContractClass() == null) {
 113             return false;
 114         }
 115         if (!config.getContractClass().isInterface()) {
 116             return false;
 117         }
 118         return (config.getEndpointClass() == null || config.getEndpointClass().isInterface());
 119     }
 120     //TODO fix freeze
 121 
 122     public void freeze(WSDLPort port) {
 123         if (clientConfig) {
 124             return;
 125         }
 126         synchronized(this) {
 127             if (operationDispatcher == null) {
 128                 operationDispatcher = (port == null) ? null : new OperationDispatcher(port, seiModel.getWSBinding(), seiModel);
 129             }
 130         }
 131     }
 132 
 133     public SEIModel getModel() {
 134         return seiModel;
 135     }
 136 //Refactored from SEIStub
 137 
 138     private void initStubHandlers() {
 139         stubHandlers = new HashMap<Method, StubHandler>();
 140         Map<ActionBasedOperationSignature, JavaMethodImpl> syncs = new HashMap<ActionBasedOperationSignature, JavaMethodImpl>();
 141         // fill in methodHandlers.
 142         // first fill in sychronized versions
 143         for (JavaMethodImpl m : seiModel.getJavaMethods()) {
 144             if (!m.getMEP().isAsync) {
 145                 StubHandler handler = new StubHandler(m, packetFactory);
 146                 syncs.put(m.getOperationSignature(), m);
 147                 stubHandlers.put(m.getMethod(), handler);
 148             }
 149         }
 150         for (JavaMethodImpl jm : seiModel.getJavaMethods()) {
 151             JavaMethodImpl sync = syncs.get(jm.getOperationSignature());
 152             if (jm.getMEP() == MEP.ASYNC_CALLBACK || jm.getMEP() == MEP.ASYNC_POLL) {
 153                 Method m = jm.getMethod();
 154                 StubAsyncHandler handler = new StubAsyncHandler(jm, sync, packetFactory);
 155                 stubHandlers.put(m, handler);
 156             }
 157         }
 158     }
 159 
 160     JavaMethodImpl resolveJavaMethod(Packet req) throws DispatchException {
 161         WSDLOperationMapping m = req.getWSDLOperationMapping();
 162         if (m == null) {
 163             synchronized (this) {
 164                 m = (operationDispatcher != null)
 165                         ? operationDispatcher.getWSDLOperationMapping(req)
 166                         : operationDispatcherNoWsdl.getWSDLOperationMapping(req);
 167             }
 168         }
 169         return (JavaMethodImpl) m.getJavaMethod();
 170     }
 171 
 172     public JavaCallInfo deserializeRequest(Packet req) {
 173         com.sun.xml.internal.ws.api.databinding.JavaCallInfo call = new com.sun.xml.internal.ws.api.databinding.JavaCallInfo();
 174         try {
 175             JavaMethodImpl wsdlOp = resolveJavaMethod(req);
 176             TieHandler tie = wsdlOpMap.get(wsdlOp);
 177             call.setMethod(tie.getMethod());
 178             Object[] args = tie.readRequest(req.getMessage());
 179             call.setParameters(args);
 180         } catch (DispatchException e) {
 181             call.setException(e);
 182         }
 183         return call;
 184     }
 185 
 186     public JavaCallInfo deserializeResponse(Packet res, JavaCallInfo call) {
 187         StubHandler stubHandler = stubHandlers.get(call.getMethod());
 188         try {
 189             return stubHandler.readResponse(res, call);
 190         } catch (Throwable e) {
 191             call.setException(e);
 192             return call;
 193         }
 194     }
 195 
 196     public WebServiceFeature[] getFeatures() {
 197         // TODO Auto-generated method stub
 198         return null;
 199     }
 200 
 201     @Override
 202     public Packet serializeRequest(JavaCallInfo call) {
 203         StubHandler stubHandler = stubHandlers.get(call.getMethod());
 204         Packet p = stubHandler.createRequestPacket(call);
 205         p.setState(Packet.State.ClientRequest);
 206         return p;
 207     }
 208 
 209     @Override
 210     public Packet serializeResponse(JavaCallInfo call) {
 211         Method method = call.getMethod();
 212         Message message = null;
 213         if (method != null) {
 214             TieHandler th = tieHandlers.get(method);
 215             if (th != null) {
 216                 return th.serializeResponse(call);
 217             }
 218         }
 219         if (call.getException() instanceof DispatchException) {
 220             message = ((DispatchException) call.getException()).fault;
 221         }
 222         Packet p = (Packet) packetFactory.createContext(message);
 223         p.setState(Packet.State.ServerResponse);
 224         return p;
 225     }
 226 
 227     @Override
 228     public ClientCallBridge getClientBridge(Method method) {
 229         return stubHandlers.get(method);
 230     }
 231 
 232     @Override
 233     public void generateWSDL(WSDLGenInfo info) {
 234         com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator wsdlGen = new com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator(
 235                 seiModel,
 236                 info.getWsdlResolver(),
 237                 seiModel.getWSBinding(),
 238                 info.getContainer(), seiModel.getEndpointClass(),
 239                 info.isInlineSchemas(),
 240                 info.isSecureXmlProcessingDisabled(),
 241                 info.getExtensions());
 242         wsdlGen.doGeneration();
 243     }
 244 
 245     @Override
 246     public EndpointCallBridge getEndpointBridge(Packet req) throws DispatchException {
 247         JavaMethodImpl wsdlOp = resolveJavaMethod(req);
 248         return wsdlOpMap.get(wsdlOp);
 249     }
 250 
 251     Codec getCodec() {
 252         if (codec == null) {
 253             codec = ((BindingImpl) seiModel.getWSBinding()).createCodec();
 254         }
 255         return codec;
 256     }
 257 
 258     @Override
 259     public ContentType encode(Packet packet, OutputStream out) throws IOException {
 260         return getCodec().encode(packet, out);
 261     }
 262 
 263     @Override
 264     public void decode(InputStream in, String ct, Packet p) throws IOException {
 265         getCodec().decode(in, ct, p);
 266     }
 267 
 268     @Override
 269     public com.oracle.webservices.internal.api.databinding.JavaCallInfo createJavaCallInfo(Method method, Object[] args) {
 270         return new com.sun.xml.internal.ws.api.databinding.JavaCallInfo(method, args);
 271     }
 272 
 273     @Override
 274     public com.oracle.webservices.internal.api.databinding.JavaCallInfo deserializeResponse(
 275             MessageContext message, com.oracle.webservices.internal.api.databinding.JavaCallInfo call) {
 276         return deserializeResponse((Packet) message, (JavaCallInfo) call);
 277     }
 278 
 279     @Override
 280     public com.oracle.webservices.internal.api.databinding.JavaCallInfo deserializeRequest(MessageContext message) {
 281         return deserializeRequest((Packet) message);
 282     }
 283 
 284     @Override
 285     public MessageContextFactory getMessageContextFactory() {
 286         return packetFactory;
 287     }
 288 }