⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 servlethandler.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	{
	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 + -