Software Reality
Programming with
a dose of satire.

Site Map Search


Agile Development
 
Extreme Programming
 
Code Generation


Articles
Lifecycle
Design
Programming
Soapbox
Reviews
Cthulhu

Check out our ageing Reviews Section


Use Case Driven
Use Case Driven Object Modeling with UML: Theory and Practice
Get from use cases to working, maintainable source code. Examples use Spring Framework, JUnit and Enterprise Architect

Agile UML
Agile Development with ICONIX Process
A practical subset of agile development techniques, illustrated by example

Get Controversial!
Extreme Programming Refactored
Extreme Programming with a dose of satire
Available now:



ICONIX/Sparx Public Classes to Come to London

ICONIX is planning a series of open- enrollment public classes entitled Hands-On Enterprise Architect for Power Users in collaboration with Sparx Systems.




Slots Web Framework

Slots Source Code

<< Slots Central

 

SlotServlet.java

package com.felstar.slots;

import java.io.*;
import java.net.*;

import javax.servlet.*;
import javax.servlet.http.*;

import java.util.*;

/**
 *
 * @author Dino Fancellu, felstar.com
 * @version
 */
public class SlotServlet extends HttpServlet {
    
    /** Initializes the servlet.
     */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        ServletContext context=config.getServletContext();
        String realpath=context.getRealPath(slot_config);
        slotsConfig=new File(realpath);        
        if (!slotsConfig.exists())
        {
         System.out.println("** Config file does not exist at "+realpath);
        }
    }
    
    /** Destroys the servlet.
     */
    public void destroy() {
        
    }
    
    final String slot_config= "/WEB-INF/slots-config.properties";
    File slotsConfig=null;
    
    long lastModified=0;
    Properties properties=new Properties();
    String defaultbase=null;
    
    Hashtable cache=new Hashtable(16);
    
    protected void loadProperties() throws IOException {       
        if (lastModified>=slotsConfig.lastModified()) return;
        synchronized (this)
        {
         if (lastModified>=slotsConfig.lastModified()) return;   
        
         InputStream is=new FileInputStream(slotsConfig);
        
         properties.clear();
         properties.load(is);
         is.close();
         
         defaultbase=properties.getProperty("default");
         cache.clear();
         lastModified=slotsConfig.lastModified();                  
        }
    }
       
    
    /*
     * Given an entry, base or url, resolves a map of slot entries,
     * using base and url inhertance
     *
     **/
    
    protected LinkedHashMap resolveEntry(String entryname) {                                
        String entry=properties.getProperty(entryname);
        
        //System.out.print(entryname+"=");
        //System.out.println(entry);
        
        // if its am invalid base, i.e. no definition
        if (entry==null&&!entryname.startsWith("/")) {
            throw new IllegalArgumentException("Invalid base, not defined: "+entryname);
        }                
        
        String originalEntryname=entryname;
        
        // if we haven"t found an entry for complete path, we check parents, up to root
        // this lets us define slots for entire directories, recursively.
        while (entry==null) {
            int lastslash=entryname.lastIndexOf("/");
            if (lastslash==-1) {
                break;
            }
            entryname=entryname.substring(0,lastslash);
            if (entryname==null||entryname.length()==0) {
                break;
            }
            entry=properties.getProperty(entryname);
        }
        
        
        LinkedHashMap map=parseLine(entry);
        if (entry!=null)
        {
         map.put("entry", "\""+entry+"\"");
        }        
                
        String base=(String)map.get("base");
        
        //cache.put(base,map);
        //System.out.println(" Putting "+base+" "+map);
        
        if (base!=null&&base.startsWith("/")&&!entryname.startsWith("/")) {
         
         return map;
        }
                
        LinkedHashMap map2=resolveEntry(base);
        
        map.remove("base");
        map2.putAll(map);
        
        return map2;
    }
    
    /**
     * Takes a line of CSV slot entries and returns a map
     * If no base defined, we use the default base
     *
     * @param line
     * @return
     */
    protected LinkedHashMap parseLine(String line) {
        LinkedHashMap map=new LinkedHashMap();
        if (line!=null) {
            String vals[]=line.split(",");
            for (int x=0;x<vals.length;x++) {
                String slot=vals[x];
                String[] bits=slot.split("=");
                String attr=bits[0];
                String attrfile=bits[1];
                map.put(attr,attrfile);
            }
        }
        String base=(String)map.get("base");
        
        if (base==null) {
            map.put("base",defaultbase);
        }
        return map;
    }
    
    
    
    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        
        String pathinfo=null;
        
         // this request may be for an included resource, don"t want to use parent pathinfo,
         // else we"d end up in an infinite loop!
        pathinfo = (String)request.getAttribute("javax.servlet.include.path_info");
        
  
        
        if (pathinfo==null)
        {         
         pathinfo=request.getPathInfo();
        } 
        
                
        //System.out.println("pathinfo="+pathinfo);
        
        String servletPath=request.getServletPath();
        //System.out.println("servletPath="+servletPath);
        
        if (pathinfo==null) {
            pathinfo=servletPath;
            // being served by the *.slot mapping, turn it into a jsp
            // remember, this "jsp" can in fact point to a servlet
            if (pathinfo.endsWith(".slot")) {
                pathinfo=pathinfo.replaceAll("\\.slot", "\\.jsp");
            }
        }
        
        
        if (pathinfo!=null&&pathinfo.indexOf(".")==-1) {
            out.println("Broken, directory browsing not allowed");
            return;
        }
        
        loadProperties();
        
        if (properties.size()<1)
        {
         System.out.println("** Config file empty");
         return;
        }
        
        LinkedHashMap entryMap=(LinkedHashMap)cache.get(pathinfo);
        if (entryMap!=null)
        {
            // System.out.println(" Cache hit "+pathinfo);         
        }
        else
        {
         entryMap=resolveEntry(pathinfo);
         cache.put(pathinfo,entryMap);
        }
                
        SlotWrapper wrapper=new SlotWrapper(response);
        
                
        // hard wire in /slot path for servlet, slots_root is only used for .jsp refs,
        // not needed for .slot refs, can"t use getServletPath(), as it won"t be valid 
        // when called for .slot
        
        request.setAttribute("slots_root", request.getContextPath()+"/slot");
                
        Iterator keys=entryMap.keySet().iterator();
        while (keys.hasNext()) {
            String attr=(String)keys.next();
            
            if ("base".equals(attr)) {
                continue;
            }
            
            String attrfile=(String)entryMap.get(attr);
            
            String st=null;
            // we replace with the context path of this webapp, useful for client side references, e.g. css
            String filtered=attrfile.replaceAll("/\\$WEBROOT", request.getContextPath());
            
            if (filtered.startsWith("\"")) {
                st=filtered.replaceAll("\"", "");
            }
            else {
                
                st=wrapper.include(request,filtered);
                
            }
            
            request.setAttribute("slots_"+attr, st);
        }
        // if we haven"t overriden content then take it from pathinfo
        if (!entryMap.containsKey("content")) {
                                                   
            String st=wrapper.include(request,pathinfo);
                       
            request.setAttribute("slots_content", st);
        }
           
                
        String basefile=(String)entryMap.get("base");
        RequestDispatcher disp=request.getRequestDispatcher(basefile);
        disp.forward(request,response);
        out.close();
    }
  
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
  
    
}


 

<< Slots Central

<< Software Reality Front Page

 

All trademarks and copyrights on this page are owned by their respective owners.
Stories and articles are owned by the original author.
All the rest Copyright © 1998-2007 Matt Stephens. ALL RIGHTS RESERVED.