| 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 | |
|
| 424 | |
|
| 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 | |
|
| 433 | 24305 | switch (mode) { |
| 434 | |
case 0: |
| 435 | 1382 | switch (c) { |
| 436 | |
case '/': |
| 437 | 864 | ptr = ptr.getFileSystem().getRoot(); |
| 438 | 864 | mode = 10; |
| 439 | 864 | break; |
| 440 | |
case '.': |
| 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 '/': |
| 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 '.': |
| 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 '/': |
| 469 | 0 | break; |
| 470 | |
case '.': |
| 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 '/': |
| 481 | 0 | mode = 10; |
| 482 | 0 | break; |
| 483 | |
case '.': |
| 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 '/': |
| 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 | |
|
| 507 | 1467 | String name = path.substring(nameStart, i); |
| 508 | |
|
| 509 | 1467 | ptr = ptr.resolveFile(name); |
| 510 | 1467 | if (!lookForFilter) break; |
| 511 | 1467 | VFSUtil.refresh(ptr); |
| 512 | 1467 | if (isFilter(ptr)) { |
| 513 | |
|
| 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 | |
|
| 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 | |
} |