Changeset 97

Show
Ignore:
Timestamp:
05/24/05 22:38:36 (4 years ago)
Author:
pragma
Message:

- Updated to support Mango 1.3 and Build 2.07

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/doc/community.html

    r89 r97  
    5252                    </ul> 
    5353                </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. 
    5555                    <ul> 
    5656                        <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  
    6060        <p> 
    6161            <ul> 
     62                <li>Version 1.2 for DSP 0.2B - Eric Anderton - H3r3tic</li> 
    6263                <li>Version 1.0 for DSP 0.2B - Eric Anderton</li> 
    6364            </ul> 
  • trunk/doc/dsp-reference/tags.html

    r96 r97  
    2222            <ul> 
    2323                <li><a href='#page'>dsp:page</a></li> 
     24                <li><a href='#servlet'>dsp:servlet</a></li> 
    2425            </ul> 
    2526        </p> 
     
    2728        <p> 
    2829            <ul> 
    29                 <li><a href='#servlet'>dsp:servlet</a></li> 
    3030                <li><a href='#import'>dsp:import</a></li> 
    3131                <li><a href='#include'>dsp:include</a></li> 
     32                <li><a href='#capture'>dsp:capture</a></li> 
    3233                <li><a href='#attribute'>dsp:attribute</a></li> 
    3334            </ul> 
     
    6768 
    6869        <h3>Syntax:</h3> 
    69         <pre class='syntax'>&lt;dsp:page&gt; <i>[basic tags]</i> &lt;/dsp:page&gt;</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'>&lt;dsp:page&gt; <i>[dsp:servlet and basic tags]</i> &lt;/dsp:page&gt;</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. 
    7475        </p> 
    7576 
     
    166167 
    167168                <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> 
    169170 
    170171                <li><u>dependency</u> - specifies if this generates an 
     
    184185            file's content to the servlet output without any additional processing.  The 'code' mode, adds the 
    185186            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. 
    186190        </p> 
    187191        <p> 
     
    196200                <li><a href='concepts.html#app-filespace'>Application File Space</a></li> 
    197201                <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'>&lt;dsp:capture <i>[attributes]</i> &gt; <i>[content]</i> &lt;/dsp:capture&gt;</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> 
    198238            </ul> 
    199239        </p> 
     
    397437 
    398438        <h3>Syntax:</h3> 
    399         <pre class='syntax'>&lt;dsp:tag <i>[attributes]</i> &gt; <i>[dsp:attribute]</i> &lt;/dsp:out&gt;</pre> 
     439        <pre class='syntax'>&lt;dsp:tag <i>[attributes]</i> &gt; <i>[dsp:attribute]</i> &lt;/dsp:tag&gt;</pre> 
    400440        <pre class='syntax'>&lt;dsp:tag <i>[attributes]</i> /&gt;</pre> 
    401441 
  • trunk/dsp/ConfigParser.d

    r75 r97  
    118118             
    119119        case Data: 
    120             if("name" in attribs){ 
     120            if(attribs.contains("name")){ 
    121121                this.name = attribs["name"];     
    122122            } 
     
    125125            }        
    126126             
    127             if("value" in attribs){ 
     127            if(attribs.contains("value")){ 
    128128                dictionary.put(name,attribs["value"]);   
    129129                debug printf("config: %.*s = %.*s\n",name,attribs["value"]);                 
  • trunk/dsp/DSPProcessor.d

    r71 r97  
    3131private import dsp.ServletGenerator; 
    3232private import dsp.TagLibrary; 
    33  
     33private import dsp.ServletCompilationContext; 
    3434 
    3535private import xml.utf8all; 
     
    3939 
    4040class DSPProcessor : SimpleConsumer{ 
    41     ServletGenerator generator; 
    42     TagLibrary tags; 
     41    ServletCompilationContext context; 
    4342 
    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; 
    5445    } 
    5546     
     
    6556        if(name.startsWith(DSPGrammar.preamble)){ 
    6657            char[] instruction = name[DSPGrammar.preamble.length..$]; 
    67             switch(instruction){ 
     58            switch(instruction){        
    6859            case "in": 
    69                 generator.appendCPIn(data); 
     60                context.generator.appendCPIn(data); 
    7061                break; 
    7162                 
    7263            case "out": 
    73                 generator.appendCPOut(data); 
     64                context.generator.appendCPOut(data); 
    7465                break; 
    7566             
    76             case "body": 
    77                 generator.appendBody(data); 
    78                 break;           
    79              
    8067            case "output": 
    81                 generator.appendOutput(data); 
     68                context.generator.appendOutput(data); 
    8269                break; 
    8370                 
    8471            case "xml": 
    8572                // allow for xml-specific PI's to not be consumed 
    86                 generator.appendOutput("<?xml " ~ data ~ "?>"); 
     73                context.generator.appendOutput("<?xml " ~ data ~ "?>"); 
    8774                break;           
    8875                 
     
    9279        } 
    9380        else if(name == DSPGrammar.rawPreamble){ 
    94             generator.appendBody(data); 
     81            context.generator.appendBody(data); 
    9582        } 
    9683        else{ 
    9784            // output the non-dsp PI: 
    98             generator.appendOutput("<?" ~ name ~ " " ~ data ~ "?>"); 
     85            context.generator.appendOutput("<?" ~ name ~ " " ~ data ~ "?>"); 
    9986        } 
    10087    } 
     
    10491            if(text[0] == DSPGrammar.escapeChar && text.length > 1){ 
    10592                // 'escaped' comments are sent to the client 
    106                 generator.appendOutput("<!--" ~ text[1..$] ~ "-->"); 
     93                context.generator.appendOutput("<!--" ~ text[1..$] ~ "-->"); 
    10794            } 
    10895        } 
     
    11097             
    11198    void xmlStartElement(char[] name,XMLAttributes attribs,bit isEmpty){ 
    112         switch(generator.getContentMode()){ 
     99        switch(context.generator.getContentMode()){ 
    113100        case ServletGenerator.LiteralContentMode: 
    114101            // real DSP tag - attempt to deduce its type and handle it 
    115102            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); 
    117104            } 
    118105 
     
    124111            // a plain XML/HTML tag - interpret the attributes and output it 
    125112            else{ 
    126                 generator.appendOutput("<" ~ name); 
     113                context.generator.appendOutput("<" ~ name); 
    127114 
    128115                foreach(char[] attribName,char[] attribValue; attribs){ 
    129                     generator.appendExpression(attribValue); 
     116                    context.generator.appendExpression(attribValue); 
    130117 
    131                     generator.appendOutput(" " ~ attribName ~ "=\'"); 
    132                     generator.appendOutputExpression("\'","&apos;"); 
    133                     generator.appendOutput("\'");      
     118                    context.generator.appendOutput(" " ~ attribName ~ "=\'"); 
     119                    context.generator.appendOutputExpression("\'","&apos;"); 
     120                    context.generator.appendOutput("\'");      
    134121                } 
    135122 
    136123                if(isEmpty){ 
    137                     generator.appendOutput(" />"); 
     124                    context.generator.appendOutput(" />"); 
    138125                } 
    139126                else{ 
    140                     generator.appendOutput(">"); 
     127                    context.generator.appendOutput(">"); 
    141128                } 
    142129            } 
     
    155142        // real DSP tag - attempt to deduce its type and handle it 
    156143        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); 
    158145        } 
    159146         
    160147        // a plain XML/HTML tag - close it up 
    161148        else if(!isEmpty){ 
    162             generator.appendOutput("</" ~ name ~ ">"); 
     149            context.generator.appendOutput("</" ~ name ~ ">"); 
    163150        } 
    164151    } 
    165152     
    166153    void xmlText(char[] text){ 
    167         switch(generator.getContentMode()){ 
     154        switch(context.generator.getContentMode()){ 
    168155        case ServletGenerator.LiteralContentMode:    
    169156            //TODO: handle escaping of entities like '&' '<' '>' 
    170             generator.appendExpression(text); 
    171             generator.appendOutputExpression(); 
     157            context.generator.appendExpression(text); 
     158            context.generator.appendOutputExpression(); 
    172159            break; 
    173160             
    174161        case ServletGenerator.InCodeContentMode: 
    175             generator.appendCPIn(text); 
     162            context.generator.appendCPIn(text); 
    176163            break; 
    177164             
    178165        case ServletGenerator.OutCodeContentMode: 
    179             generator.appendCPOut(text); 
     166            context.generator.appendCPOut(text); 
    180167            break;   
    181168         
    182169        case ServletGenerator.CodeContentMode:  
    183             generator.appendBody(text); 
     170            context.generator.appendBody(text); 
    184171            break; 
    185172        } 
  • trunk/dsp/DSPTag.d

    r71 r97  
    3131private import dsp.DSPGrammar; 
    3232private import dsp.TagLibrary; 
     33private import dsp.ServletCompilationContext; 
    3334 
    3435interface 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); 
    3738} 
  • trunk/dsp/ServletCompiler.d

    r71 r97  
    2929private import dsp.StandardTagLibrary; 
    3030private import dsp.RequestConfig; 
     31private import dsp.ServletGenerator; 
     32private import dsp.ServletCompilationContext; 
    3133 
    3234private import xml.utf8all; 
     
    4042 
    4143class ServletCompiler{ 
    42     DSPProcessor processor; 
    4344    XMLParser parser; 
    4445    OfflineProvider provider; 
     
    4647    public this(){ 
    4748        parser = new XMLParser(); 
    48         processor = new DSPProcessor(new StandardTagLibrary());  
    4949        provider = new OfflineProvider(); 
    5050    } 
    5151     
    52     public void CompileServlet(RequestConfig cfg){ 
    53         ProcessDSPFile(cfg); 
    54         RunCompiler(cfg); 
     52    public void CompileServlet(ServletCompilationContext context){ 
     53        ProcessDSPFile(context); 
     54        RunCompiler(context); 
    5555    } 
    5656     
    57     private void ProcessDSPFile(RequestConfig cfg){ 
    58         CharT[] source = charTConvert(cast(char[])std.file.read(cfg.dspSourceFilename)); 
     57    private void ProcessDSPFile(ServletCompilationContext context){ 
     58        CharT[] source = charTConvert(cast(char[])std.file.read(context.requestConfig.dspSourceFilename)); 
    5959         
    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        ); 
    6271    } 
    6372     
    64     private void RunCompiler(RequestConfig cfg){ 
     73    private void RunCompiler(ServletCompilationContext context){ 
    6574        char[] commandline = 
    66             "dmd " ~ cfg.dSourceFilename ~  
    67             " " ~ cfg.options ~ 
     75            "dmd " ~ context.requestConfig.dSourceFilename ~  
     76            " " ~ context.requestConfig.options ~ 
    6877            " -op" ~ 
    69             " -od" ~ cfg.tempDirectory ~  
    70             " -of" ~ cfg.destServletFilename ~ 
     78            " -od" ~ context.requestConfig.tempDirectory ~  
     79            " -of" ~ context.requestConfig.destServletFilename ~ 
    7180            " mango.lib" ~ 
    72             " " ~ cfg.runtimeDirectory ~ "DllStub.obj" ~ 
    73             " " ~ cfg.runtimeDirectory ~ "IDSPRequest.obj" ~ 
    74             " " ~ cfg.runtimeDirectory ~ "IDSPResponse.obj" ~          
    75             " " ~ cfg.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" ~ 
    7685            " -version=dsp" ~ 
    77             " > " ~ cfg.tempDirectory ~ cfg.name ~ "_output.txt" 
     86            " > " ~ context.requestConfig.tempDirectory ~ context.requestConfig.name ~ "_output.txt" 
    7887            ; 
    7988             
    80     /* //TODO: report a bug regarding issues with build. 
     89    /* //TODO: fix this so 'build' works correctly 
    8190        char[] commandline = 
    82             "build " ~ cfg.dSourceFilename ~  
     91            "build " ~ context.requestConfig.dSourceFilename ~  
    8392            " -op" ~ 
    84             " -od" ~ cfg.tempDirectory ~  
    85             " -of" ~ cfg.destServletFilename ~ 
     93            " -od" ~ context.requestConfig.tempDirectory ~  
     94            " -of" ~ context.requestConfig.destServletFilename ~ 
    8695            " mango.lib" ~ 
    8796            " servlet.def" ~ 
    8897            " -version=dsp" ~ 
    89             " > " ~ cfg.tempDirectory ~ cfg.name ~ "_output.txt" 
     98            " > " ~ context.tempDirectory ~ context.requestConfig.name ~ "_output.txt" 
    9099            ;    
    91100    */ 
     
    93102         
    94103        if(std.process.system(commandline) != 0){ 
    95             throw new Exception(cast(char[])std.file.read(cfg.tempDirectory ~ cfg.name ~ "_output.txt")); 
     104            throw new Exception(cast(char[])std.file.read(context.requestConfig.tempDirectory ~ context.requestConfig.name ~ "_output.txt")); 
    96105        } 
    97106    } 
  • trunk/dsp/StandardTagLibrary.d

    r48 r97  
    3838        tags["out"] = new OutCode(); 
    3939        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(); 
    4244    } 
    4345} 
  • trunk/dsp/TagLibrary.d

    r71 r97  
    3232private import dsp.DSPGrammar; 
    3333private import dsp.DSPTag; 
     34private import dsp.ServletCompilationContext; 
    3435 
    3536class TagLibrary{ 
     
    4849    } 
    4950 
    50     public void startTag(ServletGenerator 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); 
    5253    } 
    5354     
    54     public void endTag(ServletGenerator 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); 
    5657    } 
    5758} 
  • trunk/dsp/Util.d

    r71 r97  
    2525 
    2626module dsp.Util; 
     27 
     28private import mango.io.model.IConduit; 
     29private import mango.io.model.IBuffer; 
     30private import mango.io.Buffer; 
     31private import mango.io.Tokenizer; 
    2732 
    2833import std.string; 
     
    5863    return result; 
    5964} 
     65 
     66class 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 
     87static const uint DEFAULT_CAPACITY = 1024; 
     88 
     89char[] 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  
    2727 
    2828private import dsp.servlet.IDSPRequest; 
     29private import dsp.servlet.DSPAttributes; 
    2930 
    3031private import mango.servlet.model.IServletRequest; 
     
    3334private import mango.http.server.model.IProviderBridge; 
    3435 
     36private import std.boxer; 
     37 
    3538class DSPRequest : ServletRequest, IDSPRequest{ 
     39    DSPAttributes attribs; 
     40    char[] contentData; 
     41     
    3642    public this(IProviderBridge bridge){ 
    3743        super(bridge); 
    3844    } 
     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    } 
    3963} 
  • trunk/dsp/servlet/DSPResponse.d

    r57 r97  
    2626module dsp.servlet.DSPResponse; 
    2727 
     28private import dsp.servlet.IDSPRequest; 
    2829private import dsp.servlet.IDSPResponse; 
     30private import dsp.servlet.DSPAttributes; 
     31private import dsp.servlet.RuntimeTag; 
    2932 
    3033private import mango.servlet.ServletResponse; 
     
    3235private import mango.http.HttpWriter; 
    3336private import mango.http.server.model.IProviderBridge; 
     37private import mango.io.Buffer; 
     38 
     39private import std.boxer; 
    3440 
    3541class DSPResponse : ServletResponse, IDSPResponse{ 
    3642    char[] exception; 
    37      
     43    HttpWriter[] writerStack;    
     44    HttpWriter writer; 
     45    RuntimeTag[char[]][] customTagScopeStack; 
     46    RuntimeTag[] tagStack; 
     47         
    3848    public this(IProviderBridge bridge){ 
    3949        super(bridge); 
    40     }    
     50        customTagScopeStack.length = 1; 
     51    } 
    4152     
    4253    HttpWriter getWriter(){ 
    43         //TODO: implement writer stack 
    44         return super.getWriter(); 
     54        //return writer; 
     55        if(!writer) writer = super.getWriter(); 
     56        return writer; 
    4557    } 
    4658     
     
    5668        return exception; 
    5769    } 
     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 
    58177} 
  • trunk/dsp/servlet/DSPServlet.d

    r75 r97  
    3333private import dsp.servlet.IDSPResponse; 
    3434private import dsp.servlet.DSPServletContext; 
     35private import dsp.servlet.DSPLibrary; 
     36private import dsp.servlet.DSPLibraryCache; 
    3537 
    3638private import dsp.DSPException; 
    3739private import dsp.ServletCompiler; 
    3840private import dsp.RequestConfig; 
    39  
    40 private import mango.cache.HashMap; 
     41private import dsp.ServletCompilationContext; 
    4142 
    4243private import mango.servlet.Servlet; 
     
    5354 
    5455private 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 shutdown 
    60  
    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 dependencies 
    119         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