| 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 | |
|
| 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 | |
|
| 368 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 726 | |
|
| 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 | |
|
| 741 | 585 | filters = fofc.getObject(); |
| 742 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
|
| 1120 | |
public Servlet getServlet(String name) throws ServletException { |
| 1121 | |
|
| 1122 | 0 | return null; |
| 1123 | |
} |
| 1124 | |
|
| 1125 | |
|
| 1126 | |
public Enumeration getServlets() { |
| 1127 | |
|
| 1128 | 0 | return null; |
| 1129 | |
} |
| 1130 | |
|
| 1131 | |
|
| 1132 | |
public Enumeration getServletNames() { |
| 1133 | |
|
| 1134 | 0 | return null; |
| 1135 | |
} |
| 1136 | |
|
| 1137 | |
public void log(String msg) { |
| 1138 | 24 | getContainer().log(msg); |
| 1139 | 24 | } |
| 1140 | |
|
| 1141 | |
|
| 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 | |
|
| 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 | |
|
| 1181 | |
} |
| 1182 | |
|
| 1183 | |
public Object getAttribute(String name) { |
| 1184 | 42 | Object value = attributes.get(name); |
| 1185 | |
|
| 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 | |
|
| 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 | |
|
| 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 | |
} |