Coverage Report - org.webslinger.container.WebslingerContainer
 
Classes in this File Line Coverage Branch Coverage Complexity
WebslingerContainer
64%
152/239
77%
36/47
0
WebslingerContainer$1
100%
2/2
N/A
0
WebslingerContainer$2
100%
2/2
N/A
0
WebslingerContainer$3
50%
1/2
N/A
0
WebslingerContainer$4
100%
3/3
N/A
0
WebslingerContainer$5
100%
2/2
N/A
0
WebslingerContainer$ConfigTTLObject
100%
6/6
N/A
0
WebslingerContainer$ExtensionListTTLObject
100%
2/2
N/A
0
WebslingerContainer$LogWriterFactory
57%
4/7
0%
0/1
0
WebslingerContainer$PathParsingTTLObject
100%
6/6
N/A
0
 
 1  
 package org.webslinger.container;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.IOException;
 5  
 import java.io.PrintStream;
 6  
 import java.lang.ref.Reference;
 7  
 import java.util.ArrayList;
 8  
 import java.util.Collection;
 9  
 import java.util.Enumeration;
 10  
 import java.util.HashMap;
 11  
 import java.util.Iterator;
 12  
 import java.util.Map;
 13  
 import java.util.logging.Level;
 14  
 import java.util.logging.Logger;
 15  
 import javax.servlet.Filter;
 16  
 import javax.servlet.RequestDispatcher;
 17  
 import javax.servlet.Servlet;
 18  
 import javax.servlet.ServletException;
 19  
 import javax.servlet.http.HttpServletRequest;
 20  
 import javax.xml.parsers.DocumentBuilder;
 21  
 import javax.xml.parsers.DocumentBuilderFactory;
 22  
 import javax.xml.parsers.ParserConfigurationException;
 23  
 
 24  
 import org.w3c.dom.Document;
 25  
 import org.w3c.dom.Element;
 26  
 import org.xml.sax.SAXException;
 27  
 
 28  
 import org.apache.commons.vfs.FileContent;
 29  
 import org.apache.commons.vfs.FileObject;
 30  
 import org.apache.commons.vfs.FileSystemManager;
 31  
 
 32  
 import org.webslinger.PathContext;
 33  
 import org.webslinger.Root;
 34  
 import org.webslinger.Webslinger;
 35  
 import org.webslinger.WebslingerClassLoader;
 36  
 import org.webslinger.WebslingerFilter;
 37  
 import org.webslinger.WebslingerFilterServlet;
 38  
 import org.webslinger.WebslingerServletContext;
 39  
 import org.webslinger.WebslingerServletContextFactory;
 40  
 import org.apache.commons.collections.iterators.IteratorEnumeration;
 41  
 import org.webslinger.commons.vfs.CommonsVfsRollingWriter;
 42  
 import org.webslinger.commons.vfs.VFSUtil;
 43  
 import org.webslinger.commons.vfs.cow.COWEntry;
 44  
 import org.webslinger.commons.vfs.cow.COWFileSystem;
 45  
 import org.webslinger.commons.vfs.virtual.VirtualFileSystem;
 46  
 import org.webslinger.io.GenericRollingWriterFactory;
 47  
 import org.webslinger.io.IOUtil;
 48  
 import org.webslinger.io.RollingWriter;
 49  
 import org.webslinger.io.RollingWriterFactory;
 50  
 import org.webslinger.lang.ConcurrentCache;
 51  
 import org.webslinger.lang.ConcurrentFreezingCache;
 52  
 import org.webslinger.lang.Freezer;
 53  
 import org.webslinger.lang.ObjectWrapper;
 54  
 import org.webslinger.modules.ModuleState;
 55  
 import org.webslinger.rules.CompiledRules;
 56  
 import org.webslinger.rules.CSSRulesTTLCachedObject;
 57  
 import org.webslinger.servlet.webxml.ConfiguredFilter;
 58  
 import org.webslinger.servlet.webxml.ConfiguredServlet;
 59  
 import org.webslinger.servlet.webxml.FilterMapping;
 60  
 import org.webslinger.servlet.webxml.WebXml;
 61  
 import org.webslinger.util.MimeTypeLookup;
 62  
 import org.webslinger.util.TTLObject;
 63  
 import org.webslinger.xml.XmlUtil;
 64  
 
 65  860
 public class WebslingerContainer implements Root {
 66  1
     private static final Logger logger = Logger.getLogger(WebslingerContainer.class.getName());
 67  
     public static final String DEFAULT_MIME_TYPE = "application/x-webslinger-default";
 68  
     static {
 69  1
         TTLObject.setDefaultTTLForClass(PathParsingTTLObject.class, 1000);
 70  1
         TTLObject.setDefaultTTLForClass(ConfigTTLObject.class, 1000);
 71  1
         TTLObject.setDefaultTTLForClass(ExtensionListTTLObject.class, 1000);
 72  
     }
 73  
 
 74  
     protected final WebslingerServletContextFactory factory;
 75  831
     protected final ConcurrentFreezingCache<FileObject, String, FileInfo> fileInfoCache = new ConcurrentFreezingCache<FileObject, String, FileInfo>(WebslingerContainer.class, "fileInfoCache", null, ConcurrentCache.SOFT, FileFreezer) {
 76  
         protected FileInfo createValue(Object id, String path) {
 77  805
             return new CommonsVfsFileInfo(WebslingerContainer.this, (FileObject) id);
 78  
         }
 79  
     };
 80  727
     protected final ConcurrentCache<String, PathParsingTTLObject> lookForFilterCache = new ConcurrentCache<String, PathParsingTTLObject>(WebslingerContainer.class, "lookForFilterCache", null, ConcurrentCache.SOFT) {
 81  
         protected PathParsingTTLObject createValue(String key) {
 82  701
             return new PathParsingTTLObject(key, true);
 83  
         }
 84  
     };
 85  26
     protected final ConcurrentCache<String, PathParsingTTLObject> fullPathCache = new ConcurrentCache<String, PathParsingTTLObject>(WebslingerContainer.class, "fullPathCache", null, ConcurrentCache.SOFT) {
 86  
         protected PathParsingTTLObject createValue(String key) {
 87  0
             return new PathParsingTTLObject(key, false);
 88  
         }
 89  
     };
 90  
     protected final WebslingerClassLoader wcl;
 91  
     protected final FileObject root;
 92  
     protected final FileObject www;
 93  
     protected final ConfigTTLObject config;
 94  
     protected final TTLObject<String[]> extensionList;
 95  26
     protected final HashMap<String, ServletRequestDispatcher> webXmlServlets = new HashMap<String, ServletRequestDispatcher>();
 96  26
     protected final HashMap<String, WebslingerFilter> webXmlFilters = new HashMap<String, WebslingerFilter>();
 97  
     protected final WebXml webXml;
 98  
     protected final CSSRulesTTLCachedObject rules;
 99  
     protected final RollingWriterFactory logFactory;
 100  
     protected WebslingerServletContext context;
 101  
 
 102  26
     public WebslingerContainer(WebslingerServletContextFactory factory, FileObject root, WebXml webXml) throws IOException {
 103  26
         wcl = new WebslingerClassLoader(getClass().getClassLoader(), root);
 104  26
         this.factory = factory;
 105  26
         FileSystemManager fsm = root.getFileSystem().getFileSystemManager();
 106  26
         this.root = root;
 107  26
         FileObject www = root.resolveFile("www");
 108  26
         www.createFolder();
 109  26
         this.www = fsm.createFileSystem("wsvfs", www);
 110  26
         config = new ConfigTTLObject(this.www.resolveFile("/WEB-INF/Config"));
 111  26
         this.webXml = webXml;
 112  26
         String extensionList = webXml.getParameters().get("webslingerExtensionList");
 113  26
         if (extensionList != null) {
 114  2
             final String[] extensionListSplit = extensionList != null ? extensionList.split("[, \r\n]") : new String[0];
 115  4
             this.extensionList = new TTLObject<String[]>() {
 116  
                 public long getTTL() {
 117  2
                     return 600000;
 118  
                 }
 119  
 
 120  
                 protected String[] load(String[] old) {
 121  2
                     return extensionListSplit;
 122  
                 }
 123  
             };
 124  2
         } else {
 125  24
             this.extensionList = new ExtensionListTTLObject();
 126  
         }
 127  26
         rules = new CSSRulesTTLCachedObject(WebslingerContainer.this, WebslingerContainer.this.www.resolveFile("/WEB-INF/rules.css"));
 128  26
         logFactory = new LogWriterFactory("'.'yyyy-MM-dd");
 129  26
     }
 130  
 
 131  
     public WebslingerClassLoader getClassLoader() {
 132  103
         return wcl;
 133  
     }
 134  
 
 135  
     public WebslingerServletContext getWebslingerServletContext() {
 136  281
         return context;
 137  
     }
 138  
 
 139  
     public WebslingerServletContextFactory getFactory() {
 140  526
         return factory;
 141  
     }
 142  
 
 143  
     public void initializeRequest(WebslingerServletContext context, HttpServletRequest request) {
 144  526
         getFactory().initializeRequest(context, request);
 145  526
     }
 146  
 
 147  
     public String[] getConfigStringSplit(String name) throws IOException {
 148  111
         String value = getConfigString(name);
 149  111
         if (value == null) return new String[0];
 150  107
         return value.split("[, ]");
 151  
     }
 152  
 
 153  
     public String getConfigString(String name) throws IOException {
 154  146
         Object value = getConfigItem(name);
 155  146
         if (value instanceof String) return (String) value;
 156  4
         if (value == null) return null;
 157  0
         return value.toString();
 158  
     }
 159  
 
 160  
     public Object getConfigItem(String name) throws IOException {
 161  768
         FileObject config = this.config.getObject();
 162  768
         return config.exists() ? config.getContent().getAttribute(name) : null;
 163  
     }
 164  
 
 165  
     public RollingWriterFactory getLogFactory() {
 166  307
         return logFactory;
 167  
     }
 168  
 
 169  
     public WebXml getWebXml() {
 170  0
         return webXml;
 171  
     }
 172  
 
 173  
     public CompiledRules getRules() throws IOException {
 174  
         try {
 175  308
             return (CompiledRules) rules.getObject();
 176  0
         } catch (Exception e) {
 177  0
             return IOUtil.checkException(e);
 178  
         }
 179  
     }
 180  
 
 181  
     public String getDefaultMimeType() {
 182  92
         return DEFAULT_MIME_TYPE;
 183  
     }
 184  
 
 185  
     public Object start() {
 186  333
         return null;
 187  
     }
 188  
 
 189  
     public void finish(Object data) {
 190  333
     }
 191  
 
 192  
     public void init(WebslingerServletContext context) throws IOException, ServletException {
 193  26
         this.context = context;
 194  26
         ClassLoader loader = getClassLoader();
 195  26
         webXml.init(loader);
 196  47
         for (ConfiguredServlet configuredServlet: webXml.getServlets()) {
 197  
             try {
 198  21
                 Class servletClass = Class.forName(configuredServlet.getClassName(), true, loader);
 199  21
                 Servlet servlet = (Servlet) servletClass.newInstance();
 200  21
                 javax.servlet.ServletConfig servletConfig = new ServletConfigImpl(context, configuredServlet.getParameters(), configuredServlet.getName());
 201  21
                 servlet.init(servletConfig);
 202  21
                 webXmlServlets.put(configuredServlet.getName(), new ServletRequestDispatcher(servlet));
 203  0
             } catch (ServletException e) {
 204  0
                 throw e;
 205  0
             } catch (Error e) {
 206  0
                 log("Couldn't load servlet " + configuredServlet.getName(), e);
 207  0
             } catch (RuntimeException e) {
 208  0
                 log("Couldn't load servlet " + configuredServlet.getName(), e);
 209  0
             } catch (Exception e) {
 210  0
                 throw new ServletException(e.getMessage(), e);
 211  21
             }
 212  
         }
 213  
 
 214  26
         for (ConfiguredFilter configuredFilter: webXml.getFilters()) {
 215  
             try {
 216  0
                 Class filterClass = Class.forName(configuredFilter.getClassName(), true, loader);
 217  0
                 Filter filter = (Filter) filterClass.newInstance();
 218  0
                 javax.servlet.FilterConfig filterConfig = new FilterConfigImpl(context, configuredFilter.getParameters(), configuredFilter.getName());
 219  0
                 if (!(filter instanceof WebslingerFilter)) {
 220  0
                     filter = new WebslingerFilterServlet(filter);
 221  
                 }
 222  0
                 filter.init(filterConfig);
 223  0
                 webXmlFilters.put(configuredFilter.getName(), (WebslingerFilter) filter);
 224  0
             } catch (ServletException e) {
 225  0
                 throw e;
 226  0
             } catch (Error e) {
 227  0
                 log("Couldn't load filter " + configuredFilter.getName(), e);
 228  0
             } catch (RuntimeException e) {
 229  0
                 log("Couldn't load filter " + configuredFilter.getName(), e);
 230  0
             } catch (Exception e) {
 231  0
                 throw new ServletException(e.getMessage(), e);
 232  0
             }
 233  
         }
 234  
 
 235  26
     }
 236  
 
 237  
     public WebslingerFilter getServletFilter(String name) {
 238  0
         return webXmlFilters.get(name);
 239  
     }
 240  
 
 241  
     public String[] getExtensionList() throws IOException {
 242  
         try {
 243  2590
             return extensionList.getObject();
 244  0
         } catch (Exception e) {
 245  0
             return IOUtil.checkException(e);
 246  
         }
 247  
     }
 248  
 
 249  
     public RequestDispatcher getNamedDispatcher(String name) {
 250  3
         return webXmlServlets.get(name);
 251  
     }
 252  
 
 253  
     public FilterMapping[] getFilterMappings() {
 254  1
         return webXml.getFilterMappings();
 255  
     }
 256  
 
 257  
     public FileObject getRoot() {
 258  75
         return root;
 259  
     }
 260  
 
 261  
     public FileObject getWWW() {
 262  2681
         return www;
 263  
     }
 264  
 
 265  
     public FileObject getFile(String path) throws IOException {
 266  0
         return getWWW().resolveFile(path);
 267  
     }
 268  
 
 269  
     public void destroy() {
 270  26
     }
 271  
 
 272  
     public String getInitParameter(String name) {
 273  0
         return webXml.getParameters().get(name);
 274  
     }
 275  
 
 276  
     public Enumeration<String> getInitParameterNames() {
 277  0
         return new IteratorEnumeration(webXml.getParameters().keySet().iterator());
 278  
     }
 279  
 
 280  
     public String getMimeType(String extension) {
 281  785
         return webXml.getMimeType(extension);
 282  
     }
 283  
 
 284  
     public String findExtensionByMimeType(String mimeType) throws IOException {
 285  0
         return webXml.getPrimaryExtension(mimeType);
 286  
     }
 287  
 
 288  
     public Collection<String> findMimeTypes(String attrName, Object value) throws IOException {
 289  0
         ArrayList<String> mimeTypes = new ArrayList<String>();
 290  0
         for (FileObject mimeCategory: getWWW().resolveFile("/WEB-INF/DefaultMimeAttributes").getChildren()) {
 291  0
             for (FileObject mimeFile: mimeCategory.getChildren()) {
 292  0
                 if (value.equals(findMimeAttributeInternal(mimeFile, attrName))) {
 293  0
                     mimeTypes.add(mimeCategory.getName().getBaseName() + '/' + mimeFile.getName().getBaseName());
 294  
                 }
 295  
             }
 296  
         }
 297  0
         return mimeTypes;
 298  
     }
 299  
 
 300  
     public Collection<String> findExtensionsForType(String type) throws IOException {
 301  0
         return findExtensions("type", type);
 302  
     }
 303  
 
 304  
     public Collection<String> findExtensions(String attrName, Object value) throws IOException {
 305  0
         ArrayList<String> extensions = new ArrayList<String>();
 306  0
         Iterator<String> it = findMimeTypes(attrName, value).iterator();
 307  0
         while (it.hasNext()) {
 308  0
             String mimeType = it.next();
 309  0
             String[] mimeExtensions = webXml.getExtensions(mimeType);
 310  0
             if (mimeExtensions != null) {
 311  0
                 for (String ext: mimeExtensions) {
 312  0
                     extensions.add(ext);
 313  
                 }
 314  
             }
 315  0
         }
 316  0
         return extensions;
 317  
     }
 318  
 
 319  
     protected Object findMimeAttributeInternal(FileObject defaultsFile, String attrName) throws IOException {
 320  0
         if (defaultsFile.exists()) {
 321  0
             FileContent content = defaultsFile.getContent();
 322  0
             if (content.attributeExists(attrName)) return content.getAttribute(attrName);
 323  
         }
 324  0
         defaultsFile = defaultsFile.getParent();
 325  0
         if (defaultsFile.exists()) {
 326  0
             FileContent content = defaultsFile.getContent();
 327  0
             if (content.attributeExists(attrName)) return content.getAttribute(attrName);
 328  
         }
 329  0
         return null;
 330  
     }
 331  
 
 332  
     public Object findMimeAttribute(String mimeType, String attrName) throws IOException {
 333  0
         return findMimeAttributeInternal(getWWW().resolveFile("/WEB-INF/DefaultMimeAttributes/" + mimeType), attrName);
 334  
     }
 335  
 
 336  
     public void log(String msg) {
 337  24
         logger.info("WS: " + msg);
 338  24
     }
 339  
 
 340  
     public void log(String msg, Throwable t) {
 341  0
         logger.log(Level.INFO, msg, t);
 342  0
     }
 343  
 
 344  
     public boolean isFilter(FileObject file) throws IOException {
 345  2855
         return file.exists() ? file.getContent().attributeExists("is-filter") : false;
 346  
     }
 347  
 
 348  
     public FileInfo getFileInfo(FileObject file) throws IOException {
 349  
         try {
 350  1394
             return fileInfoCache.get(file);
 351  0
         } catch (RuntimeException e) {
 352  0
             throw e;
 353  0
         } catch (Exception e) {
 354  0
             throw (InternalError) new InternalError(e.getMessage()).initCause(e);
 355  
         }
 356  
     }
 357  
 
 358  1
     protected static final Freezer<FileObject, String> FileFreezer = new Freezer<FileObject, String>() {
 359  
         public String freeze(FileObject file) {
 360  1394
             return file.getName().getPath();
 361  
         }
 362  
     };
 363  
 
 364  
     public PathContext resolve(String path) throws IOException {
 365  824
         return resolve(path, true);
 366  
     }
 367  
 
 368  
     public PathContext resolve(String path, boolean lookForFilter) throws IOException {
 369  1412
         ConcurrentCache<String, PathParsingTTLObject> cache = lookForFilter ? lookForFilterCache : fullPathCache;
 370  
         try {
 371  1412
             return cache.get(path).getObject();
 372  0
         } catch (RuntimeException e) {
 373  0
             throw e;
 374  0
         } catch (Exception e) {
 375  0
             throw (InternalError) new InternalError(e.getMessage()).initCause(e);
 376  
         }
 377  
     }
 378  
 
 379  118
     protected final class ConfigTTLObject extends TTLObject<FileObject> {
 380  
         protected final FileObject config;
 381  
 
 382  26
         protected ConfigTTLObject(FileObject config) {
 383  26
             this.config = config;
 384  26
         }
 385  
 
 386  
         protected FileObject load(FileObject old) throws IOException {
 387  118
             config.refresh();
 388  118
             return config;
 389  
         }
 390  
     }
 391  
 
 392  860
     protected final class PathParsingTTLObject extends TTLObject<PathContext> {
 393  
         protected final boolean lookForFilter;
 394  
         protected final String path;
 395  
 
 396  701
         protected PathParsingTTLObject(String path, boolean lookForFilter) {
 397  701
             this.path = path;
 398  701
             this.lookForFilter = lookForFilter;
 399  701
         }
 400  
 
 401  
 
 402  
         protected PathContext load(PathContext old) throws IOException {
 403  860
             return _parse(getWWW(), getWWW(), path, lookForFilter);
 404  
         }
 405  
     }
 406  
 
 407  
     public PathContext resolve(PathContext context, PathContext relative, String path, boolean lookForFilter) throws IOException {
 408  1106
         if (path.startsWith("/")) return resolve(path, lookForFilter);
 409  518
         return _parse(context.getInfo().getServletFile(), relative.getInfo().getServletFile(), path, lookForFilter);
 410  
     }
 411  
 
 412  
     public PathContext parse(FileObject start, FileObject relative, String path, boolean lookForFilter) throws IOException {
 413  4
         return _parse(start, relative, path, lookForFilter);
 414  
     }
 415  
 
 416  
     private PathContext _parse(FileObject start, FileObject relative, String path, boolean lookForFilter) throws IOException {
 417  
         FileObject ptr;
 418  1382
         if (start.getType().hasChildren()) {
 419  1192
             ptr = start;
 420  
         } else {
 421  190
             ptr = start.getParent();
 422  
         }
 423  
         //new Exception("parse(" + start + ", " + relative + ", " + path + ")").printStackTrace();
 424  
         //System.err.println("parse(" + start + ", " + relative + ", " + path + "), ptr=" + ptr);
 425  1382
         char[] pathChars = path.toCharArray();
 426  1382
         int mode = 0;
 427  1382
         int nameStart = -1;
 428  
         int i;
 429  
 OUTER:
 430  25634
         for (i = 0; i < pathChars.length; i++) {
 431  24305
             char c = pathChars[i];
 432  
             //System.err.println("mode=" + mode + ", i=" + i + ", c='" + c + "', ptr=" + ptr);
 433  24305
             switch (mode) {
 434  
                 case 0:
 435  1382
                     switch (c) {
 436  
                         case '/':       // absolute path
 437  864
                             ptr = ptr.getFileSystem().getRoot();
 438  864
                             mode = 10;
 439  864
                             break;
 440  
                         case '.':       // possible leading './' or '../'
 441  45
                             mode = 5;
 442  45
                             break;
 443  
                         default:
 444  473
                             nameStart = i;
 445  473
                             mode = 40;
 446  
                     }
 447  473
                     break;
 448  
                 case 5:
 449  45
                     switch (c) {
 450  
                         case '/':       // found leading './'
 451  23
                             if (relative.getType().hasChildren()) {
 452  0
                                 ptr = relative;
 453  
                             } else {
 454  23
                                 ptr = relative.getParent();
 455  
                             }
 456  23
                             mode = 10;
 457  23
                             break;
 458  
                         case '.':       // possible '../'
 459  22
                             mode = 30;
 460  22
                             break;
 461  
                         default:
 462  0
                             nameStart = i - 1;
 463  0
                             mode = 40;
 464  
                     }
 465  0
                     break;
 466  
                 case 10:
 467  2341
                     switch (c) {
 468  
                         case '/':       // '/', ignore
 469  0
                             break;
 470  
                         case '.':       // possible './' or '../'
 471  23
                             mode = 20;
 472  23
                             break;
 473  
                         default:
 474  2318
                             nameStart = i;
 475  2318
                             mode = 40;
 476  
                     }
 477  2318
                     break;
 478  
                 case 20:
 479  23
                     switch (c) {
 480  
                         case '/':       // './', ignore
 481  0
                             mode = 10;
 482  0
                             break;
 483  
                         case '.':       // possible '../'
 484  23
                             mode = 30;
 485  23
                             break;
 486  
                         default:
 487  0
                             nameStart = i - 1;
 488  0
                             mode = 40;
 489  
                     }
 490  0
                     break;
 491  
                 case 30:
 492  45
                     switch (c) {
 493  
                         case '/':       // found '../'
 494  45
                             ptr = ptr.getParent();
 495  45
                             mode = 10;
 496  45
                             break;
 497  
                         default:
 498  0
                             nameStart = i - 2;
 499  0
                             mode = 40;
 500  
                     }
 501  0
                     break;
 502  
                 case 40:
 503  20469
                     switch (c) {
 504  
                         case '/':
 505  1467
                             mode = 10;
 506  
                             //System.err.println("path[" + path + "], nameStart=" + nameStart + ", i=" + i);
 507  1467
                             String name = path.substring(nameStart, i);
 508  
                             //System.err.println("name[" + name + "]");
 509  1467
                             ptr = ptr.resolveFile(name);
 510  1467
                             if (!lookForFilter) break;
 511  1467
                             VFSUtil.refresh(ptr);
 512  1467
                             if (isFilter(ptr)) {
 513  
                                 // A filter on a file or directory
 514  51
                                 i++;
 515  51
                                 break OUTER;
 516  
                             }
 517  1416
                             String[] extensions = getExtensionList();
 518  1416
                             if (extensions == null || extensions.length == 0) {
 519  6
                                 break;
 520  
                             }
 521  
                             FileObject base;
 522  1410
                             if (ptr.getType().hasChildren()) {
 523  1390
                                 name = "index";
 524  1390
                                 base = ptr;
 525  
                             } else {
 526  20
                                 base = ptr.getParent();
 527  20
                                 VFSUtil.refresh(base);
 528  
                             }
 529  1410
                             if (!base.exists()) break;
 530  1398
                             FileObject[] children = base.getChildren();
 531  1398
                             if (children == null) break;
 532  26720
                             for (String extension: extensions) {
 533  25324
                                 String toMatch = name + extension;
 534  317537
                                 for (FileObject child: children) {
 535  292215
                                     if (child.getName().getBaseName().equals(toMatch)) {
 536  6
                                         VFSUtil.refresh(child);
 537  6
                                         if (!child.getType().hasChildren()) {
 538  6
                                             if (isFilter(child)) {
 539  2
                                                 ptr = child;
 540  2
                                                 i++;
 541  2
                                                 break OUTER;
 542  
                                             }
 543  
                                         }
 544  
                                     }
 545  
                                 }
 546  
                             }
 547  
                     }
 548  
                     break;
 549  
             }
 550  
         }
 551  1382
         PathInfo pathInfo = new GivenPathInfo(path.substring(i == pathChars.length ? i : i - 1));
 552  1382
         switch (mode) {
 553  
             case 10:
 554  58
                 if (isFilter(ptr) && pathInfo.getPathInfo().length() == 0) pathInfo = new DefaultPathInfo(ptr);
 555  
                 break;
 556  
             case 0:
 557  
             case 20:
 558  0
                 break;
 559  
             case 30:
 560  0
                 ptr = ptr.getParent();
 561  0
                 break;
 562  
             case 40:
 563  1324
                 String name = path.substring(nameStart);
 564  1324
                 ptr = ptr.resolveFile(name);
 565  1324
                 if (isFilter(ptr) && pathInfo.getPathInfo().length() == 0) pathInfo = new DefaultPathInfo(ptr);
 566  
                 break;
 567  
         }
 568  
         //System.err.println("ptr=" + ptr + ", pathInfo=\"" + path.substring(i) + "\"");
 569  1382
         return new PathContext(getFileInfo(ptr), pathInfo);
 570  
     }
 571  
 
 572  
     protected class LogWriterFactory extends GenericRollingWriterFactory {
 573  
         private final FileObject logDir;
 574  
         private final String pattern;
 575  
 
 576  26
         public LogWriterFactory(String pattern) throws IOException {
 577  26
             this.logDir = getRoot().resolveFile("/Var/Log");
 578  26
             this.pattern = pattern;
 579  26
         }
 580  
 
 581  
         protected RollingWriter newRollingWriter(String name) {
 582  0
             if (!name.startsWith("org.webslinger.")) return null;
 583  0
             name = name.substring(15);
 584  0
             return new CommonsVfsRollingWriter(logDir, name.replaceAll("\\.", "/") + ".log", pattern);
 585  
         }
 586  
     }
 587  
 
 588  135
     protected class ExtensionListTTLObject extends TTLObject<String[]> {
 589  
         protected String[] load(String[] old) throws IOException {
 590  111
             return getConfigStringSplit("extension-list");
 591  
         }
 592  
     }
 593  
 }