Scala+DBMS+Web スカラ座の夜

2011年10月24日

htmlSrv class

Filed under: Framework,Scala — admin @ 10:03 PM

WEBフレームワークの中心的クラスのhtmlSrvを拡張しています。

主な拡張点は、

  1. Cookieによるセッション管理機能
  2. 認証機能
  3. ページ割り込み機能

リダイレクションとフォワードによって、別ページを割り込ませます。
この機能によって、ログイン画面や、成人ですかという画面を割り込ませることができます。
設定は、TOMCATのWEB.XMLによって設定情報を定義するので、
この定義情報を取り出すためのコードがかなりのボリュームを持っています。

それと、HTMLパーサの呼び出しに引数を1つ追加し、PrintWriterを渡しています。
従来のコードでは、いったん1ページ分のデータをStringに格納してから
Outputしていましたが、読み込み次第、出力することができます。
大きなページでは反応がよくなります。

まだ、拡張し続けているの参考まで。

package ews.servlet
import org.apache.log4j.Logger
import java.io._
import java.net.{URLDecoder,URLEncoder}
import javax.servlet._
import javax.servlet.http._
import ews.servlet.sp._
import ews.servlet.session._

/**
 * The dynamic page is made by HttpServlet.
 */
class htmlSrv extends HttpServlet {
	lazy val logger = Logger.getLogger(classOf[ewsSrv])
	var context : ServletContext = null
	var DocumentRoot : String = null	// DocumentRoot

	var loginUrl : String = null			// Login画面のURL
	var checkUrl : String = null			// Cookie設定画面のURL
	var registrationUrl : String = null		// 登録画面のURL
	var registrationPath : String = null	// 登録が必要なコンテンツが格納されるディレクトリ (このバージョンでは1つしか指定できない)
	var authPath : String = null			// 認証が必要なコンテンツが格納されるディレクトリ (このバージョンでは1つしか指定できない)
	var checkCookie : String = null			// チェック画面を表示させる場合にセットされるCookieの名称
	var registrationCookie : String = null	// 登録画面を表示させる場合にセットされるCookieの名称

	var message = "Not Found :The requested URL was not found on this server."	// Not Found
	var characode = "utf-8"
	override def init(config : ServletConfig) : Unit = {
		super.init(config)
		context = config.getServletContext
		DocumentRoot = config.getInitParameter("html")	// WEB-INF/web.xml
		loginUrl = config.getInitParameter("login")	// WEB-INF/web.xml
		if(loginUrl == null)
			loginUrl = "/toro/login"
		checkUrl = config.getInitParameter("check")	// WEB-INF/web.xml
		if(checkUrl != null && checkUrl.length == 0)
			checkUrl = null
		registrationUrl = config.getInitParameter("registration")	// WEB-INF/web.xml
		if(registrationUrl != null && registrationUrl.length == 0)
			registrationUrl = null
		registrationPath = config.getInitParameter("registrationpath")	// WEB-INF/web.xml
		if(registrationPath != null && registrationPath.length == 0)
			registrationPath = null
		authPath = config.getInitParameter("authpath")	// WEB-INF/web.xml
		if(authPath != null && authPath.length == 0)
			authPath = null
		checkCookie = config.getInitParameter("checkcookie")	// WEB-INF/web.xml
		if(checkCookie != null && checkCookie.length == 0)
			checkCookie = null
		registrationCookie = config.getInitParameter("registrationcookie")	// WEB-INF/web.xml
		if(registrationCookie != null && registrationCookie.length == 0)
			registrationCookie = null
	}
	override def doGet(request : HttpServletRequest, response : HttpServletResponse) : Unit = {
		gen(request, response)
	}
	override def doPost(request : HttpServletRequest, response : HttpServletResponse) : Unit = {
		gen(request, response)
	}
	// generate HTML
	def gen(request : HttpServletRequest, response : HttpServletResponse) : Unit = {
		logger.debug("htmlSrv ################# start")
		var htmlFile = ""
		var parsersw = if(request.getParameter("parsersw") !=null){request.getParameter("parsersw").toInt}else{0}	// 強制的にHTMLパーサを切り替える
		request.setCharacterEncoding(characode)
   		val url = request.getRequestURL
		val uri = request.getRequestURI
		var spth:String = request.getServletPath
		// URLからパラメータ情報を取り出す
		spth = spth.replace("/","")
		val ur = uri.split("/")
		var fg = false
		ur.foreach({v =>
			if(fg){
				htmlFile += "/" + v
			}
			if(v.equals(spth))
				fg = true
		})
		val contentFilePath = DocumentRoot + htmlFile // コンテンツのファイルフルパス
		var ct = ContentTypeDef.changeFromFileNameToContentType(htmlFile)
		val sw = ContentTypeDef.getCtype(ct) match {
		  case "text" => {
   			if(htmlFile.lastIndexOf(".html") > 0 || htmlFile.lastIndexOf(".htm") > 0){
   				val session = new Session(request,response)	// Cookie
   				if(checkUrl != null				// URLが定義されているか?
   				    && checkCookie != null		// クッキーが定義されているか?
   				    && checkUrl.lastIndexOf(htmlFile) == -1		// チェック用のURLの場合はフォワードさせない
   				    && session.getAttribute(checkCookie) == null){// 特定のクッキーが値の有無によって制御したい場合
   					println("Cookie oc none checkUrl="+checkUrl + " htmlFile=" + htmlFile + " " + checkUrl.lastIndexOf(htmlFile))
// for test
   					session.cookie.setCookie(checkCookie,java.lang.Math.random.toString ,-1)
   					val rd = context.getRequestDispatcher(checkUrl)
   					rd.forward(request, response)
   					return
   				} else {
   					println("checkUrl is null & Cookie oc="+session.getAttribute(checkCookie))
   				}
   				if(registrationCookie != null		// クッキーが定義されているか?
   				    && registrationUrl != null		// URLが定義されているか?
   				    && registrationUrl.lastIndexOf(htmlFile) == -1		// 登録用のURLの場合はフォワードさせない
   				    && session.getAttribute(registrationCookie) == null // 特定のクッキーが値の有無によって制御したい場合
   					&& registrationPath != null
   					&& registrationPath.equals(getPath(htmlFile))){	// 指定されたパスが登録が必要なディレクトリか?
   					println("registrationCookie & htmlFile="+htmlFile)
   					val rd = context.getRequestDispatcher(registrationUrl)
   					rd.forward(request, response)
   					return
   				}
   				if((authPath != null && authPath.equals(getPath(htmlFile))) || htaccess(htmlFile)){	// 指定されたパスが認証が必要なディレクトリか?
   					if(!session.isLogin){	// 認証がされているか?
   						println("htmlSrv ############ Longin画面を表示 -> loginUrl=" + loginUrl+"?url=" + URLEncoder.encode(uri.toString))
   						logger.debug("htmlSrv ############ Longin画面を表示 -> loginUrl=" + loginUrl+"?url=" + URLEncoder.encode(uri.toString))
   						response.sendRedirect(loginUrl+"?uri=" + URLEncoder.encode(uri.toString))
   						val out = response.getWriter
   						out.close
   						return
   					}
   				}
   			}
		    if(ct.equals("text/html")){parsersw}else{11}
		  }
		  case "image" => 10
		  case "application" => if(ct.equals("application/xml")){2}else{10}
		  case "audio" => 10
		  case "video" => 10
		  case _ => 10
		}
		logger.debug("htmlSrv ############ "+ct+" ##### htmlFile="+htmlFile)
		println("htmlSrv ############ "+ct+" ##### htmlFile="+htmlFile)
		if(sw == 0){
			ct += "; charset=" + characode
			response.setContentType(ct)
			val sp = new Htmlparse6Sp(request, response, contentFilePath)// Dynamic page. use the org.htmlparser.sax._
			val r = sp.io
		  println("htmlSrv sw=0 Htmlparse6Sp r="+r+ " " + contentFilePath)
			if(!r){
        		System.err.println("Not Found the "+htmlFile)
				error(404,"Not Found "+htmlFile,response)
			}
		} else if(sw == 11){
			ct += "; charset=" + characode
			response.setContentType(ct)
			val sp = new TextSp(request, response, contentFilePath)
			sp.characode = characode
			val r = sp.io
			if(!r){
        		System.err.println("Not Found the "+htmlFile)
				error(404,"Not Found "+htmlFile,response)
			}
		} else if(sw < 10){	// HTMLパーサ評価用
			val ssp = sw match {
			  // It reads a file, and the content is output as it is.
			  case 1 => new StraightSp(request, response, contentFilePath)
			  // The HTML file is read by the Scala XML loader. The character string is converted and XML is output.
			  case 2 => new XmlSp(request, response, contentFilePath)
			  // The analytical result of HTML parser is converted in the character string and it outputs it.
			  case 3 => new Htmlparse2Sp(request, response, contentFilePath)// javax.swing.text.html.parser._
			  case 4 => new HtmlparseSp(request, response, contentFilePath)	// nu.validator.htmlparser._ for TEST
			  case 5 => new ValidatorHtmlparserSp(request, response, contentFilePath)	// nu.validator.htmlparser for TEST
			  case 6 => new Htmlparse3Sp(request, response, contentFilePath)// org.cyberneko.html.parsers._ for TEST
			  case 7 => new Htmlparse4Sp(request, response, contentFilePath)// org.htmlparser.sax._ for TEST
			  case 8 => new Ssp(request, response, contentFilePath)			// Dynamic page. use the nu.validator.htmlparser
			  case 9 => new Htmlparse5Sp(request, response, contentFilePath)// Dynamic page. use the org.htmlparser.sax._
			}
	   		val re = if(ssp.html != null){
	   			response.setStatus(200)
	   			ssp.toString
	   		} else {
				error(404,"Not Found "+htmlFile,response)
				return
	   		}
	   		ct += "; charset=" + characode
			response.setContentType(ct)
			val out = response.getWriter
			out.println(re)	// output html data
			out.flush
			out.close
		} else {
			var stream:FileInputStream = null
			try {
				val binaryFile = new java.io.File(contentFilePath)
				if(binaryFile.exists){
					response.setContentType(ct)
					response.setStatus(200)
					stream = new FileInputStream(binaryFile)
					val buf:Array[Byte] = new Array(1024)
					var out = response.getOutputStream
					while(stream.available != 0){
						val i = stream.read(buf,0,1024)
						out.write(buf,0,i)
					}
				} else {
	        		System.err.println("Not Found the "+htmlFile)
					error(404,"Not Found "+htmlFile,response)
				}
			} catch {
	        	case e:IOException => {
	        		System.err.println("IOException "+e.getMessage)
	        		error(500,"Internal Server Error",response)
	        	}
	        	case e:Exception => {
	        		System.err.println("Exception "+e.getMessage)
	        		error(500,"Internal Server Error",response)
	        	}
			} finally {
				if(stream != null)
				  stream.close
			}
		}
//		logger.debug(" #### End")
	}
	// for error
	def error(status:Int,message:String, response : HttpServletResponse) :Unit = {
		response.setContentType("text/html")
		response.setStatus(status,message)
		var out = response.getOutputStream
		out.close
	}
	// htaccessファイルがHTMLファイルが置かれているディレクトにあるかを調べる
	// このファイルがあればそのディレクトにあるコンテンツへのアクセスは認証が必要となる。
	var htaccess = "htaccess.txt"
	def htaccess(fileName:String) : Boolean = {
		val point = fileName.lastIndexOf("/")
	    if (point == -1) {
	    	return false
	    }
        val htaccessPath = fileName.substring(0,point+1)
        val path = DocumentRoot + htaccessPath + htaccess
		try {
			val htmlFile = new java.io.File(path)
	        return htmlFile.exists
	    } catch {
	    	case e:IOException => {
	    		System.err.println("IOException "+e.getMessage)
	        }
	    }
		return false
	}
	// ファイル名からパスを取り出す
	def getPath(fileName:String) : String = {
		val point = fileName.lastIndexOf("/")
	    if (point == -1) {
	    	return null
	    }
        val htaccessPath = fileName.substring(0,point+1)
        return DocumentRoot + htaccessPath
	}
}

Comments

comments

Powered by Facebook Comments

コメントはまだありません »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

コメントを投稿するにはログインしてください。

Powered by WordPress