| /* -*- C++ -*- */ |
| /* |
| * 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 Lilantha Darshana (lilantha@virtusa.com) |
| * |
| */ |
| |
| #include "libAxiscpp.h" |
| #include "Packet.h" |
| #include "Axis.hpp" |
| #include <new> |
| #include <exception> |
| |
| #if defined (_DEBUG) |
| #include <iostream> |
| #define Trace(x) std::cout << x << std::endl; |
| #else |
| #define Trace(x) |
| #endif |
| |
| #define MIN(X,Y) (((X)<(Y))?(X):(Y)) |
| |
| /* Inaccessible static: DEBUG */ |
| /* |
| * Class: AxisCppContentHandler |
| * Method: processContent |
| * Signature: (Ljava/io/InputStream;Ljava/util/Vector;Ljava/io/OutputStream;)V |
| */ |
| JNIEXPORT void JNICALL Java_AxisCppContentHandler_processContent |
| (JNIEnv* p_Env, jclass, jobject p_jBodyReader, jobject p_jvHeaders, |
| jobject p_jBodyWriter, jint p_jnContentLength) |
| { |
| // TODO: populate soapstream with the headers & the body; |
| // invoke to process the contents |
| axstream *paxstream = new axstream; |
| |
| JNIInputStream inputBody (p_Env, p_jBodyReader); |
| JNIOutputStream outputBody (p_Env, p_jBodyWriter); |
| paxstream->m_pInputContent = new std::istream (&inputBody); |
| paxstream->m_pOutputContent = new std::ostream (&outputBody); |
| |
| paxstream->m_nContentLen = p_jnContentLength; |
| |
| JNIVector jvHeader (p_Env, p_jvHeaders); |
| // set method name as a http header. |
| int nHeaderCount = jvHeader.size () / 2; |
| paxstream->m_pHeaders = new axstream::PROT_HEADER[nHeaderCount]; |
| |
| for (int i = 0; i < nHeaderCount; i++) |
| { |
| paxstream->m_pHeaders[i].pchName = jvHeader[i * 2]; |
| paxstream->m_pHeaders[i].pchValue = jvHeader[i * 2 + 1]; |
| Trace (paxstream->m_pHeaders[i].pchName); |
| Trace (paxstream->m_pHeaders[i].pchValue); |
| } |
| paxstream->m_nHeaderCount = nHeaderCount; |
| |
| paxstream->m_enProtocolType = axstream::HTTP; |
| paxstream->m_pExtendedInfo = new axstream::EXTENDED_INFO; |
| paxstream->m_pExtendedInfo->infHttp.enMethod = axstream::HTTP_INFO::POST; |
| |
| // just add some sessionid |
| char *s = "tmp session id"; |
| paxstream->m_pchSessionId = new char[strlen(s)+1]; |
| strcpy(paxstream->m_pchSessionId,s); |
| |
| AxisContentHandler::Init (); |
| if (0 != AxisContentHandler::HandleContent (*paxstream)) |
| { |
| throw "SOAP Engine failed to response"; |
| } |
| |
| jvHeader.clear (); |
| nHeaderCount = paxstream->m_nHeaderCount; |
| |
| for (int j = 0; j < nHeaderCount; j++) |
| { |
| jvHeader.push_back (paxstream->m_pHeaders[j].pchName); |
| jvHeader.push_back (paxstream->m_pHeaders[j].pchValue); |
| Trace (paxstream->m_pHeaders[j].pchName); |
| Trace (paxstream->m_pHeaders[j].pchValue); |
| } |
| |
| *paxstream->m_pOutputContent << std::flush; |
| |
| delete paxstream; |
| } |
| |
| |
| JNIVector::JNIVector (JNIEnv* p_Env, jobject p_jVector):m_pEnv (p_Env), |
| m_jVector (p_jVector) |
| { |
| jclass clazz = p_Env->FindClass ("java/util/Vector"); |
| JNI_ASSERT (clazz != NULL, "java/lang/NoClassDefFoundError", |
| "java.util.Vector"); |
| |
| JNI_ASSERT (p_Env->IsInstanceOf (p_jVector, clazz), |
| "java/lang/IllegalArgumentException", |
| "p_jVector not a java.util.Vector object!"); |
| |
| m_jmGet = p_Env->GetMethodID (clazz, "get", "(I)Ljava/lang/Object;"); |
| |
| JNI_ASSERT (m_jmGet != NULL, "java/lang/NoSuchMethodError", |
| "method 'public Object get(int index)' not found!"); |
| |
| m_jmAdd = p_Env->GetMethodID (clazz, "addElement", "(Ljava/lang/Object;)V"); |
| |
| JNI_ASSERT (m_jmGet != NULL, "java/lang/NoSuchMethodError", |
| "method 'public void addElement(Object obj)' not found!"); |
| |
| m_jmClear = p_Env->GetMethodID (clazz, "clear", "()V"); |
| |
| JNI_ASSERT (m_jmGet != NULL, "java/lang/NoSuchMethodError", |
| "method 'public void clear()' not found!"); |
| |
| m_jmSize = p_Env->GetMethodID (clazz, "size", "()I"); |
| JNI_ASSERT (m_jmGet != NULL, "java/lang/NoSuchMethodError", |
| "method 'public void size()' not found!"); |
| } |
| |
| |
| JNIVector::~JNIVector () |
| { |
| |
| } |
| |
| char* JNIVector::operator [] (int i) |
| const |
| { |
| jboolean isCopy; |
| jobject obj = m_pEnv-> CallObjectMethod (m_jVector, m_jmGet, i); |
| jstring str = (jstring) obj; |
| const char* pch = m_pEnv->GetStringUTFChars (str, &isCopy); |
| if (m_pEnv->ExceptionOccurred ()) |
| throw std::bad_alloc (); |
| return (char*) |
| pch; |
| } |
| |
| void JNIVector::push_back (const char* str) |
| { |
| m_pEnv->CallVoidMethod (m_jVector, m_jmAdd, m_pEnv->NewStringUTF (str)); |
| if (m_pEnv->ExceptionOccurred ()) |
| throw std::bad_exception ("can't push_back"); |
| // need to set up a exception |
| } |
| |
| void JNIVector::clear () |
| { |
| m_pEnv->CallVoidMethod (m_jVector, m_jmClear); |
| if (m_pEnv->ExceptionOccurred ()) |
| throw std::bad_exception ("Can't clear the vector"); |
| // need to set up a exception |
| } |
| |
| int JNIVector::size () |
| { |
| int size = m_pEnv->CallIntMethod (m_jVector, m_jmSize); |
| if (m_pEnv->ExceptionOccurred ()) |
| throw std::bad_exception ("Don't know the vector size"); |
| // need to set up a exception |
| return size; |
| } |
| |
| |
| JNIOutputStream::JNIOutputStream (JNIEnv* p_pEnv, jobject stream, |
| unsigned bufsize):std::strstreambuf (bufsize), m_pEnv (p_pEnv), |
| _output (stream), _write (NULL), _flush (NULL), _bufsize (bufsize), |
| _jbuf (NULL) |
| { |
| jclass clazz = m_pEnv->FindClass ("java/io/OutputStream"); |
| JNI_ASSERT (clazz != NULL, "java/lang/NoClassDefFoundError", |
| "java.io.OutputStream"); |
| |
| JNI_ASSERT (m_pEnv->IsInstanceOf (stream, clazz), |
| "java/lang/IllegalArgumentException", |
| "stream not a java.io.OutputStream object!"); |
| |
| _write = m_pEnv->GetMethodID (clazz, "write", "([BII)V"); |
| // void write(byte[], int, int) |
| JNI_ASSERT (_write != NULL, "java/lang/NoSuchMethodError", |
| "method 'void java.io.OutputStream.write(byte[], int, int)' not found!"); |
| |
| _flush = m_pEnv->GetMethodID (clazz, "flush", "()V"); // void flush() |
| JNI_ASSERT (_flush != NULL, "java/lang/NoSuchMethodError", |
| "method 'void java.io.OutputStream.flush()' not found!"); |
| |
| _jbuf = m_pEnv->NewByteArray (_bufsize); |
| JNI_ASSERT (_jbuf != NULL, "java/lang/OutOfMemoryError", ""); |
| } |
| |
| JNIOutputStream::~JNIOutputStream () |
| { |
| m_pEnv->DeleteLocalRef (_jbuf); |
| } |
| |
| int JNIOutputStream::overflow (int c) |
| { |
| /* WIN32 has a bug in nested scope resolution - it can't |
| * handle std::strstreambuf::overflow - so we pull in the |
| * std namespace here. |
| */ |
| using namespace std; |
| |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| |
| unsigned count = pcount (); |
| for (unsigned start = 0, n; count > 0; count -= n, start += n) |
| { |
| n = MIN (count, _bufsize); |
| |
| m_pEnv->SetByteArrayRegion (_jbuf, 0, n, (jbyte*) pbase () + start); |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| |
| m_pEnv->CallVoidMethod (_output, _write, _jbuf, 0, n); |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| } |
| |
| setp (pbase (), epptr ()); // (put) buffer is empty |
| |
| return strstreambuf::overflow (c); |
| } |
| |
| int JNIOutputStream::sync () |
| { |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| |
| overflow (EOF); // empty buffer... |
| |
| if (_output) |
| { |
| m_pEnv->CallVoidMethod (_output, _flush); |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| } |
| |
| return 0; |
| } |
| |
| JNIInputStream::JNIInputStream (JNIEnv* env, jobject stream, |
| unsigned bufsize):std::strstreambuf (_buf = new char[bufsize], bufsize), |
| m_pEnv (env), _input (stream), _read (NULL), _close (NULL), |
| _bufsize (bufsize), _jbuf (NULL) |
| { |
| jclass clazz = m_pEnv->FindClass ("java/io/InputStream"); |
| JNI_ASSERT (clazz != NULL, "java/lang/NoClassDefFoundError", |
| "java.io.InputStream"); |
| |
| JNI_ASSERT (m_pEnv->IsInstanceOf (stream, clazz), |
| "java/lang/IllegalArgumentException", |
| "stream not a java.io.InputStream object!"); |
| |
| _read = m_pEnv->GetMethodID (clazz, "read", "([BII)I"); |
| // int read(byte[], int, int) |
| JNI_ASSERT (_read != NULL, "java/lang/NoSuchMethodError", |
| "method 'int java.io.InputStream.read(byte[], int, int)' not found!"); |
| |
| _close = m_pEnv->GetMethodID (clazz, "close", "()V"); // void close() |
| JNI_ASSERT (_read != NULL, "java/lang/NoSuchMethodError", |
| "method 'int java.io.InputStream.read(byte[], int, int)' not found!"); |
| |
| _available = m_pEnv->GetMethodID (clazz, "available", "()I"); |
| // int available() |
| JNI_ASSERT (_available != NULL, "java/lang/NoSuchMethodError", |
| "method 'int java.io.InputStream.available()' not found!"); |
| |
| _jbuf = m_pEnv->NewByteArray (_bufsize); |
| JNI_ASSERT (_jbuf != NULL, "java/lang/OutOfMemoryError", ""); |
| |
| setg (eback (), egptr (), egptr ()); // (get) buffer is empty |
| } |
| |
| JNIInputStream::~JNIInputStream () |
| { |
| delete[]_buf; |
| m_pEnv->DeleteLocalRef (_jbuf); |
| |
| m_pEnv->CallVoidMethod (_input, _close); |
| } |
| |
| int JNIInputStream::available () |
| { |
| int n = m_pEnv->CallIntMethod (_input, _available); |
| if (m_pEnv->ExceptionOccurred ()) |
| { |
| return EOF; |
| } |
| |
| return n; |
| } |
| |
| int JNIInputStream::underflow () |
| { |
| /* WIN32 has a bug in nested scope resolution - it can't |
| * handle std::strstreambuf::overflow - so we pull in the |
| * std namespace here. |
| */ |
| using namespace std; |
| |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| |
| int n = m_pEnv->CallIntMethod (_input, _read, _jbuf, 0, _bufsize); |
| if (m_pEnv->ExceptionOccurred () || n == -1) |
| return EOF; |
| |
| setg (eback (), egptr () - n, egptr ()); // (get) buffer has n chars |
| |
| m_pEnv->GetByteArrayRegion (_jbuf, 0, n, (jbyte*) gptr ()); |
| if (m_pEnv->ExceptionOccurred ()) |
| return EOF; |
| |
| return strstreambuf::underflow (); |
| } |
| |
| |
| JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM* jvm, void* reserved) |
| { |
| return JNI_VERSION_1_2; |
| } |
| |
| |
| JNIEXPORT void JNICALL JNI_OnUnload (JavaVM* jvm, void* reserved) |
| { |
| } |