package ilarkesto.webapp; import ilarkesto.base.Str; import ilarkesto.base.Sys; import ilarkesto.base.Url; import ilarkesto.core.logging.Log; import ilarkesto.di.app.AApplication; import ilarkesto.gwt.server.AGwtConversation; import ilarkesto.io.IO; import ilarkesto.logging.DefaultLogDataHandler; import java.io.File; import java.util.HashSet; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public abstract class AWebApplication extends AApplication { private static final Log LOG = Log.get(AWebApplication.class); protected abstract void onStartWebApplication(); protected abstract void onShutdownWebApplication(); protected abstract AWebSession createWebSession(HttpServletRequest httpRequest); public abstract Url getHomeUrl(); private Set<AWebSession> webSessions = new HashSet<AWebSession>(); private String applicationName; @Override protected void onStart() { if (!isDevelopmentMode()) Sys.setHeadless(true); DefaultLogDataHandler.setLogFile(new File(getApplicationDataDir() + "/log.txt")); LOG.info("Initializing web application"); onStartWebApplication(); } @Override protected void onShutdown() { onShutdownWebApplication(); } public final AWebApplication getWebApplication() { return this; } public final void setApplicationName(String applicationName) { this.applicationName = applicationName; } @Override public String getApplicationName() { if (applicationName != null) return applicationName; String name = super.getApplicationName(); name = Str.removeSuffix(name, "Web"); return name; } private static final String WEB_SESSION_SESSION_ATTRIBUTE = "_webSession"; public final AWebSession getWebSession(HttpServletRequest httpRequest) { HttpSession httpSession = httpRequest.getSession(); AWebSession webSession = (AWebSession) httpSession.getAttribute(WEB_SESSION_SESSION_ATTRIBUTE); if (webSession != null && webSession.isSessionInvalidated()) webSession = null; if (webSession == null) { webSession = createWebSession(httpRequest); httpSession.setAttribute(WEB_SESSION_SESSION_ATTRIBUTE, webSession); synchronized (webSessions) { webSessions.add(webSession); } } else { webSession.touch(); } return webSession; } public final void destroyTimeoutedSessions() { for (AWebSession session : getWebSessions()) { if (session.isTimeouted() || session.isSessionInvalidated()) { LOG.info("Destroying invalid/timeouted session:", session); destroyWebSession(session, null); } } } public final void destroyTimeoutedGwtConversations() { for (AGwtConversation conversation : getGwtConversations()) { if (conversation.isTimeouted()) { AWebSession session = conversation.getSession(); LOG.info("Destroying invalid/timeouted GwtConversation:", conversation); session.destroyGwtConversation(conversation); } } } public final void destroyWebSession(AWebSession webSession, HttpSession httpSession) { synchronized (webSessions) { webSessions.remove(webSession); webSession.destroy(); if (httpSession != null) { try { httpSession.removeAttribute(WEB_SESSION_SESSION_ATTRIBUTE); } catch (Throwable t) {} try { httpSession.invalidate(); } catch (Throwable t) {} } } } public final Set<AWebSession> getWebSessions() { synchronized (webSessions) { return new HashSet<AWebSession>(webSessions); } } @Override protected String getProductionModeApplicationDataDir() { File dirInHome = new File(Sys.getUsersHomePath() + "/webapp-data/" + getApplicationName()); if (!dirInHome.exists()) dirInHome = new File(Sys.getUsersHomePath() + "/webapps/" + getApplicationName()); File dirInWorkdir = new File(Sys.getWorkDir() + "/webapp-data/" + getApplicationName()); if (!dirInWorkdir.exists()) dirInWorkdir = new File(Sys.getWorkDir() + "/webapps/" + getApplicationName()); if (dirInHome.exists()) return dirInHome.getAbsolutePath(); String dir = dirInWorkdir.getAbsolutePath(); if (IO.isDirWritable(dir)) return dir; dir = dirInHome.getAbsolutePath(); if (!IO.isDirWritable(dir)) throw new RuntimeException("Can not write to homedirectory (" + Sys.getUsersHomePath() + ") and not to work directory (" + Sys.getWorkDir() + ")"); return dir; } public Set<AGwtConversation> getGwtConversations() { Set<AGwtConversation> ret = new HashSet<AGwtConversation>(); for (AWebSession session : getWebSessions()) { ret.addAll(session.getGwtConversations()); } return ret; } public static AWebApplication get() { return (AWebApplication) AApplication.get(); } }