Changeset 109

Show
Ignore:
Timestamp:
07/17/05 14:51:53 (3 years ago)
Author:
pragma
Message:

7/11/05
- changed default web.xml for dspconf to /dspconf from /foo/bar

7/16/05
- added line number support for code generator
+ (bugfix) Issues with paths on custom tags.. requires "./" to get local directory
- eliminated dependency attribute from <dsp:tag>
- added expression support for filename attribute on <dsp:tag>

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/app.xml

    r75 r109  
    55<applications> 
    66    <!-- note: the 'path' must be an absolute path in this version (sorry) --> 
    7     <application name="/foo/bar" path="c:/dev/dsp/trunk/dspconf" /> 
     7    <application name="/dspconf" path="c:/dev/dsp/trunk/dspconf" /> 
    88</applications> 
  • trunk/dsp/DSPGrammar.d

    r108 r109  
    3737    public static char[] rawPreamble = "dsp"; 
    3838    public static char[] preamble = "dsp:"; 
    39     public static char[] newline = "\n"; 
     39    public static char[] newline = "";//"\n"; 
    4040 
    4141    public static char[] servletPrefix = "__servlet_"; 
     
    5858    public static char[] pathToNamespace(char[] path){ 
    5959        //TODO: improve this to be more intellegent in handling non-namespace chars 
    60         return path.replace(".","_").replace("\\",".").replace("/","."); 
     60        return path.replace(".\\","").replace(".","_").replace("\\",".").replace("/","."); 
    6161    } 
    6262     
  • trunk/dsp/DSPProcessor.d

    r108 r109  
    5555     
    5656    void xmlProcessingInstruction(char[] name,char[] data){ 
    57         with(context){ 
     57        with(context){      
    5858            if(name.startsWith(DSPGrammar.preamble)){ 
     59                // provide #line token 
     60                generator.appendLineNumber("xmlProcessingInstruction.test",parser.getPosition.line);                 
     61             
    5962                char[] instruction = name[DSPGrammar.preamble.length..$]; 
    6063                switch(instruction){         
     
    108111            switch(generator.getContentMode()){ 
    109112            case ServletGenerator.LiteralContentMode:    
     113                // provide #line token 
     114                generator.appendLineNumber("xmlStartElement.test",parser.getPosition.line); 
     115                 
    110116                // real DSP tag - attempt to deduce its type and handle it 
    111117                if(name.startsWith(DSPGrammar.preamble)){ 
     
    145151            case ServletGenerator.OutCodeContentMode: 
    146152            case ServletGenerator.CodeContentMode: 
    147                 // get tag stack from the tag library 
    148153                throw new DSPException("cannot nest tags inside of a code-only tag."); 
    149154                break; 
     
    153158     
    154159    void xmlEndElement(char[] name,XMLAttributes attribs,bit isEmpty){ 
    155         with(context){ 
     160        with(context){          
    156161            // real DSP tag - attempt to deduce its type and handle it 
    157162            if(name.startsWith(DSPGrammar.preamble)){ 
     
    174179    void xmlText(char[] text){ 
    175180        with(context){ 
     181            // provide #line token 
     182            generator.appendLineNumber("xmlText.test",parser.getPosition.line);      
     183         
    176184            switch(context.generator.getContentMode()){ 
    177185            case ServletGenerator.LiteralContentMode:    
  • trunk/dsp/ServletGenerator.d

    r108 r109  
    9595    } 
    9696     
     97    public void appendLineNumber(char[] file,uint line){ 
     98        servletBody ~= "\n#line " ~ std.string.toString(line) ~ " \"" ~ file ~ "\"" ~ "\n";//DSPGrammar.newline; 
     99    } 
     100     
    97101    public void appendBody(char[] text){ 
    98102        if(outputSegment){ 
  • trunk/dsp/Util.d

    r102 r109  
    3030private import mango.io.Buffer; 
    3131private import mango.io.Tokenizer; 
     32private import mango.io.FileConst; 
    3233 
    3334import std.string; 
     
    6869    conduit.close(); 
    6970} 
     71 
     72/** 
     73    Cleans an entire path by resolving "//", "./" and "../" sequences 
     74     
     75    Throws an exception if the path resolves to below the root of the given path 
     76*/ 
     77char[] cleanPath(char[] path){ 
     78printf("cleanPath: %.*s\n",path); 
     79    char[][] segments; 
     80    int lastSep = 0; 
     81    for(int i=0; i<path.length; i++){ 
     82        if(path[i] == '\\' || path[i] == '/'){ // catch both kinds 
     83            char[] segment = path[lastSep..i]; 
     84            if(segment == "."){ 
     85                // do nothing 
     86            } 
     87            else if(segment == ".."){ 
     88                if(segments.length == 0){ 
     89                    throw new Exception("cannot resolve path"); 
     90                } 
     91                segments.length = segments.length - 1; // go up one level 
     92            } 
     93            else if(segment.length > 0){ 
     94            printf("segment: '%.*s'\n",segment); 
     95                segments ~= segment; 
     96            } 
     97            lastSep = i+1; 
     98        } 
     99    } 
     100    if(lastSep == 0){ 
     101        printf("no sub-segments\n"); 
     102        return path; 
     103    } 
     104    else{ 
     105        printf("segments: %d lastSep == %d \n",segments.length,lastSep); 
     106    } 
     107     
     108    segments ~= path[lastSep..$]; 
     109     
     110    char[] output = ""; 
     111    foreach(int i,char[] segment; segments){ 
     112        if(i > 0) output ~= FileConst.PathSeparatorString; 
     113        output ~= segment; 
     114    } 
     115     
     116    printf("output: %.*s\n",output); 
     117 
     118    return output; 
     119} 
  • trunk/dsp/servlet/DSPAttributes.d

    r102 r109  
    4646    return defaultValue; 
    4747} 
     48 
     49void empty(inout DSPAttributes attribs){ 
     50    attribs = DSPAttributes.init; 
     51     
     52    //HACK: make the attribute collection non-null, but empty, by adding and then removing one element 
     53    attribs["foo"] = box(null); 
     54    attribs.remove("foo"); 
     55     
     56    return attribs; 
     57} 
  • trunk/dsp/servlet/DSPLibraryCache.d

    r108 r109  
    2727 
    2828private import dsp.servlet.DSPLibrary; 
    29  
    30 /* 
    31 /+ 
    32     Behavior: 
    33      
    34     As each library is used, it is promoted up one position in the cache.  
    35     The overall action is not unlike a bubble-sort, where multiple sorting 
    36     actions eventually sort the cache out. 
    37 +/ 
    38 class DSPLibraryCache{ 
    39     struct CacheEntry{ 
    40         DSPLibrary lib; 
    41         char[] key; 
    42     } 
    43  
    44     CacheEntry[] positions; 
    45     DSPLibrary[char[]] cache; 
    46     uint freeCount; 
    47  
    48     this(uint capacity){ 
    49         freeCount = capacity; 
    50         positions.length = capacity; 
    51     } 
    52      
    53     protected void addLibrary(DSPLibrary lib,char[] key){ 
    54         debug printf("addLibrary\n"); 
    55          
    56         if(freeCount==0){ 
    57             // search for the lowest ranking library that is not in use 
    58             for(uint i=positions.length-1; i>=0; i--){ 
    59                 if(!positions[i].lib.inUse){ 
    60                  
    61                     // close out the library 
    62                     positions[i].lib.unload(); 
    63                  
    64                     // remove the entry from the cache 
    65                     cache.remove(positions[i].key); 
    66                                          
    67                     // replace the idle library with this one instead 
    68                     positions[i].lib = lib; 
    69                     positions[i].key = key; 
    70                     cache[key] = lib; 
    71                      
    72                     return; 
    73                 } 
    74             } 
    75              
    76             // balloon the cache since all libs are being used           
    77             freeCount++; 
    78              
    79             //(fallthrough) 
    80         } 
    81          
    82         positions[$-freeCount] = lib; 
    83         cache[key] = lib; 
    84         freeCount--; 
    85     } 
    86      
    87     protected void removeLibrary(DSPLibrary lib){ 
    88         debug printf("removeLibrary\n"); 
    89         assert(!lib.inUse); 
    90          
    91         for(uint i=0; i<positions.length; i++){ 
    92             if(positions[i].lib == lib){ 
    93                 char[] key = positions[i].key; 
    94                 if(i < positions.length-1){ 
    95                     positions[i..$-1] = [i+1..$]; // move entire array up to fill the gap 
    96                 } 
    97                 positions[$-1] = null; 
    98                 freeCount++; 
    99                 cache.remove(key); 
    100                 return; 
    101             } 
    102         } 
    103         assert(false); 
    104     } 
    105  
    106     protected void getLibrary(char[] key){ 
    107         debug printf("getLibrary\n"); 
    108         if(key in cache){ 
    109             for(uint i=0; i<positions.length; i++){ 
    110                  
    111             } 
    112             return cache[key]; 
    113         } 
    114         return null; 
    115     } 
    116      
    117      
    118     void put(char[] path,DSPLibrary lib){ 
    119         // place entry in the queue 
    120         if(lib){ 
    121             synchronized(this){ 
    122                 assert(!(path in cache)); 
    123                 addLibrary(lib,path.dup); 
    124             } 
    125         } 
    126          
    127         // remove the entry from the queue 
    128         else{ 
    129             //remove this entry from the list 
    130             synchronized(this){ 
    131                 removeLibrary(lib); 
    132             } 
    133         } 
    134     } 
    135      
    136     DSPLibrary get(char[] path){ 
    137         DSPLibrary result; 
    138         synchronized(this) result = getLibrary(lib); 
    139         return result; 
    140     } 
    141      
    142     char[] toString(){ 
    143         char[] output = ""; 
    144         return output; 
    145     } 
    146 }*/ 
    147  
    148  
    149  
    15029private import mango.cache.HashMap; 
    15130 
  • trunk/dsp/servlet/DSPRequest.d

    r104 r109  
    4343    public this(IProviderBridge bridge){ 
    4444        super(bridge); 
     45        reset(); 
    4546    } 
    4647     
    4748    public void reset(){ 
    48         attribs = null
     49        attribs.empty()
    4950        contentData = null; 
    5051        servletName = "default"; 
  • trunk/dsp/servlet/DSPServlet.d

    r104 r109  
    4141private import dsp.RequestConfig; 
    4242private import dsp.ServletCompilationContext; 
     43private import dsp.Util; 
    4344 
    4445private import mango.servlet.Servlet; 
     
    5657private import std.string; 
    5758 
    58 /*  
    59     <desc> 
    60         DSPServlet: dll-per-file implementation  
    61     </desc><desc> 
    62         The size of the dlls is directly related to the size of the libraries contributed to its  
    63         compilation.  Presently, the libs are floating arount 100kb in size each, due to the inclusion 
    64         of phobos and mango.  Possibly loading those libs as dlls could reduce the size, as would recompiling 
    65         them for a release or reduced-capability set. 
    66     </desc><desc> 
    67         dll-per-file is not just for a development time practice, as it is very tunable. The QueuedCache 
    68         can be used to good effect to expire infrequently used libs that needn't be loaded all the time. 
    69     </desc> 
    70 */ 
    71  
    7259class DSPServlet : Servlet{ 
    7360    private static Logger logger; 
    7461    protected DSPLibraryCache cache; 
    7562    DSPServletContext context; 
     63    char[][] AppRoots; 
     64     
    7665 
    7766    static this (){ 
     
    9079    DSPLibrary recoverLibrary(FilePath path){ 
    9180        char[] libraryPath = context.getBasePath ~ "/" ~ context.getConfiguration.get("cache-directory"); 
    92         libraryPath ~= path.getName[1..$] ~ ".dll"; 
     81        libraryPath ~= path.getName ~ ".dll"; 
    9382         
    9483        debug printf("attempting to recover: %.*s\n",libraryPath); 
     
    160149        DSPLibrary lib = cast(DSPLibrary)cache.get(pathInfo); 
    161150 
    162       debug{ 
     151    //    debug{ 
    163152            if(lib){ 
    164153                printf("cache lib: %.*s = %.*s\n",pathInfo,lib.toString()); 
    165154            } 
    166155            else{ 
    167                 printf("cache lib: %.*s = [not present]\n",request.getPathInfo); 
    168             } 
    169       } 
     156                printf("cache lib: %.*s = [not present]\n",pathInfo); 
     157            } 
     158    //    } 
    170159 
    171160        // attempt to recover the lib from the file cache 
     
    194183    void service (IServletRequest request, IServletResponse response){ 
    195184        FilePath path = new FilePath(request.getPathInfo); 
     185         
     186        //TODO: provide configurable filtering support here 
    196187                 
    197188        if(path.getExtension == "dsp"){ 
     
    212203            // run the servlet 
    213204            if(lib){ 
     205                debug printf("servicing servlet\n"); 
     206                lib.inUse = true; 
    214207                lib.service(dspRequest,dspResponse); 
     208                lib.inUse = false; 
     209                debug printf("done servicing servlet\n"); 
    215210                 
    216211                if(dspResponse.isExceptionSet){ 
     
    273268    public ServiceHandleDelegate getServletHandleForFile(IDSPRequest request,char[] filename){ 
    274269        FilePath requestPath = new FilePath(request.getPathInfo); 
    275         FilePath path = new FilePath(requestPath.getPath() ~ filename); 
     270        FilePath path = new FilePath(cleanPath(requestPath.getPath() ~ "/" ~ filename)); 
    276271         
    277272        //TODO: include support for http://, https:// and file:// protocols. 
     
    307302        if(size == 0) size = 20; 
    308303         
    309         debug printf("(cache config) size: %d threads: %d\n",size,threads); 
     304        debug printf("(cache config) size: %d threads: %d\n",size,threads);         
    310305         
    311306        cache = new DSPLibraryCache(size,threads);       
     307         
     308        // get the redirect          
    312309    }    
    313310} 
  • trunk/dsp/tags/Include.d

    r102 r109  
    3434private import dsp.DSPTag; 
    3535private import dsp.DSPException; 
     36private import dsp.Register; 
    3637private import dsp.ServletCompilationContext; 
    3738 
     
    5556            switch(attribs.get("as","output")){ 
    5657            case "output": 
    57                 //TODO: add a runtime way of evaluating the filename dynamically, and outputting the file's contents 
     58                // dependency mapping makes sure this doesn't need to be done at runtime 
    5859                generator.appendOutput(filedata); 
     60 
     61                // output the contents at runtime instead, evaluating the filename 
     62                //Register reg = generator.evaluateExpression(filename); 
     63                //generator.appendBody("response.copyFile (request.getContext,"  ~ reg.box() ~ ");" ~ DSPGrammar.newline); 
    5964                break; 
    6065 
  • trunk/dsp/tags/Servlet.d

    r104 r109  
    5858            char[] servletName = generator.popString(); 
    5959            ServletGenerator oldGenerator = generator.popGenerator(); 
     60             
     61            generator.end(); 
     62            oldGenerator.appendStatic(generator.getServletFunction(servletName)); 
     63             
    6064            context.generator = oldGenerator; 
    61              
    62             oldGenerator.end(); 
    63             generator.appendStatic(oldGenerator.getServletFunction(servletName)); 
    6465        } 
    6566    } 
  • trunk/dspconf/config.xml

    r102 r109  
    66    <runtime-directory value=""/> 
    77    <build-options value="-inline -release"/> 
     8<!-- 
     9    <error code="404" file="404.html" /> 
     10    <error code="500" file="500.html" /> 
     11 
     12    <approot file="application.dsp" />   
     13 
     14    <default file="index.dsp" /> 
     15    <default file="index.html" /> 
     16 
     17    <redirect file="config.xml" code="404" /> 
     18    <redirect file="404.html" code="404" /> 
     19    <redirect file="500.html" code="404" /> 
     20    <redirect pattern=".*\.inc" code="404" /> 
     21     
     22    <block aspect="HTTP-REFERER" pattern="badsite\.com" /> 
     23    <block aspect="IP-ADDRESS" pattern="10\.0\.0\.1" />  
     24--> 
    825</config> 
  • trunk/dspconf/custom_tag.dsp

    r105 r109  
    1313    <x:custom:foo/> 
    1414    <x:customfoobar/> 
     15     
     16    <dsp:tag name="x:custom2" file="dsp_servlet.dsp" /> 
     17     
     18    <x:custom2/> 
     19    <x:custom2:test/> 
    1520</body> 
    1621</html> 
  • trunk/dspconf/dsp_capture.dsp

    r102 r109  
    66 
    77    <dsp:capture var="content"> 
    8         hello world 
     8        This is was generated inside a dsp:capture tag. 
    99    </dsp:capture> 
    1010 
  • trunk/xml/XMLParser.d

    r100 r109  
    9696            exception("unexpected token (expected '" ~ charTConvert(match) ~ "' not '" ~ charTConvert(next) ~ "')"); 
    9797        } 
    98         cursor++; 
    99         if(cursor == '\n'){ 
     98        if(source[cursor] == '\n'){ 
     99           //writefln("newline: (%d,%d)",pos.line,pos.column); 
    100100            pos.line++; 
    101101            pos.column = 1; 
     
    104104            pos.column++; 
    105105        } 
     106        cursor++; 
    106107        pos.offset=cursor; 
    107         //writefln("getNext: '%c'",next); 
     108        //writefln("getNext: '%d' (%d,%d)",next,pos.line,pos.column); 
    108109        return next; 
    109110    }