Package org.teiid.resource.adapter.ws

Source Code of org.teiid.resource.adapter.ws.WSConnectionImpl

package org.teiid.resource.adapter.ws;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import javax.activation.DataSource;
import javax.resource.ResourceException;
import javax.xml.namespace.QName;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Binding;
import javax.xml.ws.Dispatch;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.Response;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxws.DispatchImpl;
import org.teiid.core.util.ArgCheck;
import org.teiid.core.util.Base64;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.StringUtil;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
import org.teiid.resource.spi.BasicConnection;
import org.teiid.translator.WSConnection;

/**
* WebService connection implementation.
*
* TODO: set a handler chain
*/
public class WSConnectionImpl extends BasicConnection implements WSConnection {
 
  private static final class HttpDataSource implements DataSource {
    private final URL url;
    private final HttpURLConnection httpConn;

    private HttpDataSource(URL url, HttpURLConnection httpConn) {
      this.url = url;
      this.httpConn = httpConn;
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
      throw new UnsupportedOperationException();
    }

    @Override
    public String getName() {
      return url.getPath();
    }

    @Override
    public InputStream getInputStream() throws IOException {
      return httpConn.getInputStream();
    }

    @Override
    public String getContentType() {
      return httpConn.getContentType();
    }
  }
 
  /**
   * Workaround dispatch, since neither JBossNative nor CXF 2.2.2 implement
   * this functionality.
   */
  private static final class BinaryDispatch implements Dispatch<DataSource> {

    HashMap<String, Object> requestContext = new HashMap<String, Object>();
   
    private String endpoint;
   
    public BinaryDispatch(String endpoint) {
      this.endpoint = endpoint;
    }

    @Override
    public DataSource invoke(DataSource msg) {
      try {
        final URL url = new URL(endpoint);
        final HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestMethod((String) requestContext.get(MessageContext.HTTP_REQUEST_METHOD));
        Map<String, List<String>> header = (Map<String, List<String>>)requestContext.get(MessageContext.HTTP_REQUEST_HEADERS);
        for (Map.Entry<String, List<String>> entry : header.entrySet()) {
          String value = StringUtil.join(entry.getValue(), ","); //$NON-NLS-1$
          httpConn.setRequestProperty(entry.getKey(), value);
        }
        String username = (String) requestContext.get(Dispatch.USERNAME_PROPERTY);
        String password = (String) requestContext.get(Dispatch.PASSWORD_PROPERTY);
 
        if (username != null) {
          httpConn.setRequestProperty("Authorization", "Basic " + Base64.encodeBytes((username + ':' + password).getBytes())); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        if (msg != null) {
          httpConn.setDoOutput(true);
          OutputStream os = httpConn.getOutputStream();
          InputStream is = msg.getInputStream();
          ObjectConverterUtil.write(os, is, -1);
        }
       
        return new HttpDataSource(url, httpConn);
      } catch (IOException e) {
        throw new WebServiceException(e);
      }
    }

    @Override
    public Response<DataSource> invokeAsync(DataSource msg) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Future<?> invokeAsync(DataSource msg, AsyncHandler<DataSource> handler) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void invokeOneWay(DataSource msg) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Binding getBinding() {
      throw new UnsupportedOperationException();
    }

    @Override
    public EndpointReference getEndpointReference() {
      throw new UnsupportedOperationException();
    }

    @Override
    public <T extends EndpointReference> T getEndpointReference(
        Class<T> clazz) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Map<String, Object> getRequestContext() {
      return requestContext;
    }

    @Override
    public Map<String, Object> getResponseContext() {
      throw new UnsupportedOperationException();
    }
  }
 
  static final String DEFAULT_NAMESPACE_URI = "http://teiid.org"; //$NON-NLS-1$
  static final String DEFAULT_LOCAL_NAME = "teiid"; //$NON-NLS-1$

  private static QName svcQname = new QName(DEFAULT_NAMESPACE_URI, DEFAULT_LOCAL_NAME);
  private WSManagedConnectionFactory mcf;
 
  public WSConnectionImpl(WSManagedConnectionFactory mcf) {
    this.mcf = mcf;
  }

  public <T> Dispatch<T> createDispatch(String binding, String endpoint, Class<T> type, Mode mode) {
    ArgCheck.isNotNull(binding);
    if (endpoint != null) {
      try {
        new URL(endpoint);
        //valid url, just use the endpoint
      } catch (MalformedURLException e) {
        //otherwise it should be a relative value
        //but we should still preserve the base path and query string
        String defaultEndpoint = mcf.getEndPoint();
        String defaultQueryString = null;
        String defaultFragment = null;
        String[] parts = defaultEndpoint.split("\\?", 2); //$NON-NLS-1$
        defaultEndpoint = parts[0];
        if (parts.length > 1) {
          defaultQueryString = parts[1];
          parts = defaultQueryString.split("#"); //$NON-NLS-1$
          defaultQueryString = parts[0];
          if (parts.length > 1) {
            defaultFragment = parts[1];
          }
        }
        if (endpoint.startsWith("?") || endpoint.startsWith("/")) { //$NON-NLS-1$ //$NON-NLS-2$
          endpoint = defaultEndpoint + endpoint;
        } else {
          endpoint = defaultEndpoint + "/" + endpoint; //$NON-NLS-1$ 
        }
        if (defaultQueryString != null && defaultQueryString.trim().length() > 0) {
          endpoint = WSConnection.Util.appendQueryString(endpoint, defaultQueryString);
        }
        if (defaultFragment != null && endpoint.indexOf('#') < 0) {
          endpoint = endpoint + '#' + defaultFragment;
        }
      }
    } else {
      endpoint = mcf.getEndPoint();
    }
    Dispatch<T> dispatch = null;
    if (HTTPBinding.HTTP_BINDING.equals(binding) && type == DataSource.class) {
      dispatch = (Dispatch<T>) new BinaryDispatch(endpoint);
    } else {
      //TODO: cache service/port/dispatch instances?
      Bus bus = BusFactory.getThreadDefaultBus();
      BusFactory.setThreadDefaultBus(mcf.getBus());
      Service svc;
      try {
        svc = Service.create(svcQname);
      } finally {
        BusFactory.setThreadDefaultBus(bus);
      }
      if (LogManager.isMessageToBeRecorded(LogConstants.CTX_WS, MessageLevel.DETAIL)) {
        LogManager.logDetail(LogConstants.CTX_WS, "Creating a dispatch with endpoint", endpoint); //$NON-NLS-1$
      }
      svc.addPort(mcf.getPortQName(), binding, endpoint);
     
      dispatch = svc.createDispatch(mcf.getPortQName(), type, mode);
     
      if (mcf.getSecurityType() == WSManagedConnectionFactory.SecurityType.WSSecurity
          && mcf.getOutInterceptors() != null) {
        Client client = ((DispatchImpl)dispatch).getClient();
        Endpoint ep = client.getEndpoint();
        for (Interceptor i : mcf.getOutInterceptors()) {
          ep.getOutInterceptors().add(i);
        }
      }
    }
   
    if (mcf.getSecurityType() == WSManagedConnectionFactory.SecurityType.HTTPBasic){
      dispatch.getRequestContext().put(Dispatch.USERNAME_PROPERTY, mcf.getAuthUserName());
      dispatch.getRequestContext().put(Dispatch.PASSWORD_PROPERTY, mcf.getAuthPassword());
    }
   
    if (HTTPBinding.HTTP_BINDING.equals(binding)) {
          Map<String, List<String>> httpHeaders = (Map<String, List<String>>)dispatch.getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
          if(httpHeaders == null) {
            httpHeaders = new HashMap<String, List<String>>();
          }
          httpHeaders.put("Content-Type", Collections.singletonList("text/xml; charset=utf-8"));//$NON-NLS-1$ //$NON-NLS-2$
          httpHeaders.put("User-Agent", Collections.singletonList("Teiid Server"));//$NON-NLS-1$ //$NON-NLS-2$
          dispatch.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
    }
    return dispatch;
  }

  @Override
  public void close() throws ResourceException {
   
  }

}
TOP

Related Classes of org.teiid.resource.adapter.ws.WSConnectionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.