📄 servlethandler.cpp
字号:
{
if ( !pVariableName )
{
PIPlatform_setLastError( PIAPI_EINVAL );
return NULL;
};
/* ---
Lookup function corresponding to this environment variable
--- */
PMFN fnEnv = (PMFN)PIDB_lookup( pRequestTypes, PIDBTYPE_OPAQUE, pVariableName, 0 );
/* ---
No lookup function?
--- */
if ( !fnEnv )
{
const char *szBuf = (const char *)PIDB_lookup( pPIHTTP->pRequestDB, PIDBTYPE_RFC822, pVariableName, 0 );
if (!szBuf) { PIPlatform_setLastError( PIAPI_NOTSUPPORTED ); };
return szBuf;
};
return (fnEnv)( this, pPIHTTP );
};
const char *Servlet::GetResponseVariable( PIHTTP *pPIHTTP, const char *pVariableName )
{
if ( !pVariableName )
{
PIPlatform_setLastError( PIAPI_EINVAL );
return NULL;
};
/* ---
Lookup function corresponding to this environment variable
--- */
PMFN fnEnv = (PMFN)PIDB_lookup( pResponseTypes, PIDBTYPE_OPAQUE, pVariableName, 0 );
/* ---
No lookup function?
--- */
if ( !fnEnv )
{
const char *szBuf = (const char *)PIDB_lookup( pPIHTTP->pResponseDB, PIDBTYPE_RFC822, pVariableName, 0 );
if (!szBuf) { PIPlatform_setLastError( PIAPI_NOTSUPPORTED ); };
return NULL;
};
return (fnEnv)( this, pPIHTTP );
};
jobject Servlet::CreateSession( PIHTTP *pPIHTTP, JNIEnv *env )
{
enum { BUF_SIZE=63 };
char szSID[BUF_SIZE+1];
// create new SessionID
PIPlatform_getUniqueId(szSID, BUF_SIZE+1);
jclass HttpSessionClass = 0;
jobject HttpSession = 0;
jclass SessionPoolClass = 0;
/* get the HttpSession class */
HttpSessionClass = env->FindClass("org/pi3/servlet/core/Pi3HttpSession");
if (!HttpSessionClass) { goto init_error; };
/* get the HttpSession constructor */
jmethodID HttpSessionMID;
HttpSessionMID = env->GetMethodID( HttpSessionClass, "<init>", "(Ljava/lang/String;)V");
if (!HttpSessionMID) { goto init_error; };
/* get the HttpSession object */
jstring jsSID;
jsSID = env->NewStringUTF(szSID);
HttpSession = env->NewObject( HttpSessionClass, HttpSessionMID, jsSID);
if (!HttpSession) {
goto init_error;
} else {
Log( pPIHTTP, "%s: New HttpSession '%s' created.", GetLogName(), szSID);
};
HttpSession = env->NewGlobalRef(HttpSession);
/* get the SessionPool put method */
jmethodID SessionPutMID;
SessionPoolClass = env->GetObjectClass(SessionPool());
if (!SessionPoolClass) { goto init_error; };
SessionPutMID = env->GetMethodID( SessionPoolClass, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
if (!SessionPutMID) { goto init_error; };
/* put the Session into the session pool */
env->CallObjectMethod(SessionPool(), SessionPutMID, jsSID, HttpSession);
if ( env->ExceptionOccurred() ) { goto init_error; };
return HttpSession;
init_error:
if ( env->ExceptionOccurred() )
{
env->ExceptionDescribe();
env->ExceptionClear();
};
return NULL;
}
jobject Servlet::GetServlet( PIHTTP *pPIHTTP, JNIEnv *env, const char *pPath ) {
Log( pPIHTTP, "%s: GetServlet() for path '%s' called.", GetLogName(), pPath);
/* --- make sub request context --- */
PIHTTP *pChildHTTP = PIHTTP_newChild( pPIHTTP );
PIDB_replace( pChildHTTP->pResponseDB, PIDBTYPE_STRING,
KEY_INT_PATH, (void *)pPath, 0 );
/* --- dispatch the sub request across the mapping phase --- */
int iRet = HTTPCore_dispatch( pChildHTTP, PH_MAPPING, PH_MAPPING );
/* --- copy the childs script name to variable script name --- */
if ( ( iRet != PIAPI_COMPLETED ) || ( pChildHTTP->iStatus != ST_OK ))
{
PIHTTP_delete( pChildHTTP );
return NULL;
};
const char *pScriptName = (const char *)PIDB_lookup( pChildHTTP->pResponseDB,
PIDBTYPE_STRING, KEY_INT_PATH, 0 );
PIHTTP_delete( pChildHTTP );
if (!pScriptName) return NULL;
PIFInfo *pFI = PIFInfo_new( pScriptName );
PIString sServletClass = PIFInfo_getName( pFI );
PIFInfo_delete( pFI );
if ( !sServletClass.Len() ) { return NULL; };
while (strrchr(sServletClass, '.')) strrchr(sServletClass, '.')[0] = '/';
return Context()->getServlet( sServletClass );
};
int Servlet::DoForward( PIHTTP *pPIHTTP, JNIEnv *env, const char *pPath,
jobject request, jobject response ) {
Log( pPIHTTP, "%s: DoForward() for path '%s' called.", GetLogName(), pPath);
/* --- make sub request context --- */
PIHTTP *pChildHTTP = PIHTTP_newChild( pPIHTTP );
/* --- set path --- */
PIDB_replace( pChildHTTP->pRequestDB, PIDBTYPE_STRING,
KEY_HTTP_URI, (void *)pPath, 0 );
PIDB_replace( pChildHTTP->pResponseDB, PIDBTYPE_STRING,
KEY_INT_PATH, (void *)pPath, 0 );
PIDB_replace( pChildHTTP->pResponseDB, PIDBTYPE_OPAQUE,
"SERVLET_ENV", (void *)env, 0 );
PIDB_replace( pChildHTTP->pResponseDB, PIDBTYPE_OPAQUE,
"SERVLET_REQUEST", (void *)request, 0 );
PIDB_replace( pChildHTTP->pResponseDB, PIDBTYPE_OPAQUE,
"SERVLET_RESPONSE", (void *)response, 0 );
/* --- dispatch the sub request across the mapping phase --- */
int iRet = HTTPCore_dispatch( pChildHTTP, PH_MAPPING, PH_DESTROY );
PIHTTP_delete( pChildHTTP );
return iRet;
};
jobject Servlet::GetContextServlet( JNIEnv *env, const char *pServletClass ) {
jobject Servlet = Context()->getServlet( pServletClass );
if (!Servlet) {
jclass ServletClass = env->FindClass(pServletClass);
if (!ServletClass) return NULL;
/* get the Servlet constructor */
jmethodID ServletMID;
ServletMID = env->GetMethodID( ServletClass, "<init>", "()V" );
if (!ServletMID) return NULL;
/* get the Servlet object */
Servlet = env->NewObject( ServletClass, ServletMID);
if (!Servlet) {
return NULL;
} else {
Log( "%s: Servlet '%s' created.", GetLogName(), pServletClass );
};
Servlet = env->NewGlobalRef(Servlet);
Context()->registerServlet( pServletClass, Servlet );
/* invoke the Servlet.init method */
jmethodID ServletInitMID;
ServletInitMID = env->GetMethodID( ServletClass, "init",
"(Ljavax/servlet/ServletConfig;)V");
if (!ServletInitMID) return NULL;
env->CallVoidMethod(Servlet, ServletInitMID, jServletConfig);
if (env->ExceptionOccurred())
{
env->ExceptionDescribe();
env->ExceptionClear();
return NULL;
};
};
return Servlet;
};
int Servlet::Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
{
if ( iPhase!=PH_HANDLE ) return PIAPI_ERROR;
PIDB *pR = tPIHTTP.pResponseDB;
JNIEnv *env = 0; /* pointer to native method interface */
const char *pServletName = 0;
jboolean isSingleThread = false;
jclass ServletClass = 0;
jobject Servlet = 0;
jclass ServletUtilsClass = 0;
jobject ServletUtilsObject = 0;
jclass HttpRequestClass = 0;
jobject HttpRequestObject = 0;
jclass HttpResponseClass = 0;
jobject HttpResponseObject = 0;
jthrowable Exception = 0;
int iRet = PIAPI_COMPLETED;
if (!PIHTTP_isChild( &tPIHTTP )) {
iRet = JVM()->AttachCurrentThread((void **)&env, NULL);
if (iRet) {
Log( &tPIHTTP, "%s: Error when trying to instantiate JVM.", GetLogName());
return PIAPI_ERROR;
} else {
Log( &tPIHTTP, "%s: JVM attached.", GetLogName());
};
} else {
env = (JNIEnv *)PIDB_lookup( pR, PIDBTYPE_OPAQUE, "SERVLET_ENV", 0 );
};
// Ascertain ServletName from Path and load Servlet
if (!jServlet) {
if (!sClassName.Len())
{
const char *pPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
KEY_INT_PATH, 0 );
if (!pPath) goto init_error;
PIFInfo *pFI = PIFInfo_new( pPath );
sClassName = PIFInfo_getName( pFI );
PIFInfo_delete( pFI );
};
if ( !sClassName.Len() ) { goto init_error; };
while (strchr(sClassName, '.')) strchr(sClassName, '.')[0] = '/';
Servlet = GetContextServlet( env, sClassName );
if (!Servlet) { goto init_error; };
} else {
Servlet = jServlet;
};
ServletClass = env->GetObjectClass(Servlet);
/* get the ServletUtils class */
ServletUtilsClass = env->FindClass("org/pi3/servlet/util/Pi3ServletUtils");
if (!ServletUtilsClass) { goto init_error; }
/* get the ServletUtils constructor */
jmethodID ServletUtilsMID;
ServletUtilsMID = env->GetMethodID(ServletUtilsClass, "<init>", "(II)V");
if (!ServletUtilsMID) { goto init_error; };
/* get the ServletUtils object */
ServletUtilsObject = env->NewObject( ServletUtilsClass, ServletUtilsMID,
(int)&tPIHTTP, (int)this);
if (!ServletUtilsObject) { goto init_error; };
/* get the Pi3ServletUtils.grabStackTrace method */
jmethodID grabStackTraceMID;
grabStackTraceMID = env->GetMethodID(ServletUtilsClass, "grabStackTrace",
"(Ljava/lang/Throwable;)Ljava/lang/String;");
if (!grabStackTraceMID) { goto init_error; };
if (PIHTTP_isChild( &tPIHTTP )) {
HttpRequestObject = (jobject)PIDB_lookup( tPIHTTP.pResponseDB,
PIDBTYPE_OPAQUE, "SERVLET_REQUEST", 0 );
if (HttpRequestObject) {
Log( &tPIHTTP, "%s: HttpServletRequest copied.", GetLogName());
} else {
goto init_error;
};
HttpResponseObject = (jobject)PIDB_lookup( tPIHTTP.pResponseDB,
PIDBTYPE_OPAQUE, "SERVLET_RESPONSE", 0 );
if (HttpResponseObject) {
Log( &tPIHTTP, "%s: HttpServletResponse copied.", GetLogName());
/* get the ServletResponse class */
HttpResponseClass = env->GetObjectClass(HttpResponseObject);
if (!HttpResponseClass) { goto init_error; };
} else {
goto init_error;
};
} else {
/* get the ServletRequest class */
HttpRequestClass = env->FindClass("org/pi3/servlet/core/Pi3HttpServletRequest");
if (!HttpRequestClass) { goto init_error; };
/* get the ServletRequest constructor */
jmethodID HttpRequestConstructorMID;
HttpRequestConstructorMID = env->GetMethodID( HttpRequestClass, "<init>",
"(IILorg/pi3/servlet/util/Pi3ServletUtils;Ljava/util/Hashtable;)V");
if (!HttpRequestConstructorMID) { goto init_error; };
if (Context()->validateSessions(env)) { goto init_error; };
/* get the ServletRequest object */
HttpRequestObject = env->NewObject( HttpRequestClass, HttpRequestConstructorMID,
(int)&tPIHTTP, (int)this, ServletUtilsObject, SessionPool() );
if (!HttpRequestObject) {
goto init_error;
} else {
Log( &tPIHTTP, "%s: HttpServletRequest created.", GetLogName());
};
/* get the ServletResponse class */
HttpResponseClass = env->FindClass("org/pi3/servlet/core/Pi3HttpServletResponse");
if (!HttpResponseClass) { goto init_error; };
/* get the ServletResponse constructor */
jmethodID HttpResponseConstructorMID;
HttpResponseConstructorMID = env->GetMethodID( HttpResponseClass, "<init>",
"(IILorg/pi3/servlet/util/Pi3ServletUtils;Ljavax/servlet/http/HttpServletRequest;)V");
if (!HttpResponseConstructorMID) { goto init_error; };
/* get the ServletResponse object */
HttpResponseObject = env->NewObject( HttpResponseClass, HttpResponseConstructorMID,
(int)&tPIHTTP, (int)this, ServletUtilsObject, HttpRequestObject );
if (!HttpResponseObject) {
goto init_error;
} else {
Log( &tPIHTTP, "%s: HttpServletResponse created.", GetLogName());
};
};
/* get the Servlet's thread model */
jmethodID isSingleThreadMID;
isSingleThreadMID = env->GetMethodID(ServletUtilsClass, "isSingleThread",
"(Ljava/lang/Object;)Z");
if (!isSingleThreadMID) { goto init_error; };
isSingleThread = env->CallBooleanMethod(ServletUtilsObject, isSingleThreadMID, Servlet);
if ( env->ExceptionOccurred() ) { goto init_error; };
/* invoke the Servlet.service method */
jmethodID ServiceMID;
ServiceMID = env->GetMethodID(ServletClass, "service",
"(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V");
if (!ServiceMID) { goto init_error; };
if (isSingleThread) PISync_lock( pMutex );
env->CallVoidMethod(Servlet, ServiceMID, HttpRequestObject, HttpResponseObject);
if (isSingleThread) PISync_unlock( pMutex );
if ( env->ExceptionOccurred() ) { goto init_error; };
Log( &tPIHTTP, "%s.service() method invoked.", (const char *)sClassName );
/* invoke the ServletResponse.getServerResult method */
jmethodID GetResultMID;
GetResultMID = env->GetMethodID(HttpResponseClass, "getServerResult", "()I");
if (!GetResultMID) { goto init_error; };
iRet = env->CallIntMethod(HttpResponseObject, GetResultMID);
if ( env->ExceptionOccurred() ) { goto init_error; };
goto done;
init_error:
Exception = env->ExceptionOccurred();
if ( Exception && ServletUtilsObject && grabStackTraceMID )
{
Log( &tPIHTTP, "%s: Exception occured: ", GetLogName());
/* invoke ServletUtils.grabStackTrace */
jstring jmsg = (jstring)env->CallObjectMethod(ServletUtilsObject,
grabStackTraceMID, Exception);
if (jmsg) {
jboolean isCopy;
const char *msg = env->GetStringUTFChars(jmsg, &isCopy);
Log( &tPIHTTP, msg);
HTTPCore_logError(&tPIHTTP, msg);
env->ReleaseStringUTFChars(jmsg, msg);
}
else
{
HTTPCore_logError( &tPIHTTP, "%s: Unknown exception occured. ",
GetLogName());
}
env->ExceptionDescribe();
env->ExceptionClear();
} else {
HTTPCore_logError(&tPIHTTP, "%s: Check your CLASSPATH settings.",
GetLogName());
};
iRet = HTTPUtil_doHTTPError(&tPIHTTP, ST_INTERNALERROR);
done:
/* We are done. */
if (!PIHTTP_isChild( &tPIHTTP )) {
if (!JVM()->DetachCurrentThread()/* !jvm->DestroyJavaVM() **/) {
Log( &tPIHTTP, "%s: JVM detached.", GetLogName());
} else {
Log( &tPIHTTP, "%s: Error when trying to detach JVM.", GetLogName());
};
};
return iRet;
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Servlet_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
return HandlerBaseServlet_constructor( pObj, PI_NEW( Servlet( pObj,
iArgc, ppArgv, "Servlet handler" ) ) );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Servlet_destructor( PIObject *pObj, int,
const char *[] )
{
delete (Servlet *)PIObject_getUserData( pObj );
return PIAPI_COMPLETED;
}
#if 0
/*___+++CNF_BEGIN+++___*/
<Class>
Name ServletClass
Type LogicExtension
Library Servlet
OnClassLoad HandlerBaseServlet_onClassLoad
Constructor Servlet_constructor
CopyConstructor HandlerBaseServlet_copyConstructor
Destructor Servlet_destructor
Execute HandlerBaseServlet_execute
</Class>
<Object>
Name Servlet
Class ServletClass
Context ServletContainer
</Object>
/*___+++CNF_END+++___*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -