All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.ws.transport.local.LocalAsyncTransportTube Maven / Gradle / Ivy

There is a newer version: 4.0.2
Show newest version
/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at
 * https://glassfish.dev.java.net/public/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
 */
package com.sun.xml.ws.transport.local;

import com.sun.istack.NotNull;
import com.sun.xml.ws.api.message.Packet;
import com.sun.xml.ws.api.pipe.Codec;
import com.sun.xml.ws.api.pipe.ContentType;
import com.sun.xml.ws.api.pipe.Fiber;
import com.sun.xml.ws.api.pipe.NextAction;
import com.sun.xml.ws.api.pipe.Tube;
import com.sun.xml.ws.api.pipe.TubeCloner;
import com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl;
import com.sun.xml.ws.api.server.Adapter;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.client.ContentNegotiation;
import com.sun.xml.ws.transport.http.HttpAdapter;
import com.sun.xml.ws.transport.http.WSHTTPConnection;

import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Transport {@link Tube} that routes a message to a service that runs within it.
 *
 * 

* This is useful to test the whole client-server in a single VM. * * @author Jitendra Kotamraju */ final class LocalAsyncTransportTube extends AbstractTubeImpl { /** * Represents the service running inside the local transport. * * We use {@link HttpAdapter}, so that the local transport * excercise as much server code as possible. If this were * to be done "correctly" we should write our own {@link Adapter} * for the local transport. */ private final HttpAdapter adapter; private final Codec codec; /** * The address of the endpoint deployed in this tube. */ private final URI baseURI; // per-pipe reusable resources. // we don't really have to reuse anything since this isn't designed for performance, // but nevertheless we do it as an experiement. private final Map> reqHeaders = new HashMap>(); public LocalAsyncTransportTube(URI baseURI, WSEndpoint endpoint, Codec codec) { this(baseURI,HttpAdapter.createAlone(endpoint),codec); } private LocalAsyncTransportTube(URI baseURI,HttpAdapter adapter, Codec codec) { this.adapter = adapter; this.codec = codec; this.baseURI = baseURI; assert codec !=null && adapter!=null; } /** * Copy constructor for {@link Tube#copy(TubeCloner)}. */ private LocalAsyncTransportTube(LocalAsyncTransportTube that, TubeCloner cloner) { this(that.baseURI, that.adapter, that.codec.copy()); cloner.add(that,this); } public @NotNull NextAction processException(@NotNull Throwable t) { return doThrow(t); } private class MyClosedCallback implements ClosedCallback { final Fiber fiber; LocalConnectionImpl con; String requestContentType; String requestAccept; final Packet request; MyClosedCallback(Packet request) { this.request = request; this.requestContentType = requestContentType; this.requestAccept = requestAccept; fiber = Fiber.current(); } void setConnection(LocalConnectionImpl con) { this.con = con; } void setContentType(ContentType ct) { requestContentType = ct.getContentType(); requestAccept = ct.getAcceptHeader(); } public void onClosed() { String responseContentType = getResponseContentType(con); if (con.getStatus() == WSHTTPConnection.ONEWAY) { Packet reply = request.createClientResponse(null); // one way. no response given. fiber.resume(reply); return; } // TODO: check if returned MIME type is the same as that which was sent // or is acceptable if an Accept header was used checkFIConnegIntegrity(request.contentNegotiation, requestContentType, requestAccept, responseContentType); Packet reply = request.createClientResponse(null); try { codec.decode(con.getInput(), responseContentType, reply); } catch(Exception e) { e.printStackTrace(); } fiber.resume(reply); } } private void checkFIConnegIntegrity(ContentNegotiation conneg, String requestContentType, String requestAccept, String responseContentType) { requestAccept = (requestAccept == null) ? "" : requestAccept; if (requestContentType.contains("fastinfoset")) { if (!responseContentType.contains("fastinfoset")) { throw new RuntimeException( "Request is encoded using Fast Infoset but response (" + responseContentType + ") is not"); } else if (conneg == ContentNegotiation.none) { throw new RuntimeException( "Request is encoded but Fast Infoset content negotiation is set to none"); } } else if (requestAccept.contains("fastinfoset")) { if (!responseContentType.contains("fastinfoset")) { throw new RuntimeException( "Fast Infoset is acceptable but response is not encoded in Fast Infoset"); } else if (conneg == ContentNegotiation.none) { throw new RuntimeException( "Fast Infoset is acceptable but Fast Infoset content negotiation is set to none"); } } else if (conneg == ContentNegotiation.pessimistic) { throw new RuntimeException( "Content negotitaion is set to pessimistic but Fast Infoset is not acceptable"); } else if (conneg == ContentNegotiation.optimistic) { throw new RuntimeException( "Content negotitaion is set to optimistic but the request (" + requestContentType + ") is not encoded using Fast Infoset"); } } private String getResponseContentType(LocalConnectionImpl con) { Map> rsph = con.getResponseHeaders(); if(rsph!=null) { List c = rsph.get("Content-Type"); if(c!=null && !c.isEmpty()) return c.get(0); } return null; } @NotNull public NextAction processRequest(@NotNull Packet request) { try { // Set up WSConnection with tranport headers, request content // get transport headers from message reqHeaders.clear(); Map> rh = (Map>) request.invocationProperties.get(MessageContext.HTTP_REQUEST_HEADERS); //assign empty map if its null if(rh != null){ reqHeaders.putAll(rh); } MyClosedCallback callback = new MyClosedCallback(request); LocalConnectionImpl con = new LocalConnectionImpl(baseURI,reqHeaders,callback); callback.setConnection(con); // Calling getStaticContentType sets some internal state in the codec // TODO : need to fix this properly in Codec ContentType contentType = codec.getStaticContentType(request); String requestContentType; if (contentType != null) { requestContentType = contentType.getContentType(); codec.encode(request, con.getOutput()); } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(); contentType = codec.encode(request, baos); requestContentType = contentType.getContentType(); baos.writeTo(con.getOutput()); } callback.setContentType(contentType); reqHeaders.put("Content-Type", Collections.singletonList(requestContentType)); String requestAccept = contentType.getAcceptHeader(); if (contentType.getAcceptHeader() != null) { reqHeaders.put("Accept", Collections.singletonList(requestAccept)); } if(dump) dump(con,"request",reqHeaders); //Packet serverReq = adapter.decodePacket(con, codec); adapter.invokeAsync(con); return doSuspend(); } catch(IOException ioe) { throw new WebServiceException(ioe); } } @NotNull public NextAction processResponse(@NotNull Packet response) { return doReturnWith(response); } public void preDestroy() { // Nothing to do here. Intenionally left empty } public LocalAsyncTransportTube copy(TubeCloner cloner) { return new LocalAsyncTransportTube(this, cloner); } private void dump(LocalConnectionImpl con, String caption, Map> headers) { System.out.println("---["+caption +"]---"); if(headers!=null) { for (Entry> header : headers.entrySet()) { if(header.getValue().isEmpty()) { // I don't think this is legal, but let's just dump it, // as the point of the dump is to uncover problems. System.out.println(header.getValue()); } else { for (String value : header.getValue()) { System.out.println(header.getKey()+": "+value); } } } } System.out.println(con.toString()); System.out.println("--------------------"); } /** * Dumps what goes across HTTP transport. */ private static final boolean dump; static { boolean b; try { b = Boolean.getBoolean(LocalTransportTube.class.getName()+".dump"); } catch( Throwable t ) { b = false; } dump = b; } private static final boolean async; static { boolean b; try { b = Boolean.getBoolean(LocalTransportTube.class.getName()+".async"); } catch( Throwable t ) { b = false; } async = b; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy