blob: 9559d65ea73cf79d421a81e91d093166cd1d97c0 [file] [log] [blame]
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* @author Susantha Kumara (susantha@opensource.lk, skumara@virtusa.com)
*
*/
#include "Apache2Transport.h"
#define AXIS_URI_EXTENSION "/axis"
/* Following is the character that should be used to separate the method name in
* the SOAPAction header value. Ex: "http://localhost:80/axis/Calculator#Add"
*/
#define SOAPACTION_METHODNAME_SEPARATOR "#"
Apache2Transport::Apache2Transport(void* pContext)
{
m_eProtocolType = APTHTTP1_1;
m_pContext = pContext;
#ifndef CHUNCKED_DATA_SUPPORTED
m_pBuffers = new BufferInfo[NO_OF_SERIALIZE_BUFFERS];
memset((void*)m_pBuffers, 0, sizeof(BufferInfo)*NO_OF_SERIALIZE_BUFFERS);
#endif
}
Apache2Transport::~Apache2Transport()
{
if(m_pBuffers)
{
delete [] m_pBuffers;
m_pBuffers = NULL;
}
}
AXIS_TRANSPORT_STATUS Apache2Transport::sendBytes(const char* pcSendBuffer, const void* pBufferId)
{
#ifndef CHUNCKED_DATA_SUPPORTED
int index;
#endif
if (!pBufferId) /* temporary buffers should always sent immediately */
{
ap_rputs(pcSendBuffer, (request_rec*)m_pContext);
return TRANSPORT_FINISHED;
}
#ifdef CHUNCKED_DATA_SUPPORTED
// Do we need to send any headers and length of this chunk ?
ap_rputs(pcSendBuffer, (request_rec*)m_pContext);
/* Do we need to send any indication to mark the end of this
* chunk ?
*/
return TRANSPORT_FINISHED;
#else
for (index = 0; index < NO_OF_SERIALIZE_BUFFERS; index++)
{
if (!m_pBuffers[index].pcBuffer)
{
m_pBuffers[index].pcBuffer = pcSendBuffer;
m_pBuffers[index].pBufferId = pBufferId;
break;
}
}
return TRANSPORT_IN_PROGRESS;
#endif
}
int Apache2Transport::setTransportProperty(AXIS_TRANSPORT_INFORMATION_TYPE type, const char* value)
{
const char* key = NULL;
switch (type)
{
case SOAPACTION_HEADER: /* needed only in the client side ? */
break;
case SERVICE_URI: /* need to set ? */
break;
case OPERATION_NAME: /* need to set ? */
break;
case SOAP_MESSAGE_LENGTH:
/* This is apache module and transport is http so the key */
key = "Content-Length";
break;
/* case CONTENT_TYPE:
((request_rec*)m_pContext)->content_type = value;
break; */
default:;
}
if (key)
{
ap_table_set(((request_rec*)m_pContext)->headers_out, key, value);
#ifdef CHUNCKED_DATA_SUPPORTED
ap_send_http_header((request_rec*)m_pContext);
/* Should we remove the sent headers ? */
#endif
}
return 0;
}
AXIS_TRANSPORT_STATUS Apache2Transport::flushOutput()
{
#ifndef CHUNCKED_DATA_SUPPORTED
int contentLength = 0;
int index;
char strtonum[8];
#endif
#ifdef CHUNCKED_DATA_SUPPORTED
/* headers have already been sent. see set_transport_information
* http body too have been sent
* Do we need to send any indication to mark end of chuncked
* data ?
*/
#else
/* Calculate Content-Length and set header */
for (index = 0; index < NO_OF_SERIALIZE_BUFFERS; index++)
{
if (!m_pBuffers[index].pcBuffer)
break;
contentLength += strlen(m_pBuffers[index].pcBuffer);
}
if (contentLength != 0) /* do only if the http body is not empty. */
{
sprintf(strtonum, "%d", contentLength);
setTransportProperty(SOAP_MESSAGE_LENGTH, strtonum);
ap_send_http_header((request_rec*)m_pContext);
/* Send all buffers */
for (index = 0; index < NO_OF_SERIALIZE_BUFFERS; index++)
{
if (!m_pBuffers[index].pcBuffer)
break;
ap_rputs(m_pBuffers[index].pcBuffer, (request_rec*)m_pContext);
/* Let Axis know that the buffer is no longer in use */
m_pReleaseBufferCallback(m_pBuffers[index].pcBuffer,
m_pBuffers[index].pBufferId);
}
}
#endif
return TRANSPORT_FINISHED;
}
AXIS_TRANSPORT_STATUS Apache2Transport::getBytes(char* pBuffer, int* piSize)
{
int nBufSize = *piSize;
int len_read;
len_read = ap_get_client_block((request_rec*) m_pContext, pBuffer, *piSize);
if (strstr(pBuffer, "Content-Id")) {
pAttachmentHelper = new AttachmentHelper();
//char *pAttachBuffer = (char*)malloc(1000);
//char *mimeBoundary = (char*)malloc(1000);
pAttachmentHelper->extract_Attachment(pBuffer);
pAttachmentHelper->extract_SOAPMimeHeaders(pBuffer);
pAttachmentHelper->extract_Soap(pBuffer);
}
*piSize = len_read;
if (len_read < nBufSize)
{
pBuffer[len_read] = '\0';
return TRANSPORT_FINISHED;
}
else
return TRANSPORT_IN_PROGRESS;
}
const char* Apache2Transport::getTransportProperty(AXIS_TRANSPORT_INFORMATION_TYPE eType)
{
const char* pcValue;
/* the member, "path" of "parsed_uri" contains the uri of the
request (i.e "/abc/xyz" part of http://somehost/abc/xyz) */
const char* pcUriPath = ((request_rec*)m_pContext)->parsed_uri.path;
switch (eType)
{
case SOAPACTION_HEADER:
return getTransportProperty("SOAPAction");
case SERVICE_URI:
if (strstr(pcUriPath, AXIS_URI_EXTENSION))
{
return strstr(pcUriPath, AXIS_URI_EXTENSION) +
strlen(AXIS_URI_EXTENSION) + 1;
}
else
{
return pcUriPath;
}
case OPERATION_NAME:
pcValue = getTransportProperty("SOAPAction");
if (pcValue)
{
if (strstr(pcValue, SOAPACTION_METHODNAME_SEPARATOR))
{
return strstr(pcValue, SOAPACTION_METHODNAME_SEPARATOR) +
strlen(SOAPACTION_METHODNAME_SEPARATOR);
}
else
{
return pcValue;
}
}
case SOAP_MESSAGE_LENGTH:
return getTransportProperty("Content-Length");
/* this is apache module and transport is http so the key */
default:;
}
return NULL;
}
int Apache2Transport::setTransportProperty(const char* pcKey, const char* pcValue)
{
/*ap_table_set(((request_rec*)m_pContext)->headers_out, pcKey, pcValue);*/
//ap_send_http_header((request_rec*)m_pContext);
return 0;
}
const char* Apache2Transport::getTransportProperty(const char* pcKey, bool response)
{
/* ap_table_elts returns an array_header struct. The nelts element of that
* struct contains the number of input header elements. Finally assigns that
* to the axis soap data structure. */
const apr_array_header_t* arr;
int headercount = ap_table_elts(((request_rec*)m_pContext)->headers_in)->nelts;
apr_table_entry_t* pHeaders = 0;
/* casting req_rec->headers_in to axis header struct and assigning that to
* the axis soap structure. Hope this is ok
*/
/* obtain the array_header from the headers_in table and assign it to the
* axis soap structure
*/
arr = ap_table_elts(((request_rec*)m_pContext)->headers_in);
pHeaders = (apr_table_entry_t*)arr->elts;
for (int ix=0; ix<headercount; ix++)
{
if (!strcmp(pHeaders->key, pcKey))
return pHeaders->val;
pHeaders++;
}
return 0;
}
void Apache2Transport::setSessionId(const char* pcSessionId)
{
}
const char* Apache2Transport::getSessionId()
{
return "this is temporary session id"; //TODO
}
const char* Apache2Transport::getServiceName()
{
return 0; //TODO
}
AXIS_PROTOCOL_TYPE Apache2Transport::getProtocol()
{
return m_eProtocolType;
}
int Apache2Transport::setProtocol(AXIS_PROTOCOL_TYPE eProtocol)
{
if( eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0 )
{
m_eProtocolType = eProtocol;
return AXIS_SUCCESS;
}
else
return AXIS_FAIL;
}
int Apache2Transport::getSubProtocol()
{
/*Determine the http method and assign it to the axis soap structure */
switch (((request_rec*)m_pContext)->method_number)
{
case M_GET:
return AXIS_HTTP_GET;
case M_POST:
return AXIS_HTTP_POST;
default:
return AXIS_HTTP_UNSUPPORTED;
}
}
ISoapAttachment* Apache2Transport::getAttachment(const char* pcAttachmentid)
{
ISoapAttachment* pAttch = pAttachmentHelper->getAttachment(pcAttachmentid);
return pAttch;
// return NULL;
};
char* Apache2Transport::getIncomingSOAPMimeHeaders()
{
return pAttachmentHelper->getIncomingSOAPMimeHeaders();
// return NULL;
}
ISoapAttachment** Apache2Transport::getAllAttachments(int *pAttchArraySize)
{
ISoapAttachment** pAttachments = pAttachmentHelper->getAllAttachments(pAttchArraySize);
return pAttachments;
// return NULL;
};