summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--sources/scala/collection/mutable/ResizableArray.scala9
-rw-r--r--sources/scala/tools/servletEngine/Connector.scala25
-rw-r--r--sources/scala/tools/servletEngine/ExcepServlet.scala23
-rw-r--r--sources/scala/tools/servletEngine/Main.scala25
-rw-r--r--sources/scala/tools/servletEngine/Mapping.scala24
-rw-r--r--sources/scala/tools/servletEngine/SERVLET.scala29
-rw-r--r--sources/scala/tools/servletEngine/ScalaCookiee.scala14
-rw-r--r--sources/scala/tools/servletEngine/ScalaServlet.scala59
-rw-r--r--sources/scala/tools/servletEngine/ServletException.scala13
-rw-r--r--sources/scala/tools/servletEngine/http/HTTP.scala172
-rw-r--r--sources/scala/tools/servletEngine/http/HttpConnector.scala12
-rw-r--r--sources/scala/tools/servletEngine/http/HttpException.scala27
-rw-r--r--sources/scala/tools/servletEngine/http/HttpFile.scala38
-rw-r--r--sources/scala/tools/servletEngine/http/HttpHandler.scala83
-rw-r--r--sources/scala/tools/servletEngine/http/HttpInputStream.scala145
-rw-r--r--sources/scala/tools/servletEngine/http/HttpOutputStream.scala102
-rw-r--r--sources/scala/tools/servletEngine/http/HttpProcessor.scala9
-rw-r--r--sources/scala/tools/servletEngine/http/HttpServletPro.scala84
-rw-r--r--sources/scala/xml/path/Expression.scala67
-rw-r--r--sources/scala/xml/path/Parser.scala34
-rw-r--r--sources/scala/xml/path/Scanner.scala1
-rw-r--r--sources/scala/xml/path/Tokens.scala4
23 files changed, 970 insertions, 45 deletions
diff --git a/Makefile b/Makefile
index 234913df15..baf05b4606 100644
--- a/Makefile
+++ b/Makefile
@@ -149,6 +149,13 @@ DTD2SCALA_RSRC_LIST += $(filter %.xml,$(DTD2SCALA_LIST))
DTD2SCALA_RSRC_FILES += $(filter %.xml,$(DTD2SCALA_SOURCES))
DTD2SCALA_RSRC_OUTPUTDIR = $(DTD2SCALA_ROOT:$(PROJECT_SOURCEDIR)/%=$(PROJECT_OUTPUTDIR)/%)
+# servletEngine
+SERVLETENGINE_ROOT = $(PROJECT_SOURCEDIR)/scala/tools/servletEngine
+SERVLETENGINE_LIST += $(call READLIST,$(PROJECT_LISTDIR)/servletEngine.lst)
+SERVLETENGINE_SOURCES += $(SERVLETENGINE_LIST:%=$(SERVLETENGINE_ROOT)/%)
+SERVLETENGINE_SC_FILES += $(SERVLETENGINE_SOURCES)
+SERVLETENGINE_SC_CLASSPATH = $(PROJECT_CLASSPATH)
+
# scala ant tasks
SCALA4ANT_ROOT = $(PROJECT_SOURCEDIR)/scala/tools/scala4ant
SCALA4ANT_LIST += $(call READLIST,$(PROJECT_LISTDIR)/scala4ant.lst)
@@ -156,6 +163,8 @@ SCALA4ANT_SOURCES += $(SCALA4ANT_LIST:%=$(SCALA4ANT_ROOT)/%)
SCALA4ANT_SC_FILES += $(SCALA4ANT_SOURCES)
SCALA4ANT_SC_CLASSPATH = $(PROJECT_CLASSPATH):$(ANT_JARFILE)
+
+
# scalatest
SCALATEST_ROOT = $(PROJECT_SOURCEDIR)/scala/tools/scalatest
SCALATEST_LIST += $(call READLIST,$(PROJECT_LISTDIR)/scalatest.lst)
@@ -197,6 +206,7 @@ all : interpreter
all : scaladoc
all : scalap
all : dtd2scala
+all : servletEngine
all : scala4ant
all : scalatest
@@ -249,6 +259,7 @@ scaladoc : .latest-scaladoc-rsrc
scalap : .latest-scalap-sc
dtd2scala : .latest-dtd2scala-sc
dtd2scala : .latest-dtd2scala-rsrc
+servletEngine : .latest-servletEngine-sc
scala4ant : .latest-scala4ant-sc
scalatest : .latest-scalatest-jc
boottest : .latest-boottest
@@ -269,6 +280,7 @@ library-doc : .latest-library-sdc
.PHONY : scaladoc
.PHONY : scalap
.PHONY : dtd2scala
+.PHONY : servletEngine
.PHONY : scala4ant
.PHONY : scalatest
.PHONY : boottest
@@ -419,6 +431,10 @@ cvs-fix-perms :
$(DTD2SCALA_RSRC_OUTPUTDIR))
touch $@
+.latest-servletEngine-sc : $(SERVLETENGINE_SC_FILES)
+ @$(make) sc target=SERVLETENGINE SERVLETENGINE_SC_FILES='$?'
+ touch $@
+
.latest-scala4ant-sc : $(SCALA4ANT_SC_FILES)
@$(make) sc target=SCALA4ANT SCALA4ANT_SC_FILES='$?'
touch $@
diff --git a/sources/scala/collection/mutable/ResizableArray.scala b/sources/scala/collection/mutable/ResizableArray.scala
index 5337a5212f..f2ea93b2fa 100644
--- a/sources/scala/collection/mutable/ResizableArray.scala
+++ b/sources/scala/collection/mutable/ResizableArray.scala
@@ -27,9 +27,12 @@ abstract class ResizableArray[A] with Iterable[A] {
*/
protected def ensureSize(n: Int): Unit = {
if ((size + n) > array.length) {
- val newar: Array[A] = new Array(array.length * 2);
- arraycopy(array, 0, newar, 0, size);
- array = newar;
+ var nsize = array.length;
+ while( nsize < size + n )
+ nsize = nsize * 2;
+ val newar: Array[A] = new Array(nsize);
+ arraycopy(array, 0, newar, 0, size);
+ array = newar;
}
}
diff --git a/sources/scala/tools/servletEngine/Connector.scala b/sources/scala/tools/servletEngine/Connector.scala
new file mode 100644
index 0000000000..b315d16ef5
--- /dev/null
+++ b/sources/scala/tools/servletEngine/Connector.scala
@@ -0,0 +1,25 @@
+package scala.tools.servletEngine;
+
+import java.net.{ Socket, ServerSocket };
+
+/** for every port, there is one connector that instantiates a handler
+ * per client connection
+ */
+abstract class Connector(thePort: Int) extends Thread {
+ super.setDaemon(true);
+
+ /** concrete instances of Connectors must override this with a factory
+ * for protocol handlers
+ */
+ def makeHandler(s: Socket): Thread; //Handler;
+
+ final val port = thePort;
+ final val serverSocket = new ServerSocket(thePort);
+
+ // @todo: handler pooling
+ final override def run() = while(true) {
+ val client = serverSocket.accept(); /* returns a socket upon connection */
+ val t = makeHandler(client);
+ t.start();
+ }
+}
diff --git a/sources/scala/tools/servletEngine/ExcepServlet.scala b/sources/scala/tools/servletEngine/ExcepServlet.scala
new file mode 100644
index 0000000000..822b9e8097
--- /dev/null
+++ b/sources/scala/tools/servletEngine/ExcepServlet.scala
@@ -0,0 +1,23 @@
+package scala.tools.servletEngine;
+import java.io._;
+import scala.xml._;
+import scala.collection.mutable.HashMap ;
+
+class ExcepServlet() extends ScalaServlet{
+
+override def doGetXML(info: HashMap[String,String]): Node = {
+ val code:String= info("code");
+ val detail:String=info("detail");
+
+ <html>
+ <head>
+ <title>SERVLET ERROR</title>
+ </head>
+ <body>
+ <big>Attention,erreur dans la servlet</big>
+ <br/>type de l erreur: { code }<br/>{ detail }
+ </body>
+ </html>
+}
+
+}
diff --git a/sources/scala/tools/servletEngine/Main.scala b/sources/scala/tools/servletEngine/Main.scala
new file mode 100644
index 0000000000..0ec47d735c
--- /dev/null
+++ b/sources/scala/tools/servletEngine/Main.scala
@@ -0,0 +1,25 @@
+package scala.tools.servletEngine;
+
+import java.net.ServerSocket;
+
+/** Main loop of the servlet engine, opens a ServerSocket
+ * and spawns a thread when accepting a client connections.
+ *
+ * servletEngine depends on mappings
+ * <ul>
+ * <li>p: ports to protocol, and</li>
+ * <li>s: url to servlet</li>
+ * </ul>
+ */
+object Main {
+
+ //@todo make this configurable with ports and handlers
+ private var hcon: Thread = new http.HttpConnector(8000);
+ def main(args: Array[String]): Unit = {
+ Console.println("starting http connector at 8000");
+ hcon.start();
+ while(true) {
+ Thread.sleep(50000)
+ }
+ }
+}
diff --git a/sources/scala/tools/servletEngine/Mapping.scala b/sources/scala/tools/servletEngine/Mapping.scala
new file mode 100644
index 0000000000..b389c964d9
--- /dev/null
+++ b/sources/scala/tools/servletEngine/Mapping.scala
@@ -0,0 +1,24 @@
+package scala.tools.servletEngine;
+
+import java.io._;
+
+class Mapping(){
+
+ val map = new File(http.HTTP.SERVER_LOCATION,http.HTTP.translateFilename("map.prop"));
+ val myProp = new java.util.Properties();
+
+ try{
+ myProp.load(new FileInputStream(map));
+ }
+
+ catch{
+ case e:FileNotFoundException => System.out.println("FileNotFoundException ");
+ case e:IOException => System.out.println("IOException");
+ case e: IllegalArgumentException => System.out.println(" IllegalArgumentException");
+ }
+
+ def switch(original:String):String={
+ myProp.getProperty(original);
+ }
+
+}
diff --git a/sources/scala/tools/servletEngine/SERVLET.scala b/sources/scala/tools/servletEngine/SERVLET.scala
new file mode 100644
index 0000000000..7badf7d826
--- /dev/null
+++ b/sources/scala/tools/servletEngine/SERVLET.scala
@@ -0,0 +1,29 @@
+package scala.tools.servletEngine;
+
+import java.io._;
+import java.util._;
+import java.net._;
+
+object SERVLET {
+
+ final val STATUS_OKAY = 50;
+ final val STATUS_NOT_IMPLEMENTED= 60;
+ final val STATUS_FORBIDDEN=70;
+ final val STATUS_NOT_FOUND=80;
+ final val STATUS_BAD_REQUEST= 90;
+ final val STATUS_INTERNAL_ERROR =99;
+
+
+
+ def getCodeMessage (code:int): String = code match {
+
+ case STATUS_OKAY => "OK"
+ case STATUS_BAD_REQUEST=> "Bad Request"
+ case STATUS_FORBIDDEN => "Forbidden"
+ case STATUS_NOT_FOUND => "Not Found"
+ case STATUS_INTERNAL_ERROR => "Server Internal Error"
+ case STATUS_NOT_IMPLEMENTED => "Not Implemented"
+ case _ => "Unknown Code (" + code + ")"
+
+ }
+}
diff --git a/sources/scala/tools/servletEngine/ScalaCookiee.scala b/sources/scala/tools/servletEngine/ScalaCookiee.scala
new file mode 100644
index 0000000000..1215bae48b
--- /dev/null
+++ b/sources/scala/tools/servletEngine/ScalaCookiee.scala
@@ -0,0 +1,14 @@
+package scala.tools.servletEngine;
+
+import java.io._;
+
+class ScalaCookiee(name:String,value:String) {
+
+ def getName():String ={
+ name;
+ }
+
+ def getValue():String={
+ value;
+ }
+}
diff --git a/sources/scala/tools/servletEngine/ScalaServlet.scala b/sources/scala/tools/servletEngine/ScalaServlet.scala
new file mode 100644
index 0000000000..6ece5f0e71
--- /dev/null
+++ b/sources/scala/tools/servletEngine/ScalaServlet.scala
@@ -0,0 +1,59 @@
+package scala.tools.servletEngine;
+
+import java.io.IOException;
+import scala.xml._;
+import scala.collection.mutable.HashMap ;
+import http.HttpOutputStream;
+// import scala.collection.mutable.HashMap
+// val x = new HashMap[String,String]
+// x.update("key","value");
+// x.get("key") match {
+// case Some( value ) => ...
+// case None => ...
+// } x("key")
+
+abstract class ScalaServlet {
+ var output:HttpOutputStream = null;
+ // HashMap[String,String]
+ def doGetXML(info: HashMap[String,String]): scala.xml.Node ;
+
+ final def doGet(out: HttpOutputStream, info: HashMap[String,String]): Unit= {
+ try{
+ out.write( doGetXML( info ).toString() );
+ }
+ catch {
+ case sException:ServletException => ReturnException( sException.returnType(),sException.returnInfo());
+ case ex:Exception => ReturnException(30,"");
+ }
+ }
+
+ final def ReturnException(code:int, detail :String):unit={
+ var info = new HashMap[String,String];
+ info.update("code", SERVLET.getCodeMessage(code) );
+ info.update("detail", detail);
+ new ExcepServlet().doGet(output, info);
+ return null;
+
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sources/scala/tools/servletEngine/ServletException.scala b/sources/scala/tools/servletEngine/ServletException.scala
new file mode 100644
index 0000000000..4f9826d679
--- /dev/null
+++ b/sources/scala/tools/servletEngine/ServletException.scala
@@ -0,0 +1,13 @@
+package scala.tools.servletEngine;
+import java.io._;
+import java.util._;
+import java.lang.Math._;
+import scala.xml._;
+class ServletException(typ:int,info:String) extends Exception{
+ def returnType():int={typ;}
+ def returnInfo():String={info;}
+
+}
+
+
+
diff --git a/sources/scala/tools/servletEngine/http/HTTP.scala b/sources/scala/tools/servletEngine/http/HTTP.scala
new file mode 100644
index 0000000000..3672e6c0e0
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HTTP.scala
@@ -0,0 +1,172 @@
+package scala.tools.servletEngine.http;
+
+import java.io._;
+import java.net._;
+import scala.collection.mutable.HashMap;
+
+/** constants */
+object HTTP {
+ val SERVER_INFO: String= "JNP-HTTPD/1.0";
+ val SERVLET: String= "/servlet/";
+ val SERVER_LOCATION: File= new File(System.getProperty("user.dir"));
+ val HTML_ROOT: File= new File(SERVER_LOCATION,"html");
+ val PORT:Int = 80 ;
+ val DEFAULT_INDEX: String = "index.html";
+
+ final val METHOD_GET : String="GET";
+ final val METHOD_POST : String="POST";
+ final val METHOD_HEAD : String="HEAD";
+
+
+ final val STATUS_OKAY = 200;
+ final val STATUS_NO_CONTENT= 204;
+ final val STATUS_MOVED_PERMANENTLY= 301;
+ final val STATUS_MOVED_TEMPORARILY=302;
+ final val STATUS_BAD_REQUEST=400;
+ final val STATUS_FORBIDDEN=403;
+ final val STATUS_NOT_FOUND=404;
+ final val STATUS_NOT_ALLOWED=405;
+ final val STATUS_INTERNAL_ERROR =500;
+ final val STATUS_NOT_IMPLEMENTED=501;
+
+ def getCodeMessage (code:int): String = code match {
+
+ case STATUS_OKAY => "OK"
+ case STATUS_NO_CONTENT => "No Content"
+ case STATUS_MOVED_PERMANENTLY => "Moved Permantely"
+ case STATUS_MOVED_TEMPORARILY => "Moved Temporarily"
+ case STATUS_BAD_REQUEST => "Bad Request"
+ case STATUS_FORBIDDEN => "Forbidden"
+ case STATUS_NOT_FOUND => "Not Found"
+ case STATUS_NOT_ALLOWED => "Method Not Allowed"
+ case STATUS_INTERNAL_ERROR => "Server Internal Error"
+ case STATUS_NOT_IMPLEMENTED => "Not Implemented"
+ case _ => "Unknown Code (" + code + ")"
+
+ }
+
+ def canonicalizePath(path: String):String={
+ val chars:Array[char] = path.toCharArray();
+ var length:int = chars.length;
+ var idx:int =0;
+ var odx:int =0;
+
+ idx = indexOf (chars, length,'/',odx);
+ while ( idx < (length - 1)){
+ val ndx:int = indexOf (chars, length,'/',idx + 1);
+ var kill = -1;
+ if (ndx == idx + 1){
+ kill = 1;
+ }
+ else if((ndx >= idx + 2) && (chars(idx + 1 )=='.')){
+ if(ndx == idx + 2){
+ kill = 2;
+ } else if ((ndx == idx +3) && (chars(idx + 2) == '.')){
+
+ kill = 3;
+ while ((idx > 0) && (chars({idx = idx -1; idx}) !='/'))
+ kill = kill +1;
+
+ }}
+ if (kill == -1){
+ odx = ndx;
+ } else if (idx +kill >= length){
+ odx = idx +1;
+ length =odx ;
+ } else {
+ length =length- kill;
+ System.arraycopy(chars,idx +1+kill, chars,idx +1,length-idx-1);
+
+ odx =idx;
+ }
+ idx = indexOf (chars, length,'/',odx);
+ }
+
+ return new String (chars, 0, length);
+ }
+
+
+ def indexOf (chars: Array[char],length:int,chr: char,from:int):int={
+ var frome :int = from;
+ while ((frome < length) && (chars(frome) != chr))
+ frome=frome + 1;
+ return frome
+ }
+
+
+ def translateFilename (filename:String ):String ={
+ val result:StringBuffer = new StringBuffer ();
+ try {
+ var idx = 0;
+ var odx = 0;
+ idx = filename.indexOf ('/',odx);
+ while (idx != -1){
+ result.append(filename.substring(odx,idx)).append(File.separator);
+ odx= idx +1;
+ idx = filename.indexOf ('/',odx);
+ }
+ result.append(filename.substring(odx));}
+ catch{
+ case e :java.lang.NullPointerException => System.out.println("attention erreur");
+ }
+
+ return result.toString();
+ }
+
+ final var mimeTypes = new HashMap[String, String]();
+
+ mimeTypes.update("gif", "image/gif");
+ mimeTypes.update("jpeg", "image/jpeg");
+ mimeTypes.update("jpg", "image/jpeg");
+ mimeTypes.update("html", "text/html");
+ mimeTypes.update("htm" , "text/html");
+
+ def guessMimeType(fileName: String): String ={
+ val i =fileName.lastIndexOf(".");
+ val typ = mimeTypes.get(fileName.substring (i + 1).toLowerCase()).asInstanceOf[String];
+ if (typ != null) {typ} else {"text/plain"};
+
+ }
+
+
+ def processing(inf: String): HashMap[String, String]={
+ var hashList = new HashMap[String, String];
+ var info = inf;
+ var i=occurence(info,"&");
+ info = "&".concat(info);
+ info = info.concat("&");
+ var a= "";
+ var b = "";
+ var j= 0;
+ /*
+ si info = aaaa=3&bbbb=4&cccc=5 alors on le rend comme suit: &aaaa=3&bbbb=4&cccc=5&
+ dans la boucle
+ a = aaaa
+ b= 3
+ */
+ while(j < i){
+ var idxAND=info.indexOf("&");
+ var idxEQUAL=info.indexOf("=");
+ var idxSecondAND = info.indexOf("&",idxAND+1);
+ a = info.substring(idxAND+1,idxEQUAL);
+ b = info.substring(idxEQUAL+ 1,idxSecondAND);
+ hashList.update(a, b);
+ info = info.substring(idxSecondAND);
+ j=j+1;
+ }
+ hashList;
+
+
+ }
+ def occurence(tsr:String,cr:String):int={
+ var n= 1;
+ var str = tsr;
+ var idx = str.indexOf(cr);
+ while (idx != -1){
+ n = n+1;
+ str=str.substring(idx+1);
+ idx = str.indexOf(cr);
+ }
+ n;
+ }
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpConnector.scala b/sources/scala/tools/servletEngine/http/HttpConnector.scala
new file mode 100644
index 0000000000..3e4b093e81
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpConnector.scala
@@ -0,0 +1,12 @@
+package scala.tools.servletEngine.http;
+
+import java.net.{ Socket, ServerSocket };
+
+/** for every port, there is one connector that instantiates a handler
+ * per client connection
+ */
+class HttpConnector(port: Int) extends Connector(port) {
+
+ def makeHandler(s: Socket) = new HttpHandler( s );
+
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpException.scala b/sources/scala/tools/servletEngine/http/HttpException.scala
new file mode 100644
index 0000000000..85f1ca71a3
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpException.scala
@@ -0,0 +1,27 @@
+package scala.tools.servletEngine.http;
+
+import java.io._;
+
+/**
+La classe HttpException est une sous-classe de IOException, elle retourne au client une page HTML qui contient les erreurs dont les types se trouvent dans la classe HTTP.
+
+*/
+class HttpException(code : int, detail: String) extends IOException (detail) {
+
+
+ def toProcessor = new HttpProcessor {
+
+ override def processRequest( out : HttpOutputStream ) : unit ={
+ out.setCode(code);
+ out.setHeader("Content-Type", "text/html");
+ if(out.sendHeaders()){
+ val msg = HTTP.getCodeMessage (code);
+ out.write("<HTML><HEAD><TITLE>"+ code + " " +msg + "</TITLE></HEAD>\n"+"<BODY> <H1>" +
+ msg +"</H1>\n"+ getMessage () + "<P>\n </BODY></HTML>\n");
+ }
+
+ }
+
+ }
+
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpFile.scala b/sources/scala/tools/servletEngine/http/HttpFile.scala
new file mode 100644
index 0000000000..774808b79c
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpFile.scala
@@ -0,0 +1,38 @@
+package scala.tools.servletEngine.http;
+
+import java.io._;
+import java.net._;
+import scala.collection.mutable.HashMap;
+
+/**
+La classe HttpFile implémente le trait HttpProcessor et permit de servir des fichiers statiques depuis le répétoire local des fichiers
+*/
+
+class HttpFile(in: HttpInputStream, info: HashMap[String, String]) with HttpProcessor{
+
+ if (in.getMethod() == HTTP.METHOD_HEAD){
+ throw new HttpException (HTTP.STATUS_NOT_ALLOWED,"<TT>" + in.getMethod ()+ " "+ in.getPath() +"</TT>");
+ }
+
+ var file = new File (HTTP.HTML_ROOT, HTTP.translateFilename(in.getPath()));
+ if(in.getPath().endsWith("/"))
+ file = new File(file, HTTP.DEFAULT_INDEX);
+ if(!file.exists())
+ throw new HttpException (HTTP.STATUS_NOT_FOUND,"le Fichier <TT>" +in.getPath() + "</TT> n'est pas trouvé");
+ if(file.isDirectory())
+ throw new HttpException (HTTP.STATUS_MOVED_PERMANENTLY,in.getPath() + "/");
+ if (!file.isFile() || !file.canRead())
+ throw new HttpException (HTTP.STATUS_FORBIDDEN,
+ in.getPath());
+
+
+ override def processRequest(out: HttpOutputStream): Unit ={
+ out.setHeader("Content-type", HTTP.guessMimeType(file.getName()));
+ out.setHeader("Contents-length", String.valueOf(file.length()));
+ if(out.sendHeaders()) {
+ val in = new FileInputStream(file);
+ out.write(in);
+ in.close();
+ }
+ }
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpHandler.scala b/sources/scala/tools/servletEngine/http/HttpHandler.scala
new file mode 100644
index 0000000000..c595797972
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpHandler.scala
@@ -0,0 +1,83 @@
+package scala.tools.servletEngine.http;
+
+import java.io._;
+import java.net._;
+import scala.collection.mutable.HashMap;
+
+class HttpHandler(client: Socket) extends Thread {
+
+ override def run(): Unit ={
+
+ try {
+ val httpIn = new HttpInputStream (client.getInputStream());
+ var httpOut = new HttpOutputStream(client.getOutputStream(), httpIn);
+ val processor= getProcessor(httpIn);
+ processor.processRequest(httpOut);
+ httpOut.flush();
+ }
+
+ catch {
+ case e:IOException => e.printStackTrace();
+ }
+
+ try {
+ client.close ();
+ }
+
+ catch {
+ case e: IOException => e.printStackTrace();
+ }
+
+ }
+
+
+ /* La methode run: on a construit premierement un HttpInputStream dans le
+ client Input Stream, ceci nous facilte lire et parser les requetes HTTP*/
+
+ def getProcessor(httpIn: HttpInputStream): HttpProcessor={
+ var value = 0;
+ var infoString = " " ;
+ var info:HashMap[String, String] = null;
+ var error: HttpProcessor=null;
+ var srv:HttpServletPro=null;
+ var fil:HttpFile=null;
+
+ try{
+ httpIn.readRequest ();
+ var index = httpIn.getInitialRequest().indexOf("?");
+ if(index != -1){
+ infoString = httpIn.getInitialRequest().substring(index+1);
+ info = HTTP.processing(infoString);
+ }
+
+ if (httpIn.getPath().startsWith(HTTP.SERVLET)){
+ value = 1;
+ srv = new HttpServletPro(httpIn, info);
+ }
+ else{
+ value = 2;
+ fil = new HttpFile(httpIn, info);
+ }
+ }
+
+ catch {
+ case e: HttpException => {
+ error=e.toProcessor;
+ value=3;
+ }
+ case ex: Exception => {
+ val trace = new StringWriter ();
+ ex.printStackTrace(new PrintWriter (trace,true));
+ val exept = new HttpException(HTTP.STATUS_INTERNAL_ERROR,"<PRE>"+ trace +"</PRE>");
+ value=3;
+ error= exept.toProcessor;}
+ }
+
+ if(value == 1)
+ return srv ;
+ else if(value == 2)
+ return fil;
+ else
+ return error;
+}
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpInputStream.scala b/sources/scala/tools/servletEngine/http/HttpInputStream.scala
new file mode 100644
index 0000000000..9b3596f018
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpInputStream.scala
@@ -0,0 +1,145 @@
+package scala.tools.servletEngine.http;
+
+import java.io._;
+import java.net._;
+import java.lang._;
+import scala.collection.mutable.HashMap;
+import java.util.{ NoSuchElementException, StringTokenizer };
+/**
+La classe HttpInputStream fournit un support specialisé pour lire les requêtes HTTP
+*/
+class HttpInputStream(in: InputStream) extends BufferedInputStream(in) {
+ var method = "GET" ;
+ var queryString = "initialisation" ;
+ var path= "index.html";
+ var initialRequest =" ";
+ var version: double = 0;
+ val headers: HashMap[String, String] = new HashMap[String, String]();
+
+ def readRequest(): Unit = {
+ //System.out.println((HTTP.SERVER_LOCATION));
+ val request: String = readLine();
+ if (request == null)
+ throw new HttpException (HTTP.STATUS_BAD_REQUEST,"Null query");
+ val parts = new StringTokenizer(request);
+
+ try{
+ // ici on va parcourir la requete en cherchant les informations requises
+ if (parts.hasMoreTokens ())
+ parseMethod (parts.nextToken());
+ if (parts.hasMoreTokens ()){
+ initialRequest = parts.nextToken();
+ parseRequest (initialRequest);
+ }
+ }
+
+ catch{
+ case ex:NoSuchElementException => throw new HttpException(HTTP.STATUS_BAD_REQUEST, request);
+ }
+
+ if (parts.hasMoreTokens ())
+ parseVersion (parts.nextToken ());
+ else
+ version= 0.9;
+ if((version >= 1.0)&&(method == HTTP.METHOD_HEAD))
+ throw new HttpException (HTTP.STATUS_NOT_ALLOWED, method);
+ if(version >= 1.0)
+ readHeaders();
+
+ }
+
+
+ // on recupere grace à cette methode la methode (get, header ou post)demandé
+ def parseMethod(method: String ): Unit= method.match {
+ case HTTP.METHOD_GET
+ | HTTP.METHOD_HEAD
+ | HTTP.METHOD_POST => this.method = method;
+ case _ =>
+ throw new HttpException (HTTP.STATUS_NOT_IMPLEMENTED, method);
+ }
+
+ /// on recupere grace à cette methode le URI demandé
+ def parseRequest(request: String): Unit ={
+ if(!request.startsWith("/"))
+ throw new HttpException (HTTP.STATUS_BAD_REQUEST,request);
+ val queryIdx = request.indexOf('?');
+ if (queryIdx == -1){
+ path = HTTP.canonicalizePath(request);
+ queryString ="";
+ }
+ else{
+ path = HTTP.canonicalizePath (request.substring(0, queryIdx));
+ queryString = request.substring(queryIdx + 1);
+ }
+ }
+
+ //la methode suivante parse la version
+ def parseVersion(verStr: String) : unit ={
+ if(!verStr.startsWith("HTTP/"))
+ throw new HttpException (HTTP.STATUS_BAD_REQUEST,verStr);
+
+ try{
+ version = Float.valueOf (verStr.substring(5)).floatValue ();}
+
+ catch {
+ case e:NumberFormatException => throw new HttpException(HTTP.STATUS_BAD_REQUEST, verStr);
+ case defaul:Exception => System.out.println("sdfew");}
+ }
+
+ //// la methode suivante lit les headers des requetes,on les lit jusqu a ce qu
+ //// on trouve une ligne vide
+ def readHeaders (): unit ={
+ var header = readLine ();
+ while ((header !=null) && !header.equals("")){
+ val colonIdx:int = header.indexOf(':');
+ if (colonIdx != -1){
+ val name = header.substring(0, colonIdx);
+ val value = header.substring(colonIdx + 1);
+ val _ = headers.update(name.toLowerCase(), value.trim());
+ }
+ header = readLine ();
+ }
+ }
+
+ def readLine (): String = {
+ val line = new StringBuffer();
+ var c = read();
+ if(c == -1)
+ return "error";
+ while ((c != -1)&&(c != '\n')&&(c != '\r')){
+ line.append( c.asInstanceOf[char] );
+ c = read();
+ }
+ if (c == '\r')
+ pos = pos - 1;
+ return line.toString();
+ }
+
+ def getMethod () : String ={
+ return method;
+ }
+
+ def getPath (): String ={
+ return path;
+ }
+
+ def getQueryString (): String ={
+ return queryString;}
+
+ def getVersion(): double ={
+ return version;}
+
+ def getHeader(name:String): String ={
+ return headers(name.toLowerCase());
+ }
+
+ def getHeaderNames(): Iterator[String] ={
+ return headers.keys;
+ }
+
+ def getInitialRequest (): String ={
+ return initialRequest;
+ }
+
+}
+
diff --git a/sources/scala/tools/servletEngine/http/HttpOutputStream.scala b/sources/scala/tools/servletEngine/http/HttpOutputStream.scala
new file mode 100644
index 0000000000..c245d20c89
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpOutputStream.scala
@@ -0,0 +1,102 @@
+
+package scala.tools.servletEngine.http;
+import java.io._;
+import java.lang._;
+import java.util._;
+import scala.Symbol;
+import scala.xml._;
+/**
+La classe HttpOutputStream fournit un support spécialisé pour écrire les reponses aux requêtes HTTP
+*/
+class HttpOutputStream(out:OutputStream , in: HttpInputStream ) extends BufferedOutputStream(out){
+ var code: int = 0;
+ var sendHeaders1 : boolean=true;
+ var sendBody: boolean= true;
+ var headers: Hashtable = new Hashtable ();
+ var cookieEnable:boolean = false;
+ var currentCookie:ScalaCookiee = null ;
+
+ code = HTTP.STATUS_OKAY;
+ setHeader ("server", HTTP.SERVER_INFO);
+ setHeader("Date", new Date ().toString());
+ sendHeaders1 = (in.getVersion() >= 1.0);
+ sendBody = !HTTP.METHOD_HEAD.equals (in.getMethod());
+
+ def setCode ( code:int):unit={
+ this.code=code;
+ }
+
+ def setHeader (attr:String , value:String ) :unit ={
+ /*
+ put(Object key, Object value)
+ fait correspondre la clé specifié à la valeur specifié dans la hashtable
+ */
+ headers.put(attr, value);
+ val i =0;
+ }
+
+
+ def sendHeaders() : boolean={
+ if(sendHeaders1) {
+ write ("HTTP/1.0" +code + " " + HTTP.getCodeMessage(code)+ "\r\n");
+ /* la mehode keys() Retourne une enumeration des clés de cette table de
+ hashage */
+ write("Date: "+headers.get("Date"));
+ headers.remove("Date");
+ if(cookieEnable){
+ write("\nSet-Cookie:"+currentCookie.getName()+"="+currentCookie.getValue()+"\n");
+ }
+ val attrs = headers.keys ();/*return Enumeration type*/
+ while (attrs.hasMoreElements()){
+ val attr = attrs.nextElement().asInstanceOf[String];
+ write (attr + ":" + headers.get(attr) + "\r\n");
+ }
+ write ("\n");
+ }
+ return sendBody;
+ }
+
+
+ def write (msg: String ): unit ={
+ var b:Array[byte] = msg.getBytes("latin1");
+ write (b,0,b.length);
+ }
+
+ override def write(bytes:Array[scala.Byte],offs:int,len:int):unit = {
+ super.write (bytes,offs,len);
+ }
+
+
+ override def write(i:int):unit ={
+ }
+
+
+ def write (in: InputStream ):unit={
+ //buf le buffer interne dans lequel les données sont enregistrées
+ var n = buf.length;
+ var length = buf.length;
+ n = in.read(buf, count, length - count);
+ while (n >= 0){
+ count = count + n;
+ if (count >= length){
+ count =0;
+ out.write(buf,count,length);
+ }
+ n = in.read(buf, count, length - count);
+
+ }
+ }
+
+
+ def setCookie(c : ScalaCookiee):unit={
+ cookieEnable= true;
+ currentCookie = c;
+ }
+
+
+ def disableCookie():unit={
+ cookieEnable= false;
+ currentCookie =null;
+ }
+
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpProcessor.scala b/sources/scala/tools/servletEngine/http/HttpProcessor.scala
new file mode 100644
index 0000000000..563f9181a3
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpProcessor.scala
@@ -0,0 +1,9 @@
+package scala.tools.servletEngine.http ;
+
+import java.io._;
+/**
+le processing actuel de la requête du client est reporté aux classes qui implemetent le trait HttpProcessor, ce trait decrit la façon avec laquelle la classe Httpd peut appeler le processeur pour repondre à la requête du client.
+*/
+ trait HttpProcessor {
+ def processRequest(out: HttpOutputStream): Unit ={};
+}
diff --git a/sources/scala/tools/servletEngine/http/HttpServletPro.scala b/sources/scala/tools/servletEngine/http/HttpServletPro.scala
new file mode 100644
index 0000000000..2998e56f8e
--- /dev/null
+++ b/sources/scala/tools/servletEngine/http/HttpServletPro.scala
@@ -0,0 +1,84 @@
+package scala.tools.servletEngine.http;
+
+import java.io._;
+import java.net._;
+import scala.collection.mutable.HashMap;
+
+
+class HttpServletPro(in: HttpInputStream, info: HashMap[String,String]) with HttpProcessor{
+
+ var servletName="" ;
+ val servletInfo ="";
+ var servlet = new File (HTTP.SERVER_LOCATION,HTTP.translateFilename("src"));
+ val contentLength = 0;
+ //val repertoire = extract();
+
+ var servletClassName:String = extract();
+
+ /*
+ if(!servlet.exists()){
+ throw new HttpException (HTTP.STATUS_NOT_FOUND, "la servlet <TT>"+ servletName + "</TT> n'est pas trouvée ");}
+ if (!servlet.isFile())
+ throw new HttpException (HTTP.STATUS_FORBIDDEN, servletName );
+ */
+
+ // assumption: in.getPath() is a string a/b/c, looks up servlet by c
+ final def extract():String ={
+ val path = in.getPath();// retourne /servlet/repertoire/servletName
+ Console.println("HttpServletPro:path = "+path);
+ var repertoireExtract="";
+ var repertoireIdx = path.indexOf('/', 1);
+ Console.println("HttpServletPro:repIdx = "+repertoireIdx);
+ var servletIdx = path.indexOf('/', repertoireIdx+1 );
+ Console.println("HttpServletPro:servletIdx = "+servletIdx);
+ repertoireExtract = path.substring(repertoireIdx+1,servletIdx );
+ Console.println("HttpServletPro:repExtr = "+repertoireExtract);
+
+ var servletExtract = path.substring(servletIdx +1 );
+ Console.println("HttpServletPro:servletExtract = "+servletExtract);
+ var ma = new Mapping();
+ //var servletRequested = ma.switch(servletExtract);
+ val res = ma.switch(servletExtract) + "$class";
+ Console.println("mapping: servletRequested = "+res);
+ res
+ //servletName = "/".concat(ma.switch(servletRequested));
+ //servlet = new File (HTTP.SERVER_LOCATION,HTTP.translateFilename("src"));
+ //servlet = new File (servlet,HTTP.translateFilename(repertoireExtract));
+ //servlet = new File (servlet,HTTP.translateFilename(servletName.substring(1)));
+
+ //return repertoireExtract ;
+ }
+
+
+
+
+ override def processRequest(out: HttpOutputStream): Unit ={
+ out.setHeader("Content-Type", "text/html");
+ val sc1:ScalaCookiee = new ScalaCookiee("Server", "test");
+ out.setCookie(sc1);
+ val x= out.sendHeaders ();
+
+ try{
+ /*
+ val idx = servletName.indexOf('.');
+ val s1 = servletName.substring(1,idx);
+ val s2 =repertoire.concat(".").concat(s1).concat("$class");
+ var servlet1 = Class.forName(s2);
+ */
+ Console.println("Getting class "+servletClassName);
+ val servlet1 = Class.forName( servletClassName );
+ var servletInstance = servlet1.newInstance().asInstanceOf[ScalaServlet];
+ servletInstance.doGet(out,info);
+ }
+
+ catch{
+ case e :ClassNotFoundException => System.out.println("error:attention le nom de la servlet est incorect");
+ case e :InstantiationException => System.out.println("InstantiationException"); e.printStackTrace();
+ case e : IllegalAccessException => System.out.println("IllegalAccessException");
+ case e:Exception =>
+ System.out.println("une erreur inconue dans al aclasse HttpServletPro");
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/sources/scala/xml/path/Expression.scala b/sources/scala/xml/path/Expression.scala
index bb195354a1..9f7d427b10 100644
--- a/sources/scala/xml/path/Expression.scala
+++ b/sources/scala/xml/path/Expression.scala
@@ -1,33 +1,54 @@
package scala.xml.path;
-// import scala.xml.Node ;
-
object Expression {
- def evaluate(expr:Expression):List[Node] = {
- Nil; // to do
- }
-}
-abstract class Expression ;
+ final def testFromString(x: String): Test = {
+ x.charAt(0) match {
+ case '*' if( x.length == 1 ) => WildcardTest;
+ case _ => NameTest(x);
+ }
+ }
+
+ case class FExp(e:Expr, c:Cond) {
+ def eval(n: Node): NodeSeq = new NodeSeq { val theSeq=Nil}; // @todo
+ }
+
+ abstract class GenExp ;
+ case class Attrib(test: NameTest, e: Expr) extends GenExp;
+
+ abstract class Expr extends GenExp {
+ def \ (x: String) =
+ if( x=="*")
+ Child(WildcardTest, this)
+ else
+ Child(NameTest(x), this);
+
+ def \\ (x: String) =
+ if( x=="*")
+ DescOrSelf(WildcardTest, this)
+ else
+ DescOrSelf(NameTest(x), this);
-/*
-case class Node[T<:Element]( conds:Condition* ) extends Expression {
- type t = T;
+ def apply(c: Cond) = FExp(this, c);
- def test( x:Element ):boolean = {
- x.isInstanceOf[t];
- }
-};
-*/
-case class PathNode( label:String, cond:Option[List[List[Expression]]] ) extends Expression ;
+ def eval(n: Node): NodeSeq = new NodeSeq { val theSeq=Nil}; // @todo
+ }
-case class Attribute( name:String ) extends Expression;
+ case object Root extends Expr;
-case object Wildcard extends Expression;
+ case class Child(test: Test, e: Expr) extends Expr;
+ case class DescOrSelf(test: Test, e: Expr) extends Expr;
-case object Descendant extends Expression;
-/*
-case class Present(attr:Attribute) extends Condition;
-case class Equals(attr:Attribute, str:String) extends Condition;
-*/
+ abstract class Test;
+
+ case object WildcardTest extends Test; // "x \ * "
+ case class NameTest(label: String) extends Test; // "x \ bar"
+
+
+ abstract class Cond;
+
+ case class Exists(p: GenExp) extends Cond ; // "p [ p ]"
+ case class Equals(p: Expr, c:String) extends Cond ; // "p [ @p == bla ]"
+
+}
diff --git a/sources/scala/xml/path/Parser.scala b/sources/scala/xml/path/Parser.scala
index b675e4396f..c36216cbcb 100644
--- a/sources/scala/xml/path/Parser.scala
+++ b/sources/scala/xml/path/Parser.scala
@@ -7,35 +7,37 @@ class Parser( it:Iterator[char] ) with Scanner( it ) {
nextToken
}
+ def getName: String = {
+ if( token != NAME ) error("expected * or a name") else {};
+ val x = value;
+ nextToken;
+ }
+
def parseString( xpath:String ) = {
//initScanner( new IterableString( xpath ));
expr
}
- def expr:List[Expression] = {
- var es : List[Expression] = Nil;
+ def expr:Expr = {
+ var es : Expr = Root;
while( token != ENDTOK ) token.match {
case AT =>
nextToken; es = Attribute( ident ) :: es;
- case DOT =>
- nextToken; acc( SLASH );
-
- case IDENT => {
- val label = value;
- nextToken;
- val cs = conds;
- es = PathNode( label, cs ) :: es
- }
case SLASH =>
- nextToken;
+ val x = getName;
+ if( x == "*" )
+ es = Child(Wildcard, es)
+ else
+ es = Child(NameTest( x ), es)
case SLASHSLASH =>
- nextToken; es = Descendant :: es ;
-
- case STAR =>
- nextToken; es = Wildcard :: es;
+ val x = getName;
+ if( x == "*" )
+ es = DescOrSelf(Wildcard, es)
+ else
+ es = DescOrSelf(NameTest( x ), es)
}
es.reverse;
diff --git a/sources/scala/xml/path/Scanner.scala b/sources/scala/xml/path/Scanner.scala
index b067efe97d..ff0631294c 100644
--- a/sources/scala/xml/path/Scanner.scala
+++ b/sources/scala/xml/path/Scanner.scala
@@ -24,7 +24,6 @@ class Scanner( it:Iterator[char] ) with Tokens {
next;
if ( '/' == c ) { next; token = SLASHSLASH } else { token = SLASH }
}
- case '*' =>next; token = STAR
case _ =>getIdentOrKeyword;
}
diff --git a/sources/scala/xml/path/Tokens.scala b/sources/scala/xml/path/Tokens.scala
index d88b372335..86ec396624 100644
--- a/sources/scala/xml/path/Tokens.scala
+++ b/sources/scala/xml/path/Tokens.scala
@@ -10,8 +10,8 @@ class Tokens {
final val DOT = COMMA + 1;
final val DOTDOT = DOT + 1;
final val EQUALS = DOTDOT + 1;
- final val IDENT = EQUALS + 1;
- final val LBRACKET = IDENT + 1;
+ final val NAME = EQUALS + 1;
+ final val LBRACKET = NAME + 1;
final val RBRACKET = LBRACKET + 1;
final val SLASH = RBRACKET + 1;
final val SLASHSLASH = SLASH + 1;