package er.extensions.appserver.ws;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.istack.NotNull;
import com.sun.xml.ws.api.PropertySet;
import com.sun.xml.ws.api.server.WebServiceContextDelegate;
import com.sun.xml.ws.transport.http.WSHTTPConnection;
import com.webobjects.appserver.WOApplication;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.appserver.WOSession;
import er.extensions.appserver.ERXRequest;
import er.extensions.appserver.ERXResponse;
import er.extensions.appserver.ERXWOContext;
/**
* @author mstoll
*
* This class maps ERXRequest/ERXResponse to a WSHTTPConnection
* This enables to jump into the request handling mechanism of JaxWS
* for handling WebServices from a Servlet.
*
*/
public class ERWSWOHTTPConnection
extends WSHTTPConnection
{
public static final String ERJAXWS_WOCONTEXT = "com.webobjects.appserver.WOContext";
public static final String ERJAXWS_ERXWOCONTEXT = "er.extensions.appserver.ERXWOContext";
private static final Logger log = LoggerFactory.getLogger(ERWSWOHTTPConnection.class);
/** the current ERXRequest */
ERXRequest woRequest;
/** the output stream JaxWS writes into */
ByteArrayOutputStream responseOutputStream = new ByteArrayOutputStream();
/** the HTTP result status, being set from JaxWS
* to be handed into ERXResponse
*/
int responseStatus = 0;
/** the current ERXResponse */
ERXResponse woResponse;
/** the associated session **/
WOSession session = null;
private static final PropertySet.PropertyMap model = parse(ERWSWOHTTPConnection.class);
/**
* The constructor
* @param req the current ERXRequest for this RR cycle
*/
public ERWSWOHTTPConnection(WORequest req)
{
woRequest = (ERXRequest)req;
woResponse = new ERXResponse();
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getInput()
*/
@Override
public InputStream getInput() throws IOException
{
return woRequest.content().stream();
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getOutput()
*/
@Override
public OutputStream getOutput() throws IOException
{
return responseOutputStream;
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getPathInfo()
*/
@Override
public String getPathInfo()
{
return "";
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getQueryString()
*/
@Override
public String getQueryString()
{
return woRequest.queryString();
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getRequestHeader(java.lang.String)
*/
@Override
public String getRequestHeader(String s)
{
return woRequest.headerForKey(s);
}
// JAX 2.2 methods
// @Override
// public Set<String> getRequestHeaderNames()
// {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public List<String> getRequestHeaderValues(String s)
// {
// // TODO Auto-generated method stub
// return null;
// }
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getRequestHeaders()
*/
@SuppressWarnings({
"rawtypes", "unchecked"
})
@PropertySet.Property({ "javax.xml.ws.http.request.headers",
"com.sun.xml.ws.api.message.packet.inbound.transport.headers" })
@NotNull
@Override
public Map<String, List<String>> getRequestHeaders()
{
return (Map)woRequest.headers();
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getRequestMethod()
*/
@Override
public String getRequestMethod()
{
return woRequest.method();
}
// JAX 2.2 methods
// @Override
// public String getRequestScheme()
// {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public String getRequestURI()
// {
// // TODO Auto-generated method stub
// return null;
// }
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getResponseHeaders()
*/
@PropertySet.Property({ "javax.xml.ws.http.response.headers",
"com.sun.xml.ws.api.message.packet.outbound.transport.headers" })
@Override
public Map<String, List<String>> getResponseHeaders()
{
return null;
}
// @Override
// public String getServerName()
// {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public int getServerPort()
// {
// // TODO Auto-generated method stub
// return 0;
// }
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getStatus()
*/
@Override
public int getStatus()
{
return responseStatus;
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#getWebServiceContextDelegate()
*/
@Override
public WebServiceContextDelegate getWebServiceContextDelegate()
{
return null;
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#isSecure()
*/
@Override
public boolean isSecure()
{
return woRequest.isSecure();
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#setContentTypeResponseHeader(java.lang.String)
*/
@Override
public void setContentTypeResponseHeader(String s)
{
woResponse.setHeader(s, "Content-Type");
}
// @Override
// public void setResponseHeader(String s, List<String> list)
// {
// // TODO Auto-generated method stub
//
// }
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#setResponseHeaders(java.util.Map)
*/
@Override
public void setResponseHeaders(Map<String, List<String>> map)
{
woResponse.setHeaders(map);
}
/* (non-Javadoc)
* @see com.sun.xml.ws.transport.http.WSHTTPConnection#setStatus(int)
*/
@Override
public void setStatus(int i)
{
responseStatus = i;
}
/* (non-Javadoc)
* @see com.sun.xml.ws.api.PropertySet#getPropertyMap()
*/
@Override
protected PropertySet.PropertyMap getPropertyMap()
{
return model;
}
/**
* Generate the response after the ERXRequest has been treaten by JaxWS
*
* @return the generated ERXResponse
*/
public WOResponse generateResponse()
{
try
{
responseOutputStream.flush();
woResponse.setStatus(responseStatus);
woResponse.setContent(responseOutputStream.toByteArray());
if(context != null && context._session() != null)
{
context._session().setStoresIDsInCookies(true);
context._session()._appendCookieToResponse(woResponse);
WOApplication.application().saveSessionForContext(context);
woResponse._finalizeInContext(context);
}
}
catch(IOException e)
{
log.error("Exception on writing response.", e);
return null;
}
return woResponse;
}
private WOContext context = null;
@PropertySet.Property({ "com.webobjects.appserver.WOContext" })
public synchronized WOContext WOContext()
{
if(context == null)
{
synchronized (this)
{
if(context == null)
{
context = WOApplication.application().createContextForRequest(woRequest);
String sessionID = getSessionIDFromCookie();
if(sessionID != null)
context._setRequestSessionID(sessionID);
}
}
}
return context;
}
@PropertySet.Property({ "er.extensions.appserver.ERXWOContext" })
public synchronized ERXWOContext ERXWOContext()
{
WOContext c = WOContext();
if(c instanceof ERXWOContext)
{
return (ERXWOContext)c;
}
throw new IllegalArgumentException("WOContext is no sublass of ERXWOContext");
}
private String getSessionIDFromCookie()
{
return woRequest.cookieValueForKey(WOApplication.application().sessionIdKey());
}
}