Changeset 97
- Timestamp:
- 05/24/05 22:38:36 (4 years ago)
- Files:
-
- trunk/doc/community.html (modified) (1 diff)
- trunk/doc/dsp-reference/index.html (modified) (1 diff)
- trunk/doc/dsp-reference/tags.html (modified) (7 diffs)
- trunk/dsp/ConfigParser.d (modified) (2 diffs)
- trunk/dsp/DSPProcessor.d (modified) (8 diffs)
- trunk/dsp/DSPTag.d (modified) (1 diff)
- trunk/dsp/ServletCompiler.d (modified) (4 diffs)
- trunk/dsp/StandardTagLibrary.d (modified) (1 diff)
- trunk/dsp/TagLibrary.d (modified) (2 diffs)
- trunk/dsp/Util.d (modified) (2 diffs)
- trunk/dsp/servlet/DSPRequest.d (modified) (2 diffs)
- trunk/dsp/servlet/DSPResponse.d (modified) (3 diffs)
- trunk/dsp/servlet/DSPServlet.d (modified) (9 diffs)
- trunk/dsp/servlet/DSPServletContext.d (modified) (1 diff)
- trunk/dsp/servlet/IDSPRequest.d (modified) (1 diff)
- trunk/dsp/servlet/IDSPResponse.d (modified) (1 diff)
- trunk/dsp/tags/Code.d (modified) (1 diff)
- trunk/dsp/tags/InCode.d (modified) (1 diff)
- trunk/dsp/tags/OutCode.d (modified) (1 diff)
- trunk/dsp/tags/all.d (modified) (1 diff)
- trunk/dspconf/dsp01.dsp (modified) (3 diffs)
- trunk/dspconf/dsp04.dsp (added)
- trunk/dsptest.d (modified) (1 diff)
- trunk/server.d (modified) (2 diffs)
- trunk/server.xml (modified) (1 diff)
- trunk/xml/IXMLConsumer.d (modified) (3 diffs)
- trunk/xml/IXMLConsumerAdapter.d (modified) (2 diffs)
- trunk/xml/SimpleConsumer.d (modified) (2 diffs)
- trunk/xml/Unicode.d (modified) (4 diffs)
- trunk/xml/XMLAttributes.d (modified) (2 diffs)
- trunk/xml/XMLParser.d (modified) (10 diffs)
- trunk/xml/utf16all.d (modified) (1 diff)
- trunk/xml/utf32all.d (modified) (1 diff)
- trunk/xml/utf32all.obj (modified) (previous)
- trunk/xml/utf8all.d (modified) (1 diff)
- trunk/xml/xmlns/IXMLNamespaceConsumer.d (modified) (1 diff)
- trunk/xml/xmlns/IXMLNamespaceConsumerAdapter.d (modified) (1 diff)
- trunk/xml/xmlns/QName.d (modified) (1 diff)
- trunk/xml/xmlns/XMLNSAttributes.d (modified) (2 diffs)
- trunk/xml/xmlns/XMLNamespaceParser.d (modified) (1 diff)
- trunk/xml/xmlns/utf16all.d (modified) (1 diff)
- trunk/xmltest.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/doc/community.html
r89 r97 52 52 </ul> 53 53 </li> 54 <li><b> h3r3tic</b> - End-user, tester and all-round good guy.54 <li><b>Tomasz Stachowiak (aka h3r3tic)</b> - End-user, tester and all-round good guy. 55 55 <ul> 56 56 <li><a href='http://www.dsource.org/forums/profile.php?mode=viewprofile&u=25'>DSource User Profile</a></li> trunk/doc/dsp-reference/index.html
r95 r97 60 60 <p> 61 61 <ul> 62 <li>Version 1.2 for DSP 0.2B - Eric Anderton - H3r3tic</li> 62 63 <li>Version 1.0 for DSP 0.2B - Eric Anderton</li> 63 64 </ul> trunk/doc/dsp-reference/tags.html
r96 r97 22 22 <ul> 23 23 <li><a href='#page'>dsp:page</a></li> 24 <li><a href='#servlet'>dsp:servlet</a></li> 24 25 </ul> 25 26 </p> … … 27 28 <p> 28 29 <ul> 29 <li><a href='#servlet'>dsp:servlet</a></li>30 30 <li><a href='#import'>dsp:import</a></li> 31 31 <li><a href='#include'>dsp:include</a></li> 32 <li><a href='#capture'>dsp:capture</a></li> 32 33 <li><a href='#attribute'>dsp:attribute</a></li> 33 34 </ul> … … 67 68 68 69 <h3>Syntax:</h3> 69 <pre class='syntax'><dsp:page> <i>[ basic tags]</i> </dsp:page></pre>70 71 <h3>Valid Content:</h3> 72 <p> 73 The tag may contain any basic tags, custom tags and text content.70 <pre class='syntax'><dsp:page> <i>[dsp:servlet and basic tags]</i> </dsp:page></pre> 71 72 <h3>Valid Content:</h3> 73 <p> 74 The tag may contain any <a href='tags.html#servlet'>dsp:servlet</a>, basic tags, custom tags and text content. 74 75 </p> 75 76 … … 166 167 167 168 <li><u>as</u> - specifies how to treat the file. 168 Valid values are "code" and "output", which is the default if this attribute is not specified.</li>169 Valid values are "code", "in", "out", "dsp" and "output", which is the default if this attribute is not specified.</li> 169 170 170 171 <li><u>dependency</u> - specifies if this generates an … … 184 185 file's content to the servlet output without any additional processing. The 'code' mode, adds the 185 186 file's content to the servlet as though it were contained in a <a href='#code'>dsp:code tag</a>. 187 Likewise, the 'in' and 'out' modes correspond to the <a href='#in'>dsp:in</a> and 188 <a href='#out'>dsp:out</a> tags. Lastly, the 'dsp' mode treats the contents as DSP code, and will 189 treat these as though the file's contents were placed at the include tag's location in the file. 186 190 </p> 187 191 <p> … … 196 200 <li><a href='concepts.html#app-filespace'>Application File Space</a></li> 197 201 <li><a href='concepts.html#dependencies'>File Dependencies</a></li> 202 </ul> 203 </p> 204 205 <!-- ******************************************************************* --> 206 207 <a name='capture'></a> 208 <h1>The Capture Tag.</h1> 209 210 <h3>Syntax:</h3> 211 <pre class='syntax'><dsp:capture <i>[attributes]</i> > <i>[content]</i> </dsp:capture></pre> 212 213 <h3>Valid Content:</h3> 214 <p> 215 The tag may contain any basic tags, custom tags and text content. 216 </p> 217 218 <h3>Attributes:</h3> 219 <p> 220 <ul> 221 <li><u>var</u> - <b>(required)</b> the D variable to assign the captured output to. Any scalar 222 type will do, as the runtime will convert the content to the variable's type. 223 Class and struct types are not allowed, and will generate an error if used.</li> 224 </ul> 225 </p> 226 227 <h3>Description:</h3> 228 <p> 229 The dsp:capture tag takes advantage of DSP's <a href='concepts.html#output-stack'>output stack</a> behavior, 230 and saves the content inside the tag to a specified variable, instead of passing it on to the output. 231 All basic tags and custom tags behave as normal inside the dsp:capture tag. 232 </p> 233 234 <h3>See Also:</h3> 235 <p> 236 <ul> 237 <li><a href='concepts.html#output-stack'>Output Stack</a></li> 198 238 </ul> 199 239 </p> … … 397 437 398 438 <h3>Syntax:</h3> 399 <pre class='syntax'><dsp:tag <i>[attributes]</i> > <i>[dsp:attribute]</i> </dsp: out></pre>439 <pre class='syntax'><dsp:tag <i>[attributes]</i> > <i>[dsp:attribute]</i> </dsp:tag></pre> 400 440 <pre class='syntax'><dsp:tag <i>[attributes]</i> /></pre> 401 441 trunk/dsp/ConfigParser.d
r75 r97 118 118 119 119 case Data: 120 if( "name" in attribs){120 if(attribs.contains("name")){ 121 121 this.name = attribs["name"]; 122 122 } … … 125 125 } 126 126 127 if( "value" in attribs){127 if(attribs.contains("value")){ 128 128 dictionary.put(name,attribs["value"]); 129 129 debug printf("config: %.*s = %.*s\n",name,attribs["value"]); trunk/dsp/DSPProcessor.d
r71 r97 31 31 private import dsp.ServletGenerator; 32 32 private import dsp.TagLibrary; 33 33 private import dsp.ServletCompilationContext; 34 34 35 35 private import xml.utf8all; … … 39 39 40 40 class DSPProcessor : SimpleConsumer{ 41 ServletGenerator generator; 42 TagLibrary tags; 41 ServletCompilationContext context; 43 42 44 public this(TagLibrary tags){ 45 generator = new ServletGenerator(); 46 this.tags = tags; 47 } 48 49 public char[] getServletSource(char[] modulePath,char[] fileExtension){ 50 return generator.getServletSource(modulePath,fileExtension); 51 } 52 53 void xmlProlog(XMLAttributes attribs){ 43 public this(ServletCompilationContext context){ 44 this.context = context; 54 45 } 55 46 … … 65 56 if(name.startsWith(DSPGrammar.preamble)){ 66 57 char[] instruction = name[DSPGrammar.preamble.length..$]; 67 switch(instruction){ 58 switch(instruction){ 68 59 case "in": 69 generator.appendCPIn(data);60 context.generator.appendCPIn(data); 70 61 break; 71 62 72 63 case "out": 73 generator.appendCPOut(data);64 context.generator.appendCPOut(data); 74 65 break; 75 66 76 case "body":77 generator.appendBody(data);78 break;79 80 67 case "output": 81 generator.appendOutput(data);68 context.generator.appendOutput(data); 82 69 break; 83 70 84 71 case "xml": 85 72 // allow for xml-specific PI's to not be consumed 86 generator.appendOutput("<?xml " ~ data ~ "?>");73 context.generator.appendOutput("<?xml " ~ data ~ "?>"); 87 74 break; 88 75 … … 92 79 } 93 80 else if(name == DSPGrammar.rawPreamble){ 94 generator.appendBody(data);81 context.generator.appendBody(data); 95 82 } 96 83 else{ 97 84 // output the non-dsp PI: 98 generator.appendOutput("<?" ~ name ~ " " ~ data ~ "?>");85 context.generator.appendOutput("<?" ~ name ~ " " ~ data ~ "?>"); 99 86 } 100 87 } … … 104 91 if(text[0] == DSPGrammar.escapeChar && text.length > 1){ 105 92 // 'escaped' comments are sent to the client 106 generator.appendOutput("<!--" ~ text[1..$] ~ "-->");93 context.generator.appendOutput("<!--" ~ text[1..$] ~ "-->"); 107 94 } 108 95 } … … 110 97 111 98 void xmlStartElement(char[] name,XMLAttributes attribs,bit isEmpty){ 112 switch( generator.getContentMode()){99 switch(context.generator.getContentMode()){ 113 100 case ServletGenerator.LiteralContentMode: 114 101 // real DSP tag - attempt to deduce its type and handle it 115 102 if(name.startsWith(DSPGrammar.preamble)){ 116 tags.startTag(generator,name[DSPGrammar.preamble.length .. $],attribs,isEmpty);103 context.tags.startTag(context,name[DSPGrammar.preamble.length .. $],attribs,isEmpty); 117 104 } 118 105 … … 124 111 // a plain XML/HTML tag - interpret the attributes and output it 125 112 else{ 126 generator.appendOutput("<" ~ name);113 context.generator.appendOutput("<" ~ name); 127 114 128 115 foreach(char[] attribName,char[] attribValue; attribs){ 129 generator.appendExpression(attribValue);116 context.generator.appendExpression(attribValue); 130 117 131 generator.appendOutput(" " ~ attribName ~ "=\'");132 generator.appendOutputExpression("\'","'");133 generator.appendOutput("\'");118 context.generator.appendOutput(" " ~ attribName ~ "=\'"); 119 context.generator.appendOutputExpression("\'","'"); 120 context.generator.appendOutput("\'"); 134 121 } 135 122 136 123 if(isEmpty){ 137 generator.appendOutput(" />");124 context.generator.appendOutput(" />"); 138 125 } 139 126 else{ 140 generator.appendOutput(">");127 context.generator.appendOutput(">"); 141 128 } 142 129 } … … 155 142 // real DSP tag - attempt to deduce its type and handle it 156 143 if(name.startsWith(DSPGrammar.preamble)){ 157 tags.endTag(generator,name[DSPGrammar.preamble.length .. $],attribs,isEmpty);144 context.tags.endTag(context,name[DSPGrammar.preamble.length .. $],attribs,isEmpty); 158 145 } 159 146 160 147 // a plain XML/HTML tag - close it up 161 148 else if(!isEmpty){ 162 generator.appendOutput("</" ~ name ~ ">");149 context.generator.appendOutput("</" ~ name ~ ">"); 163 150 } 164 151 } 165 152 166 153 void xmlText(char[] text){ 167 switch( generator.getContentMode()){154 switch(context.generator.getContentMode()){ 168 155 case ServletGenerator.LiteralContentMode: 169 156 //TODO: handle escaping of entities like '&' '<' '>' 170 generator.appendExpression(text);171 generator.appendOutputExpression();157 context.generator.appendExpression(text); 158 context.generator.appendOutputExpression(); 172 159 break; 173 160 174 161 case ServletGenerator.InCodeContentMode: 175 generator.appendCPIn(text);162 context.generator.appendCPIn(text); 176 163 break; 177 164 178 165 case ServletGenerator.OutCodeContentMode: 179 generator.appendCPOut(text);166 context.generator.appendCPOut(text); 180 167 break; 181 168 182 169 case ServletGenerator.CodeContentMode: 183 generator.appendBody(text);170 context.generator.appendBody(text); 184 171 break; 185 172 } trunk/dsp/DSPTag.d
r71 r97 31 31 private import dsp.DSPGrammar; 32 32 private import dsp.TagLibrary; 33 private import dsp.ServletCompilationContext; 33 34 34 35 interface DSPTag{ 35 public void startTag( TagLibrary library,ServletGenerator generator,char[] name,XMLAttributes attribs,bit isEmpty);36 public void endTag( TagLibrary library,ServletGenerator generator,char[] name,XMLAttributes attribs,bit isEmpty);36 public void startTag(ServletCompilationContext context,char[] name,XMLAttributes attribs,bit isEmpty); 37 public void endTag(ServletCompilationContext context,char[] name,XMLAttributes attribs,bit isEmpty); 37 38 } trunk/dsp/ServletCompiler.d
r71 r97 29 29 private import dsp.StandardTagLibrary; 30 30 private import dsp.RequestConfig; 31 private import dsp.ServletGenerator; 32 private import dsp.ServletCompilationContext; 31 33 32 34 private import xml.utf8all; … … 40 42 41 43 class ServletCompiler{ 42 DSPProcessor processor;43 44 XMLParser parser; 44 45 OfflineProvider provider; … … 46 47 public this(){ 47 48 parser = new XMLParser(); 48 processor = new DSPProcessor(new StandardTagLibrary());49 49 provider = new OfflineProvider(); 50 50 } 51 51 52 public void CompileServlet( RequestConfig cfg){53 ProcessDSPFile(c fg);54 RunCompiler(c fg);52 public void CompileServlet(ServletCompilationContext context){ 53 ProcessDSPFile(context); 54 RunCompiler(context); 55 55 } 56 56 57 private void ProcessDSPFile( RequestConfig cfg){58 CharT[] source = charTConvert(cast(char[])std.file.read(c fg.dspSourceFilename));57 private void ProcessDSPFile(ServletCompilationContext context){ 58 CharT[] source = charTConvert(cast(char[])std.file.read(context.requestConfig.dspSourceFilename)); 59 59 60 parser.parse(processor, provider, source); 61 std.file.write(cfg.dSourceFilename,cast(char[])processor.getServletSource(cfg.requestModule,cfg.ext)); 60 context.generator = new ServletGenerator(); 61 context.tags = new StandardTagLibrary(); 62 63 parser.parse(new DSPProcessor(context), provider, source); 64 std.file.write( 65 context.requestConfig.dSourceFilename, 66 context.generator.getServletSource( 67 context.requestConfig.requestModule, 68 context.requestConfig.ext 69 ) 70 ); 62 71 } 63 72 64 private void RunCompiler( RequestConfig cfg){73 private void RunCompiler(ServletCompilationContext context){ 65 74 char[] commandline = 66 "dmd " ~ c fg.dSourceFilename ~67 " " ~ c fg.options ~75 "dmd " ~ context.requestConfig.dSourceFilename ~ 76 " " ~ context.requestConfig.options ~ 68 77 " -op" ~ 69 " -od" ~ c fg.tempDirectory ~70 " -of" ~ c fg.destServletFilename ~78 " -od" ~ context.requestConfig.tempDirectory ~ 79 " -of" ~ context.requestConfig.destServletFilename ~ 71 80 " mango.lib" ~ 72 " " ~ c fg.runtimeDirectory ~ "DllStub.obj" ~73 " " ~ c fg.runtimeDirectory ~ "IDSPRequest.obj" ~74 " " ~ c fg.runtimeDirectory ~ "IDSPResponse.obj" ~75 " " ~ c fg.runtimeDirectory ~ "servlet.def" ~81 " " ~ context.requestConfig.runtimeDirectory ~ "DllStub.obj" ~ 82 " " ~ context.requestConfig.runtimeDirectory ~ "IDSPRequest.obj" ~ 83 " " ~ context.requestConfig.runtimeDirectory ~ "IDSPResponse.obj" ~ 84 " " ~ context.requestConfig.runtimeDirectory ~ "servlet.def" ~ 76 85 " -version=dsp" ~ 77 " > " ~ c fg.tempDirectory ~ cfg.name ~ "_output.txt"86 " > " ~ context.requestConfig.tempDirectory ~ context.requestConfig.name ~ "_output.txt" 78 87 ; 79 88 80 /* //TODO: report a bug regarding issues with build.89 /* //TODO: fix this so 'build' works correctly 81 90 char[] commandline = 82 "build " ~ c fg.dSourceFilename ~91 "build " ~ context.requestConfig.dSourceFilename ~ 83 92 " -op" ~ 84 " -od" ~ c fg.tempDirectory ~85 " -of" ~ c fg.destServletFilename ~93 " -od" ~ context.requestConfig.tempDirectory ~ 94 " -of" ~ context.requestConfig.destServletFilename ~ 86 95 " mango.lib" ~ 87 96 " servlet.def" ~ 88 97 " -version=dsp" ~ 89 " > " ~ c fg.tempDirectory ~ cfg.name ~ "_output.txt"98 " > " ~ context.tempDirectory ~ context.requestConfig.name ~ "_output.txt" 90 99 ; 91 100 */ … … 93 102 94 103 if(std.process.system(commandline) != 0){ 95 throw new Exception(cast(char[])std.file.read(c fg.tempDirectory ~ cfg.name ~ "_output.txt"));104 throw new Exception(cast(char[])std.file.read(context.requestConfig.tempDirectory ~ context.requestConfig.name ~ "_output.txt")); 96 105 } 97 106 } trunk/dsp/StandardTagLibrary.d
r48 r97 38 38 tags["out"] = new OutCode(); 39 39 tags["in"] = new InCode(); 40 tags["code"] = new Code(); 41 tags["body"] = new Code(); 40 tags["code"] = new Code(); 41 tags["page"] = new Page(); 42 tags["servlet"] = new Servlet(); 43 tags["include"] = new Include(); 42 44 } 43 45 } trunk/dsp/TagLibrary.d
r71 r97 32 32 private import dsp.DSPGrammar; 33 33 private import dsp.DSPTag; 34 private import dsp.ServletCompilationContext; 34 35 35 36 class TagLibrary{ … … 48 49 } 49 50 50 public void startTag(Servlet Generator generator,char[] name,XMLAttributes attribs,bit isEmpty){51 getTag(name).startTag( this,generator,name,attribs,isEmpty);51 public void startTag(ServletCompilationContext context,char[] name,XMLAttributes attribs,bit isEmpty){ 52 getTag(name).startTag(context,name,attribs,isEmpty); 52 53 } 53 54 54 public void endTag(Servlet Generator generator,char[] name,XMLAttributes attribs,bit isEmpty){55 getTag(name).endTag( this,generator,name,attribs,isEmpty);55 public void endTag(ServletCompilationContext context,char[] name,XMLAttributes attribs,bit isEmpty){ 56 getTag(name).endTag(context,name,attribs,isEmpty); 56 57 } 57 58 } trunk/dsp/Util.d
r71 r97 25 25 26 26 module dsp.Util; 27 28 private import mango.io.model.IConduit; 29 private import mango.io.model.IBuffer; 30 private import mango.io.Buffer; 31 private import mango.io.Tokenizer; 27 32 28 33 import std.string; … … 58 63 return result; 59 64 } 65 66 class CompleteBufferReader: Scanner{ 67 IBuffer buffer; 68 69 this(IBuffer buffer){ 70 this.buffer = buffer; 71 } 72 73 char[] read(){ 74 char[] data; 75 76 // delegate to read in everything that is passed in 77 int scan (char[] content) 78 { 79 data ~= content; 80 return IConduit.Eof; 81 } 82 super.next (buffer, &scan); 83 return(data); 84 } 85 } 86 87 static const uint DEFAULT_CAPACITY = 1024; 88 89 char[] getEntireConduit(IConduit conduit,uint capacity = DEFAULT_CAPACITY){ 90 IBuffer buf = new Buffer(capacity); 91 buf.setConduit(conduit); 92 CompleteBufferReader reader = new CompleteBufferReader(buf); 93 return reader.read(); 94 } trunk/dsp/servlet/DSPRequest.d
r57 r97 27 27 28 28 private import dsp.servlet.IDSPRequest; 29 private import dsp.servlet.DSPAttributes; 29 30 30 31 private import mango.servlet.model.IServletRequest; … … 33 34 private import mango.http.server.model.IProviderBridge; 34 35 36 private import std.boxer; 37 35 38 class DSPRequest : ServletRequest, IDSPRequest{ 39 DSPAttributes attribs; 40 char[] contentData; 41 36 42 public this(IProviderBridge bridge){ 37 43 super(bridge); 38 44 } 45 46 DSPAttributes attributes(){ 47 return attribs; 48 } 49 50 DSPAttributes attributes(DSPAttributes attributes){ 51 this.attribs = attributes; 52 return attribs; 53 } 54 55 char[] content(){ 56 return contentData; 57 } 58 59 char[] content(char[] content){ 60 this.contentData = content; 61 return contentData; 62 } 39 63 } trunk/dsp/servlet/DSPResponse.d
r57 r97 26 26 module dsp.servlet.DSPResponse; 27 27 28 private import dsp.servlet.IDSPRequest; 28 29 private import dsp.servlet.IDSPResponse; 30 private import dsp.servlet.DSPAttributes; 31 private import dsp.servlet.RuntimeTag; 29 32 30 33 private import mango.servlet.ServletResponse; … … 32 35 private import mango.http.HttpWriter; 33 36 private import mango.http.server.model.IProviderBridge; 37 private import mango.io.Buffer; 38 39 private import std.boxer; 34 40 35 41 class DSPResponse : ServletResponse, IDSPResponse{ 36 42 char[] exception; 37 43 HttpWriter[] writerStack; 44 HttpWriter writer; 45 RuntimeTag[char[]][] customTagScopeStack; 46 RuntimeTag[] tagStack; 47 38 48 public this(IProviderBridge bridge){ 39 49 super(bridge); 40 } 50 customTagScopeStack.length = 1; 51 } 41 52 42 53 HttpWriter getWriter(){ 43 //TODO: implement writer stack 44 return super.getWriter(); 54 //return writer; 55 if(!writer) writer = super.getWriter(); 56 return writer; 45 57 } 46 58 … … 56 68 return exception; 57 69 } 70 71 //* save the current writer and use a new one in its place 72 void pushWriter(){ 73 HttpWriter newWriter = new HttpWriter(new Buffer()); 74 writerStack ~= newWriter; 75 writer = newWriter; 76 } 77 78 //* pull the old content out of the current writer and commit it to the previous one 79 char[] popWriter(){ 80 uint len = writerStack.length; 81 assert(len > 0); 82 83 HttpWriter oldWriter = writerStack[len-1]; 84 writerStack.length = len-1; 85 86 char[] data = cast(char[])writer.getBuffer().getContent(); 87 writer = oldWriter; 88 89 return data; 90 } 91 92 private RuntimeTag findTag(char[] name){ 93 return customTagScopeStack[$-1][name]; 94 } 95 96 private RuntimeTag getCurrentTag(){ 97 return tagStack[$-1]; 98 } 99 100 private void pushCurrentTag(RuntimeTag tag){ 101 tagStack ~= tag; 102 } 103 104 private RuntimeTag popCurrentTag(){ 105 tagStack.length = tagStack.length-1; 106 } 107 108 void startTagScope(){ 109 RuntimeTag[char[]] newScope; 110 111 foreach(char[] name,RuntimeTag tag; customTagScopeStack[$-1]){ 112 newScope[name] = tag; 113 } 114 115 customTagScopeStack ~= newScope; 116 } 117 118 void endTagScope(){ 119 customTagScopeStack.length = customTagScopeStack.length-1; 120 } 121 122 RuntimeTag addTag(char[] tagname,char[] filename){ 123 RuntimeTag tag; 124 //TODO: get the tag handle from the context somehow 125 //tag.handle = context.getServletHandle(filename); 126 127 customTagScopeStack[$-1][tagname] = tag; 128 } 129 130 void startTag(char[] name){ 131 RuntimeTag tag = findTag(name); 132 pushCurrentTag(tag.clone()); 133 134 if(!tag.isNull){ 135 pushWriter(); 136 } 137 else{ 138 writer.put("<" ~ name); 139 } 140 } 141 142 void setTagAttribute(char[] name,Box value){ 143 RuntimeTag tag = getCurrentTag(); 144 if(!tag.isNull){ 145 tag.attributes[name] = value; 146 } 147 else{ 148 writer.put(" " ~ name ~ "= '" ~ value.toString() ~ "'"); 149 } 150 } 151 152 void endTagAttributes(){ 153 if(!getCurrentTag().isNull){ 154 writer.put(">"); 155 } 156 } 157 158 void endTag(IDSPRequest request,char[] name){ 159 RuntimeTag tag = getCurrentTag(); 160 if(!tag.isNull){ 161 DSPAttributes attributes = request.attributes; 162 char[] content = request.content; 163 164 request.content = popWriter(); 165 request.attributes = tag.attributes; 166 tag.handle(request,this); 167 168 request.attributes = attributes; 169 request.content = content; 170 } 171 else{ 172 writer.put("</" ~ name ~ ">"); 173 } 174 popCurrentTag(); 175 } 176 58 177 } trunk/dsp/servlet/DSPServlet.d
r75 r97 33 33 private import dsp.servlet.IDSPResponse; 34 34 private import dsp.servlet.DSPServletContext; 35 private import dsp.servlet.DSPLibrary; 36 private import dsp.servlet.DSPLibraryCache; 35 37 36 38 private import dsp.DSPException; 37 39 private import dsp.ServletCompiler; 38 40 private import dsp.RequestConfig; 39 40 private import mango.cache.HashMap; 41 private import dsp.ServletCompilationContext; 41 42 42 43 private import mango.servlet.Servlet; … … 53 54 54 55 private import std.string; 55 56 extern(C) alias void function(IDSPRequest request,IDSPResponse response) ServiceHandle;57 extern(C) alias char[][] function() DependencyHandle;58 59 //TODO: use SystemFinalizer to catch libraries that are still loaded at shutdown60 61 class DSPLibrary{62 protected long timeModified;63 protected Library lib;64 public ServiceHandle service;65 protected DependencyHandle dependencies;66 67 public DSPLibrary next,last;68 public char[] key;69 70 protected void unload(){71 if(lib){72 debug printf("unloading library %.*s\n",lib.getPath());73 if(lib.isLoaded) lib.unload();74 lib = null;75 service = null;76 dependencies = null;77 timeModified = 0;78 }79 }80 81 public char[] getPath(){82 if(lib && lib.isLoaded) return lib.getPath();83 return "[not loaded]";84 }85 86 public this(char[] path){87 lib = new Library(path);88 if(lib && lib.isLoaded){89 service = cast(ServiceHandle)lib.getSymbol("service");90 91 if(!service){92 unload();93 throw new DSPException("servlet library does not have a valid service handle");94 }95 96 dependencies = cast(DependencyHandle)lib.getSymbol("dependencies");97 98 if(!dependencies){99 unload();100 throw new DSPException("servlet library does not have a valid dependencies handle");101 }102 103 debug printf("library loaded: %.*s\n",path);104 }105 else{106 if(lib){107 unload();108 }109 throw new DSPException("could not load library");110 }111 112 timeModified = (new FileProxy(path)).getModifiedTime();113 }114 115 bit isOutOfDate(char[] basePath,FilePath path){116 if(!lib || !lib.isLoaded) return true;117 118 // verify the date/time of the dependencies119 foreach(char[] dep; dependencies()){120 debug debug printf("[%.*s%.*s]\n",basePath,dep);121 if((new FileProxy(basePath ~ dep)).getModifiedTime() > timeModified){122 debug printf("%.*s%.*s : servlet is out of date.\n",basePath,dep);123 return true;124 }125 }126 127 debug printf("%.*s%.*s : servlet is up to date.\n",basePath,path.toString());128 129 return false;130 }131 132 public char[] toString(){133 if(lib){134 if(lib.isLoaded){135 return "loaded: " ~ lib.getPath;136 }137 else{138 return "unloaded: " ~ lib.getPath;139 }140 }141 return "[empty library]";142 }143 }144 145 146 class DSPLibraryCache{147 HashMap map;148 DSPLibrary mostPopular,leastPopular; // mp through last pointers to lp. lp through next opinters to mp.149 uint freeCount;150 151 this (uint capacity = 101, uint concurrency = 16){152 map = new HashMap (capacity, 0.75, concurrency);153 mostPopular = null;154 leastPopular = null;155 freeCount = capacity;156 }157 158 protected void dropEntry(DSPLibrary lib){159 debug printf("dropEntry\n");160 if(lib.next) lib.next.last = lib.last;161 if(lib.last) lib.last.next = lib.next;162 if(lib is mostPopular){163 mostPopular = mostPopular.last;164 if(mostPopular){165 mostPopular.last = null;166 }167 }168 if(lib is leastPopular){169 leastPopular = leastPopular.next;170 if(leastPopular){171 leastPopular.last = null;172 }173 }174 }175 176 protected void makePopular(DSPLibrary lib){177 debug printf("makePopular\n");178 dropEntry(lib);179 if(mostPopular is null){180 mostPopular = lib;181 leastPopular = lib;182 }183 else if(!(lib is mostPopular)){184 mostPopular.next = lib;185
