Coverage Report - org.webslinger.WebslingerServletContext
 
Classes in this File Line Coverage Branch Coverage Complexity
WebslingerServletContext
48%
219/454
65%
34/52
0
WebslingerServletContext$1
100%
2/2
N/A
0
WebslingerServletContext$10
25%
2/8
0%
0/1
0
WebslingerServletContext$11
33%
1/3
N/A
0
WebslingerServletContext$12
33%
1/3
N/A
0
WebslingerServletContext$13
33%
1/3
N/A
0
WebslingerServletContext$14
33%
1/3
N/A
0
WebslingerServletContext$15
67%
2/3
N/A
0
WebslingerServletContext$16
89%
8/9
100%
3/3
0
WebslingerServletContext$17
100%
2/2
N/A
0
WebslingerServletContext$2
100%
3/3
N/A
0
WebslingerServletContext$3
100%
8/8
N/A
0
WebslingerServletContext$4
50%
1/2
N/A
0
WebslingerServletContext$5
0%
0/25
0%
0/3
0
WebslingerServletContext$6
0%
0/6
N/A
0
WebslingerServletContext$7
57%
4/7
N/A
0
WebslingerServletContext$8
45%
10/22
N/A
0
WebslingerServletContext$9
20%
1/5
N/A
0
WebslingerServletContext$ChainCache
56%
9/16
100%
2/2
0
WebslingerServletContext$EventListenerCaller
N/A
N/A
0
WebslingerServletContext$EventListenerFactory
N/A
N/A
0
WebslingerServletContext$EventListenerList
36%
4/11
0%
0/2
0
WebslingerServletContext$FileObjectAttributeSplitTTLObject
100%
5/5
100%
1/1
0
WebslingerServletContext$FileObjectFilters
89%
8/9
100%
1/1
0
WebslingerServletContext$InitTTLCachedObject
9%
3/32
0%
0/1
0
WebslingerServletContext$PathContextFilters
80%
8/10
100%
1/1
0
WebslingerServletContext$RequestEventsRequestListener
92%
24/26
100%
6/6
0
WebslingerServletContext$RequestFilterChain
47%
16/34
N/A
0
WebslingerServletContext$ServletRequestListenerFactory
25%
2/8
0%
0/1
0
WebslingerServletContext$TriggerListCache
0%
0/2
N/A
0
WebslingerServletContext$VMData
0%
0/3
N/A
0
WebslingerServletContext$WebslingerFilterChainCascade
55%
6/11
N/A
0
WebslingerServletContext$WebslingerServletContextListener
0%
0/9
N/A
0
WebslingerServletContext$WebslingerServletRequestListener
0%
0/9
N/A
0
 
 1  
 package org.webslinger;
 2  
 
 3  
 import java.io.InputStream;
 4  
 import java.io.IOException;
 5  
 import java.io.PrintWriter;
 6  
 import java.io.StringWriter;
 7  
 import java.io.Writer;
 8  
 import java.net.MalformedURLException;
 9  
 import java.net.SocketException;
 10  
 import java.net.URL;
 11  
 import java.net.HttpURLConnection;
 12  
 import java.security.Principal;
 13  
 import java.util.ArrayList;
 14  
 import java.util.Collections;
 15  
 import java.util.Enumeration;
 16  
 import java.util.EnumMap;
 17  
 import java.util.EventListener;
 18  
 import java.util.EventObject;
 19  
 import java.util.HashMap;
 20  
 import java.util.HashSet;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.Set;
 25  
 import java.util.TreeSet;
 26  
 import java.util.concurrent.Callable;
 27  
 import java.util.concurrent.ConcurrentHashMap;
 28  
 import java.util.concurrent.ExecutionException;
 29  
 import java.util.concurrent.Future;
 30  
 import java.util.concurrent.atomic.AtomicInteger;
 31  
 import javax.imageio.spi.ServiceRegistry;
 32  
 import javax.servlet.Filter;
 33  
 import javax.servlet.FilterChain;
 34  
 import javax.servlet.FilterConfig;
 35  
 import javax.servlet.RequestDispatcher;
 36  
 import javax.servlet.Servlet;
 37  
 import javax.servlet.ServletConfig;
 38  
 import javax.servlet.ServletContext;
 39  
 import javax.servlet.ServletContextEvent;
 40  
 import javax.servlet.ServletContextListener;
 41  
 import javax.servlet.ServletException;
 42  
 import javax.servlet.ServletOutputStream;
 43  
 import javax.servlet.ServletRequest;
 44  
 import javax.servlet.ServletRequestEvent;
 45  
 import javax.servlet.ServletRequestListener;
 46  
 import javax.servlet.ServletRequestWrapper;
 47  
 import javax.servlet.ServletResponse;
 48  
 import javax.servlet.ServletResponseWrapper;
 49  
 import javax.servlet.http.Cookie;
 50  
 import javax.servlet.http.HttpServletRequest;
 51  
 import javax.servlet.http.HttpServletResponse;
 52  
 import javax.servlet.http.HttpSession;
 53  
 
 54  
 import org.apache.bsf.BSFException;
 55  
 import org.apache.commons.vfs.FileContent;
 56  
 import org.apache.commons.vfs.FileName;
 57  
 import org.apache.commons.vfs.FileObject;
 58  
 import org.apache.commons.vfs.FileSystem;
 59  
 import org.apache.commons.vfs.FileSystemException;
 60  
 import org.apache.commons.vfs.FileType;
 61  
 import org.apache.commons.vfs.provider.DelegateFileObject;
 62  
 import org.apache.commons.vfs.provider.local.LocalFile;
 63  
 
 64  
 import org.apache.commons.collections.iterators.IteratorEnumeration;
 65  
 import org.webslinger.commons.fileupload.AbstractCommonsVfsFileItem;
 66  
 import org.webslinger.commons.fileupload.CommonsVfsFileItemFactory;
 67  
 import org.webslinger.commons.vfs.VFSUtil;
 68  
 import org.webslinger.commons.vfs.flat.FlatFileObject;
 69  
 import org.webslinger.commons.vfs.util.FileObjectAttributeTTLObject;
 70  
 import org.webslinger.container.CommonsVfsFileInfo;
 71  
 import org.webslinger.container.GivenPathInfo;
 72  
 import org.webslinger.container.CommonsVfsFileInfo;
 73  
 import org.webslinger.container.WebslingerContainer;
 74  
 import org.webslinger.container.StringFileInfo;
 75  
 import org.webslinger.io.ThreadLocalRollingWriterFactory;
 76  
 import static org.webslinger.lang.ClassUtil.NULL;
 77  
 import org.webslinger.lang.ConcurrentCache;
 78  
 import org.webslinger.lang.ExecutionPool;
 79  
 import org.webslinger.lang.ThreadSingletonState;
 80  
 import org.webslinger.io.IOUtil;
 81  
 import org.webslinger.servlet.EmbeddedHttpSessionManager;
 82  
 import org.webslinger.servlet.FakeHttpServletRequest;
 83  
 import org.webslinger.servlet.FakeHttpServletResponse;
 84  
 import org.webslinger.servlet.FakeResource;
 85  
 import org.webslinger.servlet.FakeServletContext;
 86  
 import org.webslinger.servlet.FakeServletRequest;
 87  
 import org.webslinger.servlet.FakeServletResponse;
 88  
 import org.webslinger.servlet.HttpSessionData;
 89  
 import org.webslinger.servlet.HttpSessionStore;
 90  
 import org.webslinger.servlet.HttpSessionId;
 91  
 import org.webslinger.servlet.HttpSessionIdManager;
 92  
 import org.webslinger.servlet.OverrideHttpSessionRequest;
 93  
 import org.webslinger.servlet.OverrideHttpSessionResponse;
 94  
 import org.webslinger.servlet.WrappedHttpServletRequest;
 95  
 import org.webslinger.servlet.WrappedHttpServletResponse;
 96  
 import org.webslinger.servlet.webxml.ConfiguredFilter;
 97  
 import org.webslinger.servlet.webxml.ConfiguredServlet;
 98  
 import org.webslinger.servlet.webxml.FilterMapping;
 99  
 import org.webslinger.util.GeneratedResult;
 100  
 import org.webslinger.util.TTLCachedObject;
 101  
 import org.webslinger.util.TTLObject;
 102  
 import org.webslinger.vfs.VFSDelegate;
 103  
 import org.webslinger.vfs.TypeVFSDelegate;
 104  
 import org.webslinger.vfs.GeneratedStringVFSDelegate;
 105  
 
 106  
 import org.xml.sax.SAXException;
 107  
 
 108  0
 public class WebslingerServletContext implements FakeServletContext {
 109  
     static {
 110  1
         TTLObject.setDefaultTTLForClass(InitTTLCachedObject.class, 1000);
 111  1
         TTLObject.setDefaultTTLForClass(FileObjectFilters.class, 60000);
 112  1
         TTLObject.setDefaultTTLForClass(FileObjectAttributeSplitTTLObject.class, 60000);
 113  1
         TTLObject.setDefaultTTLForClass(TriggerListCache.class, 1000);
 114  1
         TTLObject.setDefaultTTLForClass(PathContextFilters.class, 60000);
 115  1
         TTLObject.setDefaultTTLForClass(RequestEventsRequestListener.class, 60000);
 116  
     }
 117  
 
 118  
     public static final String WEBSLINGER_SESSION_COOKIE_NAME = "WEBSLINGERSESSIONID";
 119  
     public static final String WEBSLINGER_SESSION_PARAMETER_NAME = "WEBSLINGERSESSIONID";
 120  
     public static final String DEFAULT_TYPE = "binary";
 121  1
     public static final String SESSION_KEY = WebslingerServletContext.class.getName() + ":sessions";
 122  
 
 123  
     protected final String id;
 124  
     protected final WebslingerContainer container;
 125  26
     protected final HashMap<String, Object> attributes = new HashMap<String, Object>();
 126  26
     protected final ConcurrentHashMap<String, TypeHandler> typeHandlers = new ConcurrentHashMap<String, TypeHandler>();
 127  26
     protected final Map<DispatcherType, ChainCache> chains = new EnumMap<DispatcherType, ChainCache>(DispatcherType.class);
 128  26
     protected final ConcurrentCache<PathContext, WebslingerFilter> filters = new ConcurrentCache<PathContext, WebslingerFilter>(WebslingerServletContext.class, "filters", null, ConcurrentCache.SOFT) {
 129  
         protected WebslingerFilter createValue(PathContext pc) {
 130  1
             return createWebslingerFilter(pc);
 131  
         }
 132  
     };
 133  26
     protected final ConcurrentHashMap<String, TTLObject<Object>> initMap = new ConcurrentHashMap<String, TTLObject<Object>>();
 134  
     protected final ServletRequestListener requestEventsListener;
 135  
     protected final EmbeddedHttpSessionManager sessionManager;
 136  
 
 137  26
     protected final ConcurrentCache<FileName, EventListenerList> servletListenerCache = new ConcurrentCache<FileName, EventListenerList>(WebslingerServletContext.class, "servletListenerCache", null, ConcurrentCache.SOFT) {
 138  26
         private final ServletRequestListenerFactory factory = new ServletRequestListenerFactory();
 139  
 
 140  
         protected EventListenerList createValue(FileName name) throws Exception {
 141  248
             return new EventListenerList(factory, getWWW().getFileSystem().resolveFile(name), "servlet-request-listeners");
 142  
         }
 143  
     };
 144  1
     protected static final ThreadLocal<WebslingerInvoker> invokerLocal = new ThreadLocal<WebslingerInvoker>();
 145  1
     protected static final ThreadLocal<WebslingerServletContext> contextLocal = new ThreadLocal<WebslingerServletContext>();
 146  
     protected final TypeVFSDelegate vfsDelegate;
 147  
     protected final CommonsVfsFileItemFactory fileItemFactory;
 148  26
     protected final ThreadSingletonState threadStateInitializer = new ThreadSingletonState() {
 149  
         protected Object data;
 150  
 
 151  
         public void start() {
 152  333
             data = getContainer().start();
 153  333
             contextLocal.set(WebslingerServletContext.this);
 154  333
         }
 155  
 
 156  
         public void finish() {
 157  333
             getContainer().finish(data);
 158  333
             invokerLocal.set(null);
 159  333
             contextLocal.set(null);
 160  333
         }
 161  
     };
 162  
 
 163  
     public static WebslingerServletContext getCurrentWebslingerServletContext() {
 164  0
         return contextLocal.get();
 165  
     }
 166  
 
 167  26
     public WebslingerServletContext(String id, WebslingerContainer container) throws WebslingerException {
 168  26
         this.id = id;
 169  26
         sessionManager = new EmbeddedHttpSessionManager(id);
 170  26
         chains.put(DispatcherType.REQUEST, new ChainCache("filters", DispatcherType.REQUEST));
 171  26
         chains.put(DispatcherType.FORWARD, new ChainCache("forward-filters", DispatcherType.FORWARD));
 172  26
         chains.put(DispatcherType.INCLUDE, new ChainCache("include-filters", DispatcherType.INCLUDE));
 173  26
         this.container = container;
 174  
         try {
 175  26
             requestEventsListener = new RequestEventsRequestListener();
 176  26
             fileItemFactory = new CommonsVfsFileItemFactory(getContainer().getRoot().resolveFile("/Var/Upload"));
 177  0
         } catch (IOException e) {
 178  0
             throw new WebslingerException("creating classloader", e);
 179  26
         }
 180  26
         TypeVFSDelegate.Resolver typeVFSDelegateResolver = new TypeVFSDelegate.Resolver() {
 181  
             public Object resolve(String name) throws IOException {
 182  0
                 return WebslingerServletContext.this.resolve(name);
 183  
             }
 184  
         };
 185  
         try {
 186  26
             vfsDelegate = new TypeVFSDelegate(typeVFSDelegateResolver);
 187  
 
 188  26
             CommonsVfsFileInfo.CommonsVfsFileInfoVFSDelegate<Object> commonsVfsDelegate = new CommonsVfsFileInfo.CommonsVfsFileInfoVFSDelegate<Object>(vfsDelegate);
 189  26
             vfsDelegate.addVFSDelegate(CommonsVfsFileInfo.class, commonsVfsDelegate);
 190  26
             vfsDelegate.addVFSDelegate(StringFileInfo.class, new StringFileInfo.StringFileInfoVFSDelegate<Object>(vfsDelegate));
 191  26
             vfsDelegate.addVFSDelegate(PathContext.class, new PathContext.PathContextVFSDelegate<Object>(vfsDelegate));
 192  26
             vfsDelegate.addVFSDelegate(Webslinger.class, new Webslinger.WebslingerVFSDelegate<Object>(vfsDelegate));
 193  26
             vfsDelegate.addVFSDelegate(GeneratedStringVFSDelegate.GeneratedString.class, new GeneratedStringVFSDelegate<Object>(vfsDelegate));
 194  0
         } catch (Exception e) {
 195  0
             throw new WebslingerException(e.getMessage(), e);
 196  26
         }
 197  26
     }
 198  
 
 199  
     public void service(String path) throws IOException, ServletException {
 200  0
         service(getRequestDispatcher(path));
 201  0
     }
 202  
 
 203  
     public void service(String path, Map<String, Object> context) throws IOException, ServletException {
 204  0
         service(getRequestDispatcher(path, context));
 205  0
     }
 206  
 
 207  
     protected void service(WebslingerRequestDispatcher dispatcher) throws IOException, ServletException {
 208  0
         HttpServletResponse response = new FakeHttpServletResponse(new FakeServletResponse(new StringWriter()));
 209  0
         PathContext pc = dispatcher.getPathContext();
 210  0
         HttpServletRequest request = new FakeHttpServletRequest(this, new FakeServletRequest(this, pc), response, pc);
 211  0
         service(request, response, dispatcher);
 212  0
     }
 213  
 
 214  1
     private static final AtomicInteger vmKey = new AtomicInteger();
 215  1
     private static final ConcurrentHashMap<String, VMData> vmData = new ConcurrentHashMap<String, VMData>();
 216  
 
 217  
     private static final class VMData {
 218  
         protected final Map<String, Object> context;
 219  
         protected Object result;
 220  
 
 221  0
         protected VMData(Map<String, Object> context) {
 222  0
             this.context = context;
 223  0
         }
 224  
     }
 225  
 
 226  
     public static Object invokeInVM(String hostName, int port, String path, Map<String, Object> context) throws IOException {
 227  0
         VMData data = new VMData(context);
 228  0
         String key = Integer.toString(vmKey.incrementAndGet());
 229  0
         HttpURLConnection connection = (HttpURLConnection) new URL("http://127.0.0.1:" + port + "/" + path).openConnection();
 230  0
         connection.setRequestProperty("VM-Key", key);
 231  0
         connection.setRequestMethod("GET");
 232  0
         connection.setRequestProperty("Host", hostName);
 233  0
         connection.setRequestProperty("Content-Type", "rpc/in-vm");
 234  
         try {
 235  0
             vmData.put(key, data);
 236  0
             connection.connect();
 237  0
             IOUtil.dump(connection.getInputStream(), true);
 238  0
             return data.result;
 239  
         } finally {
 240  0
             vmData.remove(key);
 241  
         }
 242  
     }
 243  
 
 244  
     public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 245  307
         String vmKey = request.getHeader("VM-Key");
 246  307
         boolean normalRequest =
 247  
             !"rpc/in-vm".equals(request.getContentType()) ||
 248  
             !"127.0.0.1".equals(request.getLocalAddr()) ||
 249  
             vmKey == null ||
 250  
             !vmData.containsKey(vmKey);
 251  307
         if (normalRequest) {
 252  307
             HttpServletRequest[] requestHolder = new HttpServletRequest[] {request};
 253  307
             HttpServletResponse[] responseHolder = new HttpServletResponse[] {response};
 254  307
             wrapSession(requestHolder, responseHolder);
 255  307
             service(requestHolder[0], responseHolder[0], getRequestDispatcher(requestHolder[0].getPathInfo()));
 256  307
         } else {
 257  0
             VMData data = vmData.get(vmKey);
 258  0
             PathContext pc = resolve(request.getPathInfo());
 259  0
             StringWriter sw = new StringWriter();
 260  0
             HttpServletRequest fakeRequest = alterPaths(pc, request);
 261  0
             HttpServletResponse fakeResponse = alterPaths(pc, request, response);
 262  0
             data.result = run(pc, fakeRequest, fakeResponse, data.context);
 263  
         }
 264  307
     }
 265  
 
 266  
     protected void wrapSession(HttpServletRequest[] request, HttpServletResponse[] response) throws ServletException, IOException {
 267  307
         String idExtractor = (String) getConfigItem("org.webslinger.servlet.HttpSessionIdManager");
 268  
         final HttpSessionIdManager sessionIdManager;
 269  307
         if (idExtractor != null) {
 270  0
             final PathContext pc = resolve(idExtractor);
 271  0
             sessionIdManager = new HttpSessionIdManager() {
 272  
                 public HttpSessionId extractHttpSessionId(HttpServletRequest[] request, HttpServletResponse[] response) {
 273  0
                     Map<String, Object> context = new HashMap<String, Object>();
 274  0
                     context.put("sessionRequest", request[0]);
 275  0
                     context.put("sessionResponse", response[0]);
 276  0
                     Map<String, Object> result = (Map<String, Object>) runDirectNoThrow("HttpSessionIdManager.extractHttpSessionId", pc, context, "extractHttpSessionId", null);
 277  0
                     if (result == null) return null;
 278  0
                     if (result.containsKey("sessionRequest")) request[0] = (HttpServletRequest) result.get("sessionRequest");
 279  0
                     if (result.containsKey("sessionResponse")) response[0] = (HttpServletResponse) result.get("sessionResponse");
 280  0
                     return (HttpSessionId) result.get("sessionId");
 281  
                 }
 282  
 
 283  
                 public HttpSessionId createHttpSessionId() {
 284  0
                     Map<String, Object> context = new HashMap<String, Object>();
 285  0
                     return (HttpSessionId) runDirectNoThrow("HttpSessionIdManager.createHttpSessionId", pc, context, "createHttpSessionId", null);
 286  
                 }
 287  
 
 288  
                 public void setHttpSessionId(HttpServletRequest request, HttpServletResponse response, HttpSessionId id) {
 289  0
                     Map<String, Object> context = new HashMap<String, Object>();
 290  0
                     context.put("sessionRequest", request);
 291  0
                     context.put("sessionResponse", response);
 292  0
                     context.put("sessionId", id);
 293  0
                     runDirectNoThrow("HttpSessionIdManager.setHttpSessionId", pc, context, "setHttpSessionId", null);
 294  0
                 }
 295  
 
 296  
                 public String encodeURL(String path, HttpSessionId id) {
 297  0
                     Map<String, Object> context = new HashMap<String, Object>();
 298  0
                     context.put("sessionPath", path);
 299  0
                     context.put("sessionId", id);
 300  0
                     return (String) runDirectNoThrow("HttpSessionIdManager.encodeURL", pc, context, "encodeURL", null);
 301  
                 }
 302  
 
 303  
                 public String encodeRedirectURL(String path, HttpSessionId id) {
 304  0
                     Map<String, Object> context = new HashMap<String, Object>();
 305  0
                     context.put("sessionPath", path);
 306  0
                     context.put("sessionId", id);
 307  0
                     return (String) runDirectNoThrow("HttpSessionIdManager.encodeURL", pc, context, "encodeRedirectURL", null);
 308  
                 }
 309  
             };
 310  0
         } else {
 311  307
             sessionIdManager = sessionManager;
 312  
         }
 313  
         final HttpSessionStore httpSessionStore;
 314  307
         String sessionStore = (String) getConfigItem("org.webslinger.servlet.HttpSessionStore");
 315  307
         if (sessionStore != null) {
 316  0
             final PathContext pc = resolve(sessionStore);
 317  0
             httpSessionStore = new HttpSessionStore() {
 318  
                 public HttpSessionData getSessionData(HttpServletRequest request, HttpSessionId id, boolean create) {
 319  0
                     Map<String, Object> context = new HashMap<String, Object>();
 320  0
                     context.put("sessionRequest", request);
 321  0
                     context.put("sessionId", id);
 322  0
                     context.put("create", create);
 323  0
                     return (HttpSessionData) runDirectNoThrow("HttpSessionStore.getSessionData", pc, context, "getSessionData", null);
 324  
                 }
 325  
             };
 326  0
         } else {
 327  307
             httpSessionStore = sessionManager;
 328  
         }
 329  307
         HttpSessionId sessionId = sessionIdManager.extractHttpSessionId(request, response);
 330  307
         OverrideHttpSessionRequest newRequest = new OverrideHttpSessionRequest(request[0], this, sessionIdManager, httpSessionStore, sessionId);
 331  307
         OverrideHttpSessionResponse newResponse = new OverrideHttpSessionResponse(response[0], newRequest);
 332  307
         request[0] = newRequest;
 333  307
         response[0] = newResponse;
 334  307
     }
 335  
 
 336  
     protected void service(HttpServletRequest request, HttpServletResponse response, final WebslingerRequestDispatcher dispatcher) throws IOException, ServletException {
 337  307
         start();
 338  
         try {
 339  
             //final HttpServletRequest wsRequest = new WebslingerHttpServletRequest(context, pathContext, request);
 340  307
             WebslingerFilterChain lastChain = new WebslingerFilterChain() {
 341  
                 public void doComet(CometEventType eventType, ServletRequest request, ServletResponse response) throws IOException, ServletException {
 342  0
                     dispatcher.comet(eventType, request, response);
 343  0
                 }
 344  
 
 345  
                 public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
 346  283
                     dispatcher.forward(request, response);
 347  283
                 }
 348  
 
 349  
                 public PathContext getPathContext() {
 350  132
                     return dispatcher.getPathContext();
 351  
                 }
 352  
 
 353  
                 public Map<String, Object> getContext() {
 354  0
                     return dispatcher.getContext();
 355  
                 }
 356  
             };
 357  
             try {
 358  307
                 getFilterChain(dispatcher.getPathContext(), lastChain).doFilter(request, response);
 359  0
             } catch (Throwable t) {
 360  0
                 Throwable cause = t.getCause();
 361  0
                 while (cause != null) {
 362  0
                     t = cause;
 363  0
                     cause = t.getCause();
 364  
                 }
 365  0
                 throw t;
 366  307
             }
 367  
             //RequestDispatcher dispatcher = context.getRequestDispatcher(pathContext);
 368  
             //dispatcher.forward(wsRequest, response);
 369  307
             response.flushBuffer();
 370  0
         } catch (SocketException e) {
 371  0
         } catch (Error e) {
 372  0
             throw e;
 373  0
         } catch (RuntimeException e) {
 374  0
             throw e;
 375  0
         } catch (IOException e) {
 376  0
             throw e;
 377  0
         } catch (ServletException e) {
 378  0
             throw e;
 379  0
         } catch (Throwable e) {
 380  0
             throw new ServletException(e.getMessage(), e);
 381  
         } finally {
 382  307
             ExecutionPool.runAtExit();
 383  307
         }
 384  307
     }
 385  
 
 386  
     public void initializeRequest(HttpServletRequest request) {
 387  526
         getContainer().initializeRequest(this, request);
 388  526
     }
 389  
 
 390  
     public WebslingerClassLoader getClassLoader() {
 391  77
         return getContainer().getClassLoader();
 392  
     }
 393  
 
 394  
     public void start() {
 395  333
         ExecutionPool.addAtExit(threadStateInitializer);
 396  333
     }
 397  
 
 398  
     public VFSDelegate<Object, Object, ?> getVFSDelegate() {
 399  362
         return vfsDelegate;
 400  
     }
 401  
 
 402  
     public WebslingerContainer getContainer() {
 403  4720
         return container;
 404  
     }
 405  
 
 406  
     public WebslingerInvoker getInvoker() throws IOException {
 407  1546
         WebslingerInvoker invoker = invokerLocal.get();
 408  1546
         if (invoker == null) {
 409  308
             invoker = new WebslingerInvoker(this);
 410  308
             invokerLocal.set(invoker);
 411  
         }
 412  1546
         return invoker;
 413  
     }
 414  
 
 415  
     public void runStartup() throws IOException, ServletException {
 416  26
         Iterator<WebslingerStartup> it1 = ServiceRegistry.lookupProviders(WebslingerStartup.class, getClassLoader());
 417  26
         List<Future> futures = new ArrayList<Future>();
 418  52
         while (it1.hasNext()) {
 419  26
             futures.addAll(it1.next().start(this));
 420  
         }
 421  26
         Iterator<Future> it2 = futures.iterator();
 422  26
         while (it2.hasNext()) {
 423  
             try {
 424  
                 try {
 425  0
                     it2.next().get();
 426  0
                 } catch (ExecutionException e) {
 427  0
                     throw e.getCause();
 428  0
                 }
 429  0
             } catch (RuntimeException e) {
 430  0
                 throw e;
 431  0
             } catch (IOException e) {
 432  0
                 throw e;
 433  0
             } catch (ServletException e) {
 434  0
                 throw e;
 435  0
             } catch (Throwable e) {
 436  0
                 throw (ServletException) new ServletException(e.getMessage()).initCause(e);
 437  0
             }
 438  
         }
 439  26
     }
 440  
 
 441  
     public void init() throws IOException, ServletException {
 442  
         try {
 443  26
             getContainer().init(this);
 444  26
             start();
 445  
             try {
 446  26
                 runStartup();
 447  
             } finally {
 448  26
                 ExecutionPool.runAtExit();
 449  26
             }
 450  0
         } catch (IOException e) {
 451  0
             throw e;
 452  0
         } catch (RuntimeException e) {
 453  0
             throw e;
 454  0
         } catch (ServletException e) {
 455  0
             throw e;
 456  0
         } catch (Exception e) {
 457  0
             throw new ServletException(e.getMessage(), e);
 458  26
         }
 459  26
     }
 460  
 
 461  
     public AbstractCommonsVfsFileItem createFileItem(String fieldName, String contentType, boolean isFormField, String fileName) {
 462  0
         return (AbstractCommonsVfsFileItem) fileItemFactory.createItem(fieldName, contentType, isFormField, fileName);
 463  
     }
 464  
 
 465  
     public FileObject getWWW() {
 466  464
         return getContainer().getWWW();
 467  
     }
 468  
 
 469  
     public FileObject getFile(String path) throws IOException {
 470  51
         return getWWW().resolveFile(path);
 471  
     }
 472  
 
 473  
     public void destroy() {
 474  26
         getContainer().destroy();
 475  26
     }
 476  
 
 477  
     public String[] getConfigStringSplit(String name) throws IOException {
 478  0
         return getContainer().getConfigStringSplit(name);
 479  
     }
 480  
 
 481  
     public String getConfigString(String name) throws IOException {
 482  35
         return getContainer().getConfigString(name);
 483  
     }
 484  
 
 485  
     public Object getConfigItem(String name) throws IOException {
 486  622
         return getContainer().getConfigItem(name);
 487  
     }
 488  
 
 489  
     protected static final class WebslingerFilterChainCascade implements WebslingerFilterChain {
 490  
         private final WebslingerFilter filter;
 491  
         private final WebslingerFilterChain next;
 492  
 
 493  66
         protected WebslingerFilterChainCascade(WebslingerFilter filter, WebslingerFilterChain next) {
 494  66
             this.filter = filter;
 495  66
             this.next = next;
 496  66
         }
 497  
 
 498  
         public void doComet(CometEventType eventType, ServletRequest request, ServletResponse response) throws IOException, ServletException {
 499  0
             filter.doComet(eventType, request, response, next);
 500  0
         }
 501  
 
 502  
         public final void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
 503  66
             filter.doFilter(request, response, next);
 504  66
         }
 505  
 
 506  
         public PathContext getPathContext() {
 507  0
             return next.getPathContext();
 508  
         }
 509  
 
 510  
         public Map<String, Object> getContext() {
 511  0
             return next.getContext();
 512  
         }
 513  
 
 514  
         public String toString() {
 515  0
             return "WebslingerFilterChain(" + filter + ", " + next + ")";
 516  
         }
 517  
     }
 518  
 
 519  
     public static abstract class FileObjectAttributeSplitTTLObject<T> extends FileObjectAttributeTTLObject<T, String> {
 520  
         public FileObjectAttributeSplitTTLObject(FileObject file, String attributeName, Class<T> resultType) {
 521  356
             super(file, attributeName, resultType, String.class);
 522  356
         }
 523  
 
 524  
         protected String[] splitAttribute(String attributeValue) throws IOException {
 525  1
             if (!file.exists()) return null;
 526  1
             VFSUtil.refresh(file);
 527  1
             return attributeValue.split("[, \r\n]+");
 528  
         }
 529  
     }
 530  
 
 531  
     protected WebslingerFilter[] getFilterList(FileObject file, String[] filterNames, DispatcherType dispatcherType) throws IOException {
 532  1
         ArrayList<WebslingerFilter> filters = new ArrayList<WebslingerFilter>();
 533  1
         String path = file.getName().getPath();
 534  1
         String ext = file.getName().getExtension();
 535  1
         for (FilterMapping mapping: getContainer().getFilterMappings()) {
 536  0
             String urlPattern = mapping.getUrlPattern();
 537  0
             WebslingerFilter filter = getContainer().getServletFilter(mapping.getFilterName());
 538  0
             System.err.println("name[" + mapping.getFilterName() + "] filter=" + filter + ", pattern[" + urlPattern + "], path[" + path + "]");
 539  0
             if (filter == null) continue;
 540  0
             if (!mapping.getDispatcherType().contains(dispatcherType)) continue;
 541  0
             if (urlPattern != null) {
 542  0
                 if (urlPattern.equals(path)) {
 543  0
                 } else if (urlPattern.equals("/*")) {
 544  0
                 } else if (urlPattern.endsWith("/*")) {
 545  0
                     int patternLength = urlPattern.length() - 2;
 546  0
                     if (!urlPattern.regionMatches(0, path, 0, patternLength)) continue;
 547  0
                     if (path.length() == patternLength) {
 548  0
                     } else if (path.charAt(patternLength) == '/') {
 549  
                     } else {
 550  
                         continue;
 551  
                     }
 552  0
                 } else if (urlPattern.startsWith("*.")) {
 553  0
                     if (urlPattern.length() <= 2) continue;
 554  0
                     if (!urlPattern.regionMatches(2, ext, 0, urlPattern.length() - 2)) continue;
 555  
                 }
 556  0
                 System.err.println("adding filter: " + filter);
 557  0
                 filters.add(filter);
 558  
             }
 559  
         }
 560  
 
 561  
         try {
 562  2
             for (String filterName: filterNames) {
 563  1
                 filters.add(getFilter(parse(file, filterName)));
 564  
             }
 565  0
         } catch (ServletException e) {
 566  0
             throw (IOException) new IOException(e.getMessage()).initCause(e);
 567  1
         }
 568  
         //System.err.println(file + " -> filters=" + filters);
 569  1
         return filters.toArray(new WebslingerFilter[filters.size()]);
 570  
     }
 571  
 
 572  1
     protected class FileObjectFilters extends FileObjectAttributeSplitTTLObject<WebslingerFilter[]> {
 573  
         private final DispatcherType dispatcherType;
 574  
 
 575  108
         protected FileObjectFilters(FileObject file, String attributeName, DispatcherType dispatcherType) {
 576  108
             super(file, attributeName, WebslingerFilter[].class);
 577  108
             this.dispatcherType = dispatcherType;
 578  108
         }
 579  
 
 580  
         protected WebslingerFilter[] parseAttribute(String attributeValue) throws IOException {
 581  1
             String[] filterNames = splitAttribute(attributeValue);
 582  1
             if (filterNames == null) return null;
 583  1
             return getFilterList(file, filterNames, dispatcherType);
 584  
         }
 585  
 
 586  
         public String toString() {
 587  0
             return "PathContextFilters(" + file + ", " + attributeName + ", " + dispatcherType + ")";
 588  
         }
 589  
     }
 590  
 
 591  159
     protected class PathContextFilters extends TTLObject<WebslingerFilter[]> {
 592  
         private final PathContext pc;
 593  
         private final String attributeName;
 594  
         private final DispatcherType dispatcherType;
 595  
 
 596  159
         protected PathContextFilters(PathContext pc, String attributeName, DispatcherType dispatcherType) {
 597  159
             this.pc = pc;
 598  159
             this.attributeName = attributeName;
 599  159
             this.dispatcherType = dispatcherType;
 600  159
         }
 601  
 
 602  
         protected WebslingerFilter[] load(WebslingerFilter[] old) throws IOException {
 603  159
             String[] filterNames = pc.getSplitAttribute(attributeName);
 604  159
             if (filterNames == null) return null;
 605  0
             return getFilterList(pc.getFile(), filterNames, dispatcherType);
 606  
         }
 607  
 
 608  
         public String toString() {
 609  0
             return "PathContextFilters(" + pc + ", " + attributeName + ", " + dispatcherType + ")";
 610  
         }
 611  
     }
 612  
 
 613  
     protected WebslingerFilter createWebslingerFilter(final PathContext pc) {
 614  1
             WebslingerFilter filter = new WebslingerFilter() {
 615  
                 protected FilterConfig config;
 616  
                 protected Object initObject;
 617  
 
 618  
                 public void init(FilterConfig config) throws ServletException {
 619  1
                     this.config = config;
 620  
                     try {
 621  1
                         initObject = runDirect(pc, null, "filter-init", config);
 622  0
                     } catch (IOException e) {
 623  0
                         throw new ServletException(e.getMessage(), e);
 624  1
                     }
 625  1
                 }
 626  
 
 627  
                 public void destroy() {
 628  0
                     HashMap<String, Object> context = new HashMap<String, Object>();
 629  0
                     context.put("FilterInit", initObject);
 630  0
                     runDirectNoThrow("", pc, context, "filter-destroy", null);
 631  0
                 }
 632  
 
 633  
                 public void doComet(CometEventType eventType, ServletRequest request, ServletResponse response, WebslingerFilterChain chain) throws IOException, ServletException {
 634  
                     //System.err.println("Filter{" + pc + "}(" + request + ", " + response + ", " + chain + ")");
 635  0
                     Map<String, Object> context = new HashMap<String, Object>();
 636  0
                     context.put("FilterChain", chain);
 637  0
                     context.put("FilterInit", initObject);
 638  0
                     WebslingerServletContext.this.run(pc, (HttpServletRequest) request, (HttpServletResponse) response, context, "comet", eventType);
 639  0
                 }
 640  
 
 641  
                 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
 642  
                     //System.err.println("Filter{" + pc + "}(" + request + ", " + response + ", " + chain + ")");
 643  66
                     Map<String, Object> context = new HashMap<String, Object>();
 644  66
                     context.put("FilterChain", chain);
 645  66
                     context.put("FilterInit", initObject);
 646  66
                     WebslingerServletContext.this.run(pc, (HttpServletRequest) request, (HttpServletResponse) response, context, "filter", null);
 647  66
                 }
 648  
 
 649  
                 public String toString() {
 650  0
                     return "Filter{" + pc + "}";
 651  
                 }
 652  
             };
 653  1
             FilterConfig filterConfig = new FilterConfig() {
 654  
                 public String getFilterName() {
 655  0
                     return pc.getServletPath();
 656  
                 }
 657  
 
 658  
                 public String getInitParameter(String name) {
 659  0
                     throw new UnsupportedOperationException();
 660  
                 }
 661  
 
 662  
                 public Enumeration getInitParameterNames() {
 663  0
                     throw new UnsupportedOperationException();
 664  
                 }
 665  
 
 666  
                 public ServletContext getServletContext() {
 667  0
                     return WebslingerServletContext.this;
 668  
                 }
 669  
             };
 670  
             try {
 671  1
                 filter.init(filterConfig);
 672  0
             } catch (ServletException e) {
 673  0
                 throw (InternalError) new InternalError(e.getMessage()).initCause(e);
 674  1
             }
 675  1
             return filter;
 676  
     }
 677  
 
 678  
     // FIXME: call destroy/init when file is reloaded
 679  
     protected WebslingerFilter getFilter(final PathContext pc) throws ServletException {
 680  
         try {
 681  1
             return filters.get(pc);
 682  0
         } catch (RuntimeException e) {
 683  0
             throw e;
 684  0
         } catch (ServletException e) {
 685  0
             throw e;
 686  0
         } catch (Exception e) {
 687  0
             throw (InternalError) new InternalError(e.getMessage()).initCause(e);
 688  
         }
 689  
     }
 690  
 
 691  267
     protected class ChainCache extends ConcurrentCache<Object, TTLObject<WebslingerFilter[]>> {
 692  
         private final String attributeName;
 693  
         private final DispatcherType dispatcherType;
 694  
 
 695  78
         protected ChainCache(String attributeName, DispatcherType dispatcherType) {
 696  78
             super(WebslingerServletContext.class, "ChainCache", dispatcherType.toString(), ConcurrentCache.SOFT);
 697  78
             this.attributeName = attributeName;
 698  78
             this.dispatcherType = dispatcherType;
 699  78
         }
 700  
 
 701  
         public TTLObject<WebslingerFilter[]> get(Object key) throws IOException {
 702  
             try {
 703  892
                 return super.get(key);
 704  0
             } catch (IOException e) {
 705  0
                 throw e;
 706  0
             } catch (RuntimeException e) {
 707  0
                 throw e;
 708  0
             } catch (Exception e) {
 709  0
                 throw (InternalError) new InternalError(e.getMessage()).initCause(e);
 710  
             }
 711  
         }
 712  
 
 713  
         protected TTLObject<WebslingerFilter[]> createValue(Object value) throws Exception {
 714  267
             if (value instanceof PathContext) return new PathContextFilters((PathContext) value, attributeName, dispatcherType);
 715  108
             if (value instanceof FileName) return new FileObjectFilters(getWWW().getFileSystem().resolveFile((FileName) value), attributeName, dispatcherType);
 716  0
             throw new InternalError("Can't handle(" + value + ")");
 717  
         }
 718  
     }
 719  
 
 720  
     public WebslingerFilterChain getFilterChain(PathContext pc, WebslingerFilterChain chain) throws IOException {
 721  307
         return new RequestFilterChain(pc, getFilterChain(pc, chain, DispatcherType.REQUEST));
 722  
     }
 723  
 
 724  
     WebslingerFilterChain getFilterChain(PathContext pc, WebslingerFilterChain chain, DispatcherType dispatcherType) throws IOException {
 725  
         //System.err.println("pc=" + pc);
 726  
         //System.err.println("file=" + file);
 727  307
         ChainCache dispatcherChains = chains.get(dispatcherType);
 728  307
         PathContextFilters pcf = (PathContextFilters) dispatcherChains.get(pc);
 729  307
         WebslingerFilter[] filters = pcf.getObject();
 730  307
         if (filters != null) {
 731  0
             for (WebslingerFilter filter: filters) {
 732  0
                 chain = new WebslingerFilterChainCascade(filter, chain);
 733  
             }
 734  
         }
 735  307
         FileObject file = pc.getFile();
 736  307
         FileSystem fs = file.getFileSystem();
 737  307
         FileName name = file.getName().getParent();
 738  892
         while (name != null) {
 739  585
             FileObjectFilters fofc = (FileObjectFilters) dispatcherChains.get(name);
 740  
             //System.err.println("fofc=" + fofc);
 741  585
             filters = fofc.getObject();
 742  
             //System.err.println("perFileChains=" + perFileChains);
 743  585
             if (filters != null) {
 744  132
                 for (WebslingerFilter filter: filters) {
 745  66
                     chain = new WebslingerFilterChainCascade(filter, chain);
 746  
                 }
 747  
             }
 748  585
             name = name.getParent();
 749  585
         }
 750  307
         return chain;
 751  
     }
 752  
 
 753  
     //protected void notifyEventChain(Map listenerCache, EventListenerFactory factory, EventListenerCaller caller, String attributeName, FileObject ptr, EventObject event) throws IOException {
 754  
     public class RequestFilterChain implements WebslingerFilterChain {
 755  
         private final PathContext pc;
 756  
         private final WebslingerFilterChain chain;
 757  
 
 758  307
         protected RequestFilterChain(PathContext pc, WebslingerFilterChain chain) {
 759  307
             this.pc = pc;
 760  307
             this.chain = chain;
 761  307
         }
 762  
 
 763  
         public PathContext getPathContext() {
 764  0
             return pc;
 765  
         }
 766  
 
 767  
         public Map<String, Object> getContext() {
 768  0
             return null;
 769  
         }
 770  
 
 771  
         public void doComet(CometEventType eventType, ServletRequest request, ServletResponse response) throws IOException, ServletException {
 772  0
             ServletRequestEvent sre = new ServletRequestEvent(WebslingerServletContext.this, request);
 773  0
             ThreadLocalRollingWriterFactory.setRollingWriterFactory(container.getLogFactory());
 774  
             try {
 775  0
                 request.setAttribute("RequestPath", pc);
 776  0
                 requestEventsListener.requestInitialized(sre);
 777  0
                 notifyEventChain(servletListenerCache, SERVLET_REQUEST_LISTENER_CONTEXT_INITIALIZED, pc.getFile().getName(), sre);
 778  0
                 chain.doComet(eventType, request, response);
 779  0
             } catch (RuntimeException e) {
 780  0
                 throw e;
 781  
             } finally {
 782  0
                 notifyEventChain(servletListenerCache, SERVLET_REQUEST_LISTENER_CONTEXT_DESTROYED, pc.getFile().getName(), sre);
 783  0
                 requestEventsListener.requestDestroyed(sre);
 784  0
                 getInvoker().reset();
 785  0
                 ThreadLocalRollingWriterFactory.setRollingWriterFactory(null);
 786  0
             }
 787  0
         }
 788  
 
 789  
         public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
 790  307
             ServletRequestEvent sre = new ServletRequestEvent(WebslingerServletContext.this, request);
 791  307
             ThreadLocalRollingWriterFactory.setRollingWriterFactory(container.getLogFactory());
 792  
             try {
 793  307
                 request.setAttribute("RequestPath", pc);
 794  307
                 requestEventsListener.requestInitialized(sre);
 795  307
                 notifyEventChain(servletListenerCache, SERVLET_REQUEST_LISTENER_CONTEXT_INITIALIZED, pc.getFile().getName(), sre);
 796  307
                 chain.doFilter(request, response);
 797  0
             } catch (RuntimeException e) {
 798  0
                 throw e;
 799  
             } finally {
 800  307
                 notifyEventChain(servletListenerCache, SERVLET_REQUEST_LISTENER_CONTEXT_DESTROYED, pc.getFile().getName(), sre);
 801  307
                 requestEventsListener.requestDestroyed(sre);
 802  307
                 getInvoker().reset();
 803  307
                 ThreadLocalRollingWriterFactory.setRollingWriterFactory(null);
 804  307
             }
 805  307
         }
 806  
     }
 807  
 
 808  
     protected interface EventListenerCaller {
 809  
         void notifyListener(EventListener listener, EventObject event);
 810  
     }
 811  
 
 812  
     public interface EventListenerFactory {
 813  
         EventListener getListener(PathContext pc) throws IOException;
 814  
         void destroy(EventListener listener);
 815  
     }
 816  
 
 817  0
     protected class EventListenerList extends FileObjectAttributeSplitTTLObject<EventListener[]> {
 818  
         protected final EventListenerFactory factory;
 819  
 
 820  248
         protected EventListenerList(EventListenerFactory factory, FileObject file, String attributeName) {
 821  248
             super(file, attributeName, EventListener[].class);
 822  248
             this.factory = factory;
 823  248
         }
 824  
 
 825  
         protected EventListener[] parseAttribute(String attributeValue) throws IOException {
 826  0
             String[] listenerNames = splitAttribute(attributeValue);
 827  0
             if (listenerNames == null) return null;
 828  0
             EventListener[] listeners = new EventListener[listenerNames.length];
 829  0
             for (int i = 0; i < listenerNames.length; i++) {
 830  0
                 listeners[i] = factory.getListener(parse(file, listenerNames[i]));
 831  
             }
 832  0
             return listeners;
 833  
         }
 834  
     }
 835  
 
 836  26
     protected final EventListenerFactory SERVLET_CONTEXT_LISTENER_FACTORY = new EventListenerFactory() {
 837  26
         protected final HashMap<String, EventListener> listenerCache = new HashMap<String, EventListener>();
 838  
 
 839  
         public EventListener getListener(PathContext pc) throws IOException {
 840  0
             EventListener listener = listenerCache.get(pc.getFile().getName().getPath());
 841  0
             if (listener == null) {
 842  0
                 listener = new WebslingerServletContextListener(pc);
 843  0
                 listenerCache.put(pc.getFile().getName().getPath(), listener);
 844  
             }
 845  0
             return listener;
 846  
         }
 847  
 
 848  
         public void destroy(EventListener listener) {
 849  0
         }
 850  
     };
 851  
 
 852  1
     protected static final EventListenerCaller SERVLET_CONTEXT_LISTENER_CONTEXT_DESTROYED = new EventListenerCaller() {
 853  
         public void notifyListener(EventListener listener, EventObject event) {
 854  0
             ((ServletContextListener) listener).contextDestroyed((ServletContextEvent) event);
 855  0
         }
 856  
     };
 857  
 
 858  1
     protected static final EventListenerCaller SERVLET_CONTEXT_LISTENER_CONTEXT_INITIALIZED = new EventListenerCaller() {
 859  
         public void notifyListener(EventListener listener, EventObject event) {
 860  0
             ((ServletContextListener) listener).contextInitialized((ServletContextEvent) event);
 861  0
         }
 862  
     };
 863  
 
 864  
     protected final class WebslingerServletContextListener implements ServletContextListener {
 865  
         private final PathContext pc;
 866  
 
 867  0
         protected WebslingerServletContextListener(PathContext pc) {
 868  0
             this.pc = pc;
 869  0
         }
 870  
 
 871  
         public void contextDestroyed(ServletContextEvent event) {
 872  0
             runEvent("destroyed", event);
 873  0
         }
 874  
 
 875  
         protected final void runEvent(String name, ServletContextEvent event) {
 876  0
             runDirectNoThrow("ServletContextListener." + name, pc, null, "context-listener-" + name, event);
 877  0
         }
 878  
 
 879  
         public void contextInitialized(ServletContextEvent event) {
 880  0
             runEvent("initialized", event);
 881  0
         }
 882  
     }
 883  
 
 884  26
     protected final class ServletRequestListenerFactory implements EventListenerFactory {
 885  26
         protected final HashMap<String, EventListener> listenerCache = new HashMap<String, EventListener>();
 886  
 
 887  
         public EventListener getListener(PathContext pc) throws IOException {
 888  0
             EventListener listener = listenerCache.get(pc.getFile().getName().getPath());
 889  0
             if (listener == null) {
 890  0
                 listener = new WebslingerServletRequestListener(pc);
 891  0
                 listenerCache.put(pc.getFile().getName().getPath(), listener);
 892  
             }
 893  0
             return listener;
 894  
         }
 895  
 
 896  
         public void destroy(EventListener listener) {
 897  0
         }
 898  
     }
 899  
 
 900  1
     protected static final EventListenerCaller SERVLET_REQUEST_LISTENER_CONTEXT_DESTROYED = new EventListenerCaller() {
 901  
         public void notifyListener(EventListener listener, EventObject event) {
 902  0
             ((ServletRequestListener) listener).requestDestroyed((ServletRequestEvent) event);
 903  0
         }
 904  
     };
 905  
 
 906  1
     protected static final EventListenerCaller SERVLET_REQUEST_LISTENER_CONTEXT_INITIALIZED = new EventListenerCaller() {
 907  
         public void notifyListener(EventListener listener, EventObject event) {
 908  0
             ((ServletRequestListener) listener).requestInitialized((ServletRequestEvent) event);
 909  0
         }
 910  
     };
 911  
 
 912  
     protected final class WebslingerServletRequestListener implements ServletRequestListener {
 913  
         private final PathContext pc;
 914  
 
 915  0
         protected WebslingerServletRequestListener(PathContext pc) {
 916  0
             this.pc = pc;
 917  0
         }
 918  
 
 919  
         public void requestDestroyed(ServletRequestEvent event) {
 920  0
             runEvent("destroyed", event);
 921  0
         }
 922  
 
 923  
         protected final void runEvent(String name, ServletRequestEvent event) {
 924  0
             runDirectNoThrow("ServletContextListener." + name, pc, null, "request-listener-" + name, event);
 925  0
         }
 926  
 
 927  
         public void requestInitialized(ServletRequestEvent event) {
 928  0
             runEvent("initialized", event);
 929  0
         }
 930  
     }
 931  
 
 932  
     protected void notifyEventChain(ConcurrentCache<FileName, EventListenerList> listenerCache, EventListenerCaller caller, FileName name, EventObject event) throws IOException {
 933  1784
         FileName parent = name.getParent();
 934  1784
         if (parent != null) notifyEventChain(listenerCache, caller, parent, event);
 935  
         EventListenerList listenerList;
 936  
         try {
 937  1784
             listenerList = listenerCache.get(name);
 938  0
         } catch (RuntimeException e) {
 939  0
             throw e;
 940  0
         } catch (IOException e) {
 941  0
             throw e;
 942  0
         } catch (Exception e) {
 943  0
             throw (InternalError) new InternalError(e.getMessage()).initCause(e);
 944  1784
         }
 945  1784
         EventListener[] listeners = listenerList.getObject();
 946  1784
         if (listeners == null) return;
 947  0
         for (EventListener listener: listeners) {
 948  0
             caller.notifyListener(listener, event);
 949  
         }
 950  0
     }
 951  
 
 952  26
     protected final class RequestEventsRequestListener extends TTLObject<PathContext[]> implements ServletRequestListener {
 953  
         private final FileObject initEventsDir;
 954  
 
 955  26
         protected RequestEventsRequestListener() throws IOException {
 956  26
             initEventsDir = getFile("/WEB-INF/Events/System/Request");
 957  26
         }
 958  
 
 959  
         protected PathContext[] load(PathContext[] old) throws IOException {
 960  26
             VFSUtil.refresh(initEventsDir);
 961  26
             if (!initEventsDir.exists()) return null;
 962  19
             FileObject[] children = initEventsDir.getChildren();
 963  19
             ArrayList<PathContext> pcs = new ArrayList<PathContext>(children.length);
 964  38
             for (FileObject child: children) {
 965  19
                 if (child.isHidden()) continue;
 966  19
                 if (child.getName().getBaseName().startsWith(".")) continue;
 967  19
                 pcs.add(resolve(child.getName().getPath()));
 968  
             }
 969  19
             return pcs.toArray(new PathContext[pcs.size()]);
 970  
         }
 971  
 
 972  
         public void requestDestroyed(ServletRequestEvent event) {
 973  307
             runEvent("destroyed", event);
 974  307
         }
 975  
 
 976  
         protected final void runEvent(String name, ServletRequestEvent event) {
 977  
             try {
 978  614
                 PathContext[] pcs = (PathContext[]) getObject();
 979  614
                 if (pcs == null) return;
 980  920
                 for (PathContext pc: pcs) {
 981  460
                     HttpServletResponse response = new FakeHttpServletResponse(new FakeServletResponse(new StringWriter()));
 982  460
                     runDirectNoThrow("ServletContextListener." + name, pc, null, "request-listener-" + name, event);
 983  
                 }
 984  0
             } catch (IOException e) {
 985  0
                 log("ServletContextListener." + name, e);
 986  460
             }
 987  460
         }
 988  
 
 989  
         public void requestInitialized(ServletRequestEvent event) {
 990  307
             runEvent("initialized", event);
 991  307
         }
 992  
     }
 993  
 
 994  
     // /--------------------\
 995  
     // | ServletContext api |
 996  
     // \--------------------/
 997  
 
 998  
     public ServletContext getContext(String path) {
 999  0
         return null;
 1000  
     }
 1001  
 
 1002  
     public int getMajorVersion() {
 1003  0
         return 2;
 1004  
     }
 1005  
 
 1006  
     public int getMinorVersion() {
 1007  0
         return 4;
 1008  
     }
 1009  
 
 1010  
     public String getMimeType(String path) {
 1011  
         try {
 1012  0
             return getFile(path).getContent().getContentInfo().getContentType();
 1013  0
         } catch (Exception e) {
 1014  0
             log("getMimeType(" + path + ")", e);
 1015  0
             return null;
 1016  
         }
 1017  
     }
 1018  
 
 1019  
     public Set getResourcePaths(String path) {
 1020  0
         HashSet<String> paths = new HashSet<String>();
 1021  
         try {
 1022  0
             FileObject[] children = getFile(path).getChildren();
 1023  0
             for (FileObject child: children) {
 1024  0
                 if (child.getType().hasChildren()) {
 1025  0
                     paths.add(child.getName().getPath() + '/');
 1026  
                 } else {
 1027  0
                     paths.add(child.getName().getPath());
 1028  
                 }
 1029  
             }
 1030  0
         } catch (Exception e) {
 1031  0
             log("getResourcePaths(" + path + ")", e);
 1032  0
         }
 1033  0
         return paths;
 1034  
     }
 1035  
 
 1036  
     public URL getResource(String url) throws MalformedURLException {
 1037  
         try {
 1038  6
             FileObject file = getWWW().resolveFile(url);
 1039  6
             while (file != null) {
 1040  6
                 if (file instanceof DelegateFileObject) {
 1041  0
                     file = ((DelegateFileObject) file).getDelegateFile();
 1042  6
                 } else if (file instanceof FlatFileObject) {
 1043  0
                     file = ((FlatFileObject) file).getRealFile();
 1044  
                 } else {
 1045  
                     break;
 1046  
                 }
 1047  
             }
 1048  6
             if (file == null) return null;
 1049  6
             return file.getURL();
 1050  0
         } catch (FileSystemException e) {
 1051  0
             throw (MalformedURLException) new MalformedURLException(e.getMessage()).initCause(e);
 1052  
         }
 1053  
 
 1054  
     }
 1055  
 
 1056  
     public InputStream getResourceAsStream(String path) {
 1057  
         try {
 1058  0
             FileObject file = getFile(path);
 1059  0
             if (file.exists()) return file.getContent().getInputStream();
 1060  0
         } catch (Exception e) {
 1061  0
             log("getResourceAsStream(" + path + ")", e);
 1062  0
         }
 1063  0
         return null;
 1064  
     }
 1065  
 
 1066  
     public WebslingerRequestDispatcher getRequestDispatcher(FakeResource resource) {
 1067  0
         return getRequestDispatcher((PathContext) resource);
 1068  
     }
 1069  
 
 1070  
     public WebslingerRequestDispatcher getRequestDispatcher(PathContext pc) {
 1071  0
         return getRequestDispatcher(pc, new HashMap<String, Object>());
 1072  
     }
 1073  
 
 1074  
     public WebslingerRequestDispatcher getRequestDispatcher(PathContext pc, Map<String, Object> context) {
 1075  
         //System.err.println("getRequestDispatcher(" + pc + ")");
 1076  
         try {
 1077  307
             return new WebslingerRequestDispatcher(this, pc, context);
 1078  0
         } catch (Exception e) {
 1079  0
             log("getRequestDispatcher(" + pc + ")", e);
 1080  
         }
 1081  0
         System.err.println("returning null");
 1082  0
         return null;
 1083  
     }
 1084  
 
 1085  
     public WebslingerRequestDispatcher getRequestDispatcher(String path) {
 1086  307
         return getRequestDispatcher(path, new HashMap<String, Object>());
 1087  
     }
 1088  
 
 1089  
     public WebslingerRequestDispatcher getRequestDispatcher(String path, Map<String, Object> context) {
 1090  
         //System.err.println("getRequestDispatcher(" + path + ")");
 1091  
         try {
 1092  307
             return getRequestDispatcher(resolve(path), context);
 1093  0
         } catch (Exception e) {
 1094  0
             log("getRequestDispatcher(" + path + ")", e);
 1095  
         }
 1096  0
         System.err.println("returning null");
 1097  0
         return null;
 1098  
     }
 1099  
 
 1100  
     public WebslingerRequestDispatcher getRequestDispatcher(PathContext pc, String path) {
 1101  0
         return getRequestDispatcher(pc, path, new HashMap<String, Object>());
 1102  
     }
 1103  
 
 1104  
     public WebslingerRequestDispatcher getRequestDispatcher(PathContext pc, String path, Map<String, Object> context) {
 1105  
         //System.err.println("getRequestDispatcher(" + pc + ", " + path + ")");
 1106  
         try {
 1107  0
             return getRequestDispatcher(resolve(pc, path), context);
 1108  0
         } catch (Exception e) {
 1109  0
             log("getRequestDispatcher(" + path + ")", e);
 1110  
         }
 1111  0
         System.err.println("returning null");
 1112  0
         return null;
 1113  
     }
 1114  
 
 1115  
     public RequestDispatcher getNamedDispatcher(String name) {
 1116  3
         return getContainer().getNamedDispatcher(name);
 1117  
     }
 1118  
 
 1119  
     /** @deprecated */
 1120  
     public Servlet getServlet(String name) throws ServletException {
 1121  
         // NOTE: always return null
 1122  0
         return null;
 1123  
     }
 1124  
 
 1125  
     /** @deprecated */
 1126  
     public Enumeration getServlets() {
 1127  
         // FIXME: empty enumeration
 1128  0
         return null;
 1129  
     }
 1130  
 
 1131  
     /** @deprecated */
 1132  
     public Enumeration getServletNames() {
 1133  
         // FIXME: empty enumeration
 1134  0
         return null;
 1135  
     }
 1136  
 
 1137  
     public void log(String msg) {
 1138  24
         getContainer().log(msg);
 1139  24
     }
 1140  
 
 1141  
     /** @deprecated */
 1142  
     public void log(Exception e, String msg) {
 1143  0
         log(msg, e);
 1144  0
     }
 1145  
 
 1146  
     public void log(String msg, Throwable t) {
 1147  0
         getContainer().log(msg, t);
 1148  0
     }
 1149  
 
 1150  
     public String getRealPath(String path) {
 1151  
         try {
 1152  21
             FileObject file = getWWW().resolveFile(path);
 1153  
             while (true) {
 1154  
                 //System.err.println("file=" + file);
 1155  21
                 if (file.getFileSystem().getParentLayer() != null) {
 1156  0
                     file = file.getFileSystem().getParentLayer().resolveFile(file.getName().getPath().substring(1));
 1157  21
                 } else if (file instanceof DelegateFileObject) {
 1158  0
                     file = ((DelegateFileObject) file).getDelegateFile();
 1159  
                 } else {
 1160  
                     break;
 1161  
                 }
 1162  
             }
 1163  21
             if (file instanceof LocalFile) return file.getName().getPath();
 1164  0
         } catch (FileSystemException e) {
 1165  0
             log("getRealPath(" + path + ")", e);
 1166  21
         }
 1167  21
         return null;
 1168  
     }
 1169  
 
 1170  
     public String getServerInfo() {
 1171  0
         return "Webslinger";
 1172  
     }
 1173  
 
 1174  
     public String getInitParameter(String name) {
 1175  0
         return (String) getContainer().getInitParameter(name);
 1176  
     }
 1177  
 
 1178  
     public Enumeration getInitParameterNames() {
 1179  0
         return getContainer().getInitParameterNames();
 1180  
         //return new IteratorEnumeration(initParameters.keySet().iterator());
 1181  
     }
 1182  
 
 1183  
     public Object getAttribute(String name) {
 1184  42
         Object value = attributes.get(name);
 1185  
         //System.err.println("getAttribute(" + name + ")=" + value);
 1186  42
         return value;
 1187  
     }
 1188  
 
 1189  
     public Enumeration getAttributeNames() {
 1190  0
         return new IteratorEnumeration(attributes.keySet().iterator());
 1191  
     }
 1192  
 
 1193  
     public void setAttribute(String name, Object value) {
 1194  
         //System.err.println("setAttribute(" + name + ", " + value + ")");
 1195  0
         attributes.put(name, value);
 1196  0
     }
 1197  
 
 1198  
     public void removeAttribute(String name) {
 1199  0
         attributes.remove(name);
 1200  0
     }
 1201  
 
 1202  
     public String getServletContextName() {
 1203  0
         return null;
 1204  
     }
 1205  
 
 1206  
     // local methods
 1207  
 
 1208  
     public boolean isUserInRole(Principal user, String role) {
 1209  0
         return false;
 1210  
     }
 1211  
 
 1212  
     public HttpServletResponse alterPaths(PathContext pc, HttpServletRequest request, HttpServletResponse response, Writer writer) {
 1213  374
         final PrintWriter printWriter = writer instanceof PrintWriter ? (PrintWriter) writer : new PrintWriter(writer);
 1214  374
         return new WrappedHttpServletResponse(this, request, (HttpServletResponse) response, pc) {
 1215  
             public ServletOutputStream getOutputStream() {
 1216  0
                 throw new IllegalStateException();
 1217  
             }
 1218  
 
 1219  
             public PrintWriter getWriter() {
 1220  393
                 return printWriter;
 1221  
             }
 1222  
         };
 1223  
     }
 1224  
 
 1225  
     public HttpServletResponse alterPaths(PathContext pc, HttpServletRequest request, HttpServletResponse response) {
 1226  283
         return new WrappedHttpServletResponse(this, request, (HttpServletResponse) response, pc);
 1227  
     }
 1228  
 
 1229  
     public HttpServletRequest alterPaths(PathContext pc, HttpServletRequest request) {
 1230  531
         return new WrappedHttpServletRequest(this, (HttpServletRequest) request, pc);
 1231  
     }
 1232  
 
 1233  
     public String getText(PathContext pc) throws IOException, ServletException {
 1234  0
         return getInvoker().getText(pc);
 1235  
     }
 1236  
 
 1237  
     Object runDirectNoThrow(String errorMessage, PathContext pc, Map<String, Object> context, String command, Object payload) {
 1238  
         try {
 1239  460
             return getInvoker().runDirect(pc, context, command, payload);
 1240  0
         } catch (IOException e) {
 1241  0
             log(errorMessage, e);
 1242  0
             return null;
 1243  0
         } catch (ServletException e) {
 1244  0
             log(errorMessage, e);
 1245  0
             return null;
 1246  
         }
 1247  
     }
 1248  
 
 1249  
     Object runDirect(PathContext pc, Map<String, Object> context, String command, Object payload) throws IOException, ServletException {
 1250  1
         return getInvoker().runDirect(pc, context, command, payload);
 1251  
     }
 1252  
 
 1253  
     public Object run(PathContext pc) throws IOException, ServletException {
 1254  0
         return getInvoker().run(pc, null, null, null, new StringWriter());
 1255  
     }
 1256  
 
 1257  
     public Object run(PathContext pc, Writer writer) throws IOException, ServletException {
 1258  0
         return getInvoker().run(pc, null, null, null, writer);
 1259  
     }
 1260  
 
 1261  
     public Object run(PathContext pc, Map<String, Object> context) throws IOException, ServletException {
 1262  0
         return getInvoker().run(pc, null, context, null, null, new StringWriter());
 1263  
     }
 1264  
 
 1265  
     public Object run(PathContext pc, Map<String, Object> context, Writer writer) throws IOException, ServletException {
 1266  0
         return getInvoker().run(pc, null, context, null, null, writer);
 1267  
     }
 1268  
 
 1269  
     public Object run(PathContext pc, Map<String, Object> context, String command, Object payload) throws IOException, ServletException {
 1270  0
         return getInvoker().run(pc, null, context, command, payload, new StringWriter());
 1271  
     }
 1272  
 
 1273  
     public Object run(PathContext pc, Map<String, Object> context, String command, Object payload, Writer writer) throws IOException, ServletException {
 1274  0
         return getInvoker().run(pc, null, context, command, payload, writer);
 1275  
     }
 1276  
 
 1277  
     public Object run(PathContext pc, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 1278  0
         System.err.println("no context run(" + pc + ")");
 1279  0
         return getInvoker().invoke(pc, null, request, response, getInvoker().findContext(), null, null);
 1280  
     }
 1281  
 
 1282  
     public Object run(PathContext pc, HttpServletRequest request, HttpServletResponse response, String command, Object payload) throws IOException, ServletException {
 1283  22
         return getInvoker().invoke(pc, null, request, response, getInvoker().findContext(), command, payload);
 1284  
     }
 1285  
 
 1286  
     public Object run(PathContext pc, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context) throws IOException, ServletException {
 1287  0
         return getInvoker().invoke(pc, null, request, response, context, null, null);
 1288  
     }
 1289  
 
 1290  
     public Object run(PathContext pc, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context, String command, Object payload) throws IOException, ServletException {
 1291  349
         return getInvoker().invoke(pc, null, request, response, context, command, payload);
 1292  
     }
 1293  
 
 1294  
     protected abstract static class TriggerListCache extends FileObjectAttributeSplitTTLObject<PathContext[]> {
 1295  
         public TriggerListCache(FileObject file, String attributeName) {
 1296  0
             super(file, attributeName, PathContext[].class);
 1297  0
         }
 1298  
     }
 1299  
 
 1300  
     TTLObject<Object> getInitObject(PathContext pc, TypeHandler handler) throws IOException, ServletException {
 1301  1594
         boolean hasInit = handler.hasInit(pc);
 1302  1596
         FileObject file = pc.getFile();
 1303  1591
         if (file == null) return null;
 1304  1596
         String path = file.getName().getPath();
 1305  1594
         TTLObject<Object> datum = initMap.get(path);
 1306  1596
         if (datum == null) {
 1307  1153
             if (!hasInit) return null;
 1308  19
             TTLObject<Object> newDatum = new InitTTLCachedObject(pc);
 1309  19
             datum = initMap.putIfAbsent(path, newDatum);
 1310  19
             return datum == null ? newDatum : datum;
 1311  
         } else {
 1312  441
             if (hasInit) return datum;
 1313  0
             initMap.remove(path, datum);
 1314  0
             return null;
 1315  
         }
 1316  
     }
 1317  
 
 1318  26
     protected final TypeHandler MISSING_HANDLER = new TypeHandler() {
 1319  
         public Object run(Webslinger webslinger) throws IOException, ServletException {
 1320  33
             PathContext pc = resolve("/Errors/Codes/404");
 1321  33
             HttpServletResponse response = webslinger.getResponse();
 1322  33
             if (pc.exists()) {
 1323  22
                 if (!response.isCommitted()) response.setStatus(404);
 1324  22
                 WebslingerServletContext.this.run(pc, webslinger.getRequest(), webslinger.getResponse(), null, webslinger);
 1325  
             } else {
 1326  11
                 if (!response.isCommitted()) response.sendError(404);
 1327  
             }
 1328  33
             return null;
 1329  
         }
 1330  
 
 1331  
         public String toString() {
 1332  0
             return "MISSING_HANDLER";
 1333  
         }
 1334  
     };
 1335  
 
 1336  
     TypeHandler getTypeHandler(PathContext pc) throws IOException {
 1337  
         try {
 1338  1597
             FileObject file = pc.getFile();
 1339  1597
             if (file != null && !file.exists()) return MISSING_HANDLER;
 1340  0
         } catch (IOException e) {
 1341  0
             throw new WebslingerException("checking for file existance", e);
 1342  1564
         }
 1343  
         String type;
 1344  
         try {
 1345  1565
             type = pc.getType();
 1346  0
         } catch (IOException e) {
 1347  0
             throw new WebslingerException("getting type", e);
 1348  1562
         }
 1349  1565
         if (type == null) type = DEFAULT_TYPE;
 1350  1563
         return getTypeHandler(type);
 1351  
     }
 1352  
 
 1353  
     private TypeHandler createTypeHandler(String type) throws IOException {
 1354  
         try {
 1355  
             try {
 1356  70
                 return (TypeHandler) Class.forName("org.webslinger.types." + type, true, getClass().getClassLoader()).newInstance();
 1357  16
             } catch (ClassNotFoundException e) {
 1358  
                 try {
 1359  16
                     return (TypeHandler) Class.forName("org.webslinger.ext.types." + type, true, getClass().getClassLoader()).newInstance();
 1360  12
                 } catch (ClassNotFoundException e2) {
 1361  12
                     final PathContext localHandler = resolve("/WEB-INF/TypeHandlers/" + type);
 1362  12
                     if (!localHandler.getFile().exists()) throw new WebslingerException("creating type handler", e);
 1363  12
                     return new TypeHandler() {
 1364  
                         public Object run(Webslinger webslinger) throws IOException, ServletException {
 1365  83
                             return webslinger.getInvoker().runDirect(localHandler, webslinger.getRequest(), webslinger.getResponse(), null, null, webslinger);
 1366  
                         }
 1367  
                     };
 1368  
                 }
 1369  
             }
 1370  0
         } catch (IllegalAccessException e) {
 1371  0
             throw new WebslingerException("creating type handler", e);
 1372  0
         } catch (InstantiationException e) {
 1373  0
             throw new WebslingerException("creating type handler", e);
 1374  
         }
 1375  
     }
 1376  
 
 1377  
     public TypeHandler getTypeHandler(String type) throws IOException {
 1378  1589
         TypeHandler handler = typeHandlers.get(type);
 1379  1588
         if (handler != null) return handler;
 1380  
         do {
 1381  70
             TypeHandler newHandler = createTypeHandler(type);
 1382  
             try {
 1383  70
                 newHandler.init(this, type);
 1384  0
             } catch (IOException e) {
 1385  0
                 throw new WebslingerException("initializing type handler", e);
 1386  70
             }
 1387  70
             typeHandlers.putIfAbsent(type, newHandler);
 1388  70
             handler = typeHandlers.get(type);
 1389  70
         } while (handler == null);
 1390  70
         return handler;
 1391  
     }
 1392  
 
 1393  
     public boolean isFilter(FileObject file) throws IOException {
 1394  0
         return getContainer().isFilter(file);
 1395  
     }
 1396  
 
 1397  
     public FakeResource resolveResource(String path) throws IOException {
 1398  0
         return resolve(path);
 1399  
     }
 1400  
 
 1401  
     public FakeResource resolveResource(FakeResource resource, String path) throws IOException {
 1402  0
         return resolve((PathContext) resource, path);
 1403  
     }
 1404  
 
 1405  
     public PathContext resolve(FileObject file) throws IOException {
 1406  3
         return new PathContext(new CommonsVfsFileInfo(getContainer(), file), new GivenPathInfo(""));
 1407  
     }
 1408  
 
 1409  
     public PathContext resolve(String path) throws IOException {
 1410  824
         return getContainer().resolve(path);
 1411  
     }
 1412  
 
 1413  
     public PathContext resolve(String path, boolean lookForFilter) throws IOException {
 1414  0
         return getContainer().resolve(path, lookForFilter);
 1415  
     }
 1416  
 
 1417  
     public PathContext resolve(PathContext context, String path) throws IOException {
 1418  935
         return getContainer().resolve(context, context, path, true);
 1419  
     }
 1420  
 
 1421  
     public PathContext resolve(PathContext context, String path, boolean lookForFilter) throws IOException {
 1422  0
         return getContainer().resolve(context, context, path, lookForFilter);
 1423  
     }
 1424  
 
 1425  
     public PathContext parse(FileObject ptr, String path) throws IOException {
 1426  1
         return getContainer().parse(ptr, ptr, path, true);
 1427  
     }
 1428  
 
 1429  
     public void sendError(HttpServletRequest request, HttpServletResponse response, FakeResource resource, int code) throws IOException {
 1430  11
         sendError(request, response, (PathContext) resource, code);
 1431  11
     }
 1432  
 
 1433  
     public void sendError(HttpServletRequest request, HttpServletResponse response, PathContext resource, int code) throws IOException {
 1434  11
         sendError(request, response, resource, code, new HashMap<String, Object>());
 1435  11
     }
 1436  
 
 1437  
     public void sendError(HttpServletRequest request, HttpServletResponse response, FakeResource resource, int code, String msg) throws IOException {
 1438  0
         sendError(request, response, (PathContext) resource, code, msg);
 1439  0
     }
 1440  
 
 1441  
     public void sendError(HttpServletRequest request, HttpServletResponse response, PathContext resource, int code, String msg) throws IOException {
 1442  0
         HashMap<String, Object> context = new HashMap<String, Object>();
 1443  0
         context.put("message", msg);
 1444  0
         sendError(request, response, resource, code, context);
 1445  0
     }
 1446  
 
 1447  
     protected void sendError(HttpServletRequest request, HttpServletResponse response, PathContext resource, int code, Map<String, Object> context) throws WebslingerException {
 1448  
         PathContext pc;
 1449  
         try {
 1450  11
             pc = resolve("/Errors/Codes/" + code);
 1451  0
         } catch (IOException e) {
 1452  0
             throw new WebslingerException("ERROR: looking up error handler", e);
 1453  11
         }
 1454  
         boolean exists;
 1455  
         try {
 1456  11
             exists = pc.getFile().exists();
 1457  0
         } catch (IOException e) {
 1458  0
             throw new WebslingerException("ERROR: checking existance", e);
 1459  11
         }
 1460  11
         if (!exists) {
 1461  
             try {
 1462  11
                 response.sendError(code);
 1463  11
                 return;
 1464  0
             } catch (IOException e) {
 1465  0
                 throw new WebslingerException("ERROR: sending error(fallback)", e);
 1466  
             }
 1467  
         }
 1468  0
         response.setStatus(code);
 1469  
         try {
 1470  0
             run(pc, request, response, context, null, resource);
 1471  0
         } catch (IOException e) {
 1472  0
             throw new WebslingerException("ERROR: sending error", e);
 1473  0
         } catch (ServletException e) {
 1474  0
             throw new WebslingerException("ERROR: sending error", e);
 1475  0
         }
 1476  0
     }
 1477  
 
 1478  
     protected class InitTTLCachedObject extends TTLCachedObject<Object> {
 1479  
         protected final PathContext initPc;
 1480  
 
 1481  19
         protected InitTTLCachedObject(PathContext pc) {
 1482  19
             initPc = new PathContext(pc.getInfo(), new GivenPathInfo(""));
 1483  19
         }
 1484  
 
 1485  
         protected FileObject getFile() throws IOException {
 1486  0
             return initPc.getFile();
 1487  
         }
 1488  
 
 1489  
         protected long getTimestamp(Object old) throws IOException {
 1490  0
             FileObject file = getFile();
 1491  0
             if (!file.exists()) return NOT_EXISTANT_TIMESTAMP;
 1492  0
             return getFile().getContent().getLastModifiedTime();
 1493  
         }
 1494  
 
 1495  
         protected GeneratedResult<Object> generate(Object old) throws IOException {
 1496  
             FileObject file;
 1497  
             try {
 1498  0
                 file = getFile();
 1499  0
             } catch (IOException e) {
 1500  0
                 throw new WebslingerException("INIT: getting file", e);
 1501  0
             }
 1502  0
             HttpServletResponse response = new FakeHttpServletResponse(new FakeServletResponse(new StringWriter()));
 1503  0
             HttpServletRequest request = new FakeHttpServletRequest(WebslingerServletContext.this, new FakeServletRequest(WebslingerServletContext.this, initPc), response, initPc);
 1504  
             Webslinger webslinger;
 1505  
             try {
 1506  0
                 webslinger = new Webslinger(null, WebslingerServletContext.this, getInvoker(), initPc, request, response, null, "init", null, null);
 1507  0
             } catch (ServletException e) {
 1508  0
                 throw new WebslingerException("INIT: creating Webslinger object", e);
 1509  0
             }
 1510  
             TypeHandler handler;
 1511  
             try {
 1512  0
                 handler = getTypeHandler(initPc);
 1513  0
             } catch (IOException e) {
 1514  0
                 throw new WebslingerException("INIT: getting TypeHandler", e);
 1515  0
             }
 1516  
             Object initObject;
 1517  
             try {
 1518  0
                 initObject = handler.run(webslinger);
 1519  0
             } catch (IOException e) {
 1520  0
                 throw new WebslingerException("INIT: getting initObject", e);
 1521  0
             } catch (ServletException e) {
 1522  0
                 throw new WebslingerException("INIT: getting initObject", e);
 1523  0
             }
 1524  
             long timestamp;
 1525  
             try {
 1526  0
                 timestamp = file.getContent().getLastModifiedTime();
 1527  0
             } catch (IOException e) {
 1528  0
                 throw new WebslingerException("INIT: getting timestamp", e);
 1529  0
             }
 1530  0
             return new GeneratedResult<Object>(timestamp, initObject);
 1531  
         }
 1532  
     }
 1533  
 }