From ff783b66173a31ab9e05fa68068473b1ddb00014 Mon Sep 17 00:00:00 2001
From: Rick Herrick <jrherrick@wustl.edu>
Date: Fri, 19 Feb 2016 17:15:18 -0600
Subject: [PATCH] Replaced most of web.xml with XnatWebAppInitializer.

---
 .../configuration/XnatWebAppInitializer.java  | 116 +++++
 .../security/XnatSessionEventPublisher.java   |  35 +-
 .../org/nrg/xnat/servlet/ArchiveServlet.java  | 478 ------------------
 .../modules/actions/DownloadImages.java       |  74 ++-
 src/main/webapp/WEB-INF/web.xml               | 362 ++-----------
 5 files changed, 233 insertions(+), 832 deletions(-)
 create mode 100644 src/main/java/org/nrg/xnat/configuration/XnatWebAppInitializer.java
 delete mode 100644 src/main/java/org/nrg/xnat/servlet/ArchiveServlet.java

diff --git a/src/main/java/org/nrg/xnat/configuration/XnatWebAppInitializer.java b/src/main/java/org/nrg/xnat/configuration/XnatWebAppInitializer.java
new file mode 100644
index 00000000..c956e120
--- /dev/null
+++ b/src/main/java/org/nrg/xnat/configuration/XnatWebAppInitializer.java
@@ -0,0 +1,116 @@
+package org.nrg.xnat.configuration;
+
+import org.apache.axis.transport.http.AdminServlet;
+import org.apache.axis.transport.http.AxisHTTPSessionListener;
+import org.apache.axis.transport.http.AxisServlet;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.util.TurbineConfig;
+import org.nrg.xdat.servlet.XDATAjaxServlet;
+import org.nrg.xdat.servlet.XDATServlet;
+import org.nrg.xnat.restlet.servlet.XNATRestletServlet;
+import org.nrg.xnat.restlet.util.UpdateExpirationCookie;
+import org.nrg.xnat.security.XnatSessionEventPublisher;
+import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+
+public class XnatWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
+
+    @Override
+    public void onStartup(final ServletContext context) throws ServletException {
+        context.setInitParameter("contextAttribute", "org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring-mvc");
+        context.setInitParameter("org.restlet.component", "org.nrg.xnat.restlet.XNATComponent");
+
+        // If the context path is not empty (meaning this isn't the root application), then we'll get true: Restlet will
+        // autowire its calls. If the context path is empty (meaning that this is the root application), autowire will
+        // be false.
+        context.setInitParameter("org.restlet.autoWire", Boolean.toString(StringUtils.isNotEmpty(context.getContextPath())));
+
+        // Initialize the Spring stuff.
+        super.onStartup(context);
+
+        // Now initialize everything else.
+        context.addFilter("updateExpirationCookie", UpdateExpirationCookie.class);
+
+        context.addListener(XnatSessionEventPublisher.class);
+        context.addListener(AxisHTTPSessionListener.class);
+
+        Turbine.setTurbineServletConfig(new TurbineConfig("turbine", "WEB-INF/conf/TurbineResources.properties"));
+
+        _context = context;
+
+        addServlet(XDATServlet.class, 1, "/xdat/*");
+        addServlet(Turbine.class, 2, "/app/*");
+        addServlet(XNATRestletServlet.class, 2, "/REST/*", "/data/*");
+        addServlet(XDATAjaxServlet.class, 3, "/ajax/*", "/servlet/XDATAjaxServlet", "/servlet/AjaxServlet");
+        addServlet(AxisServlet.class, 4, "/servlet/AxisServlet", "*.jws", "/services/*");
+        addServlet(AdminServlet.class, 5, "/servlet/AdminServlet");
+
+        // TODO: Don't know how to do these things through the servlet context.
+        /*
+          <welcome-file-list>
+            <welcome-file>index.jsp</welcome-file>
+            <welcome-file>app</welcome-file>
+          </welcome-file-list>
+          <!-- ======================================================================== -->
+          <!--                                                                          -->
+          <!-- Mapping HTTP error codes and exceptions to custom error pages to make    -->
+          <!-- the display a bit more pleasant and preserve system confidentiality.     -->
+          <!--                                                                          -->
+          <!-- ======================================================================== -->
+          <error-page>
+            <exception-type>java.lang.Throwable</exception-type>
+            <location>/app/template/Error.vm</location>
+          </error-page>
+          <!-- ======================================================================== -->
+          <!--                                                                          -->
+          <!-- Make sure that templates, resources and logs are not available through   -->
+          <!-- the servlet container. Remove security constraints or add an authen-     -->
+          <!-- tication role if you need access to these paths.                         -->
+          <!--                                                                          -->
+          <!-- ======================================================================== -->
+          // Might need to do these through Spring Security configuration:
+          // http://stackoverflow.com/questions/19297796/how-to-programmatically-setup-a-security-constraint-in-servlets-3-x
+          // Or move them into WEB-INF a la Spring views. Note that logs is already removed.
+          <security-constraint>
+            <web-resource-collection>
+              <web-resource-name>templates</web-resource-name>
+              <url-pattern>/templates/*</url-pattern>
+            </web-resource-collection>
+            <web-resource-collection>
+              <web-resource-name>resources</web-resource-name>
+              <url-pattern>/resources/*</url-pattern>
+            </web-resource-collection>
+            <auth-constraint />
+          </security-constraint>
+        */
+    }
+
+    @Override
+    protected String[] getServletMappings() {
+        return new String[] { "/admin/*", "/xapi/*" };
+    }
+
+    @Override
+    protected Class<?>[] getRootConfigClasses() {
+        return new Class<?>[] { RootConfig.class };
+    }
+
+    @Override
+    protected Class<?>[] getServletConfigClasses() {
+        return new Class<?>[0];
+    }
+
+    private void addServlet(final Class<? extends Servlet> clazz, final int loadOnStartup, final String... mappings) {
+        final String                      name = StringUtils.uncapitalize(clazz.getSimpleName());
+        final ServletRegistration.Dynamic registration  = _context.addServlet(name, clazz);
+        registration.setLoadOnStartup(loadOnStartup);
+        registration.addMapping(mappings);
+    }
+
+    private ServletContext _context;
+}
diff --git a/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java b/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java
index b0d738d6..f69f2904 100644
--- a/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java
+++ b/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java
@@ -16,14 +16,15 @@ import javax.inject.Inject;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
+import javax.servlet.http.HttpSession;
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;
 import javax.sql.DataSource;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.nrg.xft.security.UserI;
 import org.nrg.xnat.restlet.resources.SecureResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.security.web.session.HttpSessionCreatedEvent;
@@ -32,12 +33,8 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
 
 
 public class XnatSessionEventPublisher implements HttpSessionListener, ServletContextListener{
-    //~ Static fields/initializers =====================================================================================
-
     private String contextAttribute = null;
-
-    private static final String LOGGER_NAME = XnatSessionEventPublisher.class.getName();
-    //~ Methods ========================================================================================================
+    private static final Logger _log = LoggerFactory.getLogger(XnatSessionEventPublisher.class);
 
     ApplicationContext getContext(ServletContext servletContext) {
         return WebApplicationContextUtils.getWebApplicationContext(servletContext,contextAttribute);  // contextAttribute in xnat's case will always be "org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring-mvc");
@@ -50,16 +47,18 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo
      * @param event HttpSessionEvent passed in by the container
      */
     public void sessionCreated(HttpSessionEvent event) {
-        HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession());
-        Log log = LogFactory.getLog(LOGGER_NAME);
+        HttpSession             session = event.getSession();
+        HttpSessionCreatedEvent e       = new HttpSessionCreatedEvent(session);
 
-        if (log.isDebugEnabled()) {
-            log.debug("Publishing event: " + e);
+        if (_log.isDebugEnabled()) {
+            _log.debug("Publishing event: " + e);
         }
-        
-        event.getSession().setAttribute("XNAT_CSRF", UUID.randomUUID().toString());
-        
-        getContext(event.getSession().getServletContext()).publishEvent(e);
+
+        // TODO: This should be wired to a database setting so that the admin can change the session timeout value.
+        session.setMaxInactiveInterval(900);
+        session.setAttribute("XNAT_CSRF", UUID.randomUUID().toString());
+
+        getContext(session.getServletContext()).publishEvent(e);
     }
 
     /**
@@ -73,8 +72,6 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo
     	String sessionId = event.getSession().getId();
         
     	
-    	Log log = LogFactory.getLog(LOGGER_NAME);
-        
       	java.util.Date today = java.util.Calendar.getInstance(java.util.TimeZone.getDefault()).getTime();
      	try {
 
@@ -90,8 +87,8 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo
       		//remember, anonymous gets a session, too. Those won't be in the table. Fail silently.
       	}
         HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession());
-        if (log.isDebugEnabled()) {
-            log.debug("Publishing event: " + e);
+        if (_log.isDebugEnabled()) {
+            _log.debug("Publishing event: " + e);
         }
         getContext(event.getSession().getServletContext()).publishEvent(e);
     }
diff --git a/src/main/java/org/nrg/xnat/servlet/ArchiveServlet.java b/src/main/java/org/nrg/xnat/servlet/ArchiveServlet.java
deleted file mode 100644
index f7dd86c1..00000000
--- a/src/main/java/org/nrg/xnat/servlet/ArchiveServlet.java
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * org.nrg.xnat.servlet.ArchiveServlet
- * XNAT http://www.xnat.org
- * Copyright (c) 2014, Washington University School of Medicine
- * All Rights Reserved
- *
- * Released under the Simplified BSD.
- *
- * Last modified 7/10/13 9:04 PM
- */
-package org.nrg.xnat.servlet;
-
-import org.apache.commons.lang.RandomStringUtils;
-import org.nrg.xdat.XDAT;
-import org.nrg.xdat.base.BaseElement;
-import org.nrg.xdat.bean.CatCatalogBean;
-import org.nrg.xdat.bean.CatEntryBean;
-import org.nrg.xdat.bean.CatEntryMetafieldBean;
-import org.nrg.xdat.om.XnatExperimentdata;
-import org.nrg.xdat.om.XnatImagesessiondata;
-import org.nrg.xdat.om.XnatProjectdata;
-import org.nrg.xdat.om.XnatSubjectdata;
-import org.nrg.xdat.security.helpers.Users;
-import org.nrg.xdat.turbine.utils.TurbineUtils;
-import org.nrg.xft.ItemI;
-import org.nrg.xft.XFTItem;
-import org.nrg.xft.db.DBAction;
-import org.nrg.xft.db.PoolDBUtils;
-import org.nrg.xft.exception.ElementNotFoundException;
-import org.nrg.xft.exception.FieldNotFoundException;
-import org.nrg.xft.exception.XFTInitException;
-import org.nrg.xft.schema.Wrappers.GenericWrapper.GenericWrapperElement;
-import org.nrg.xft.schema.Wrappers.GenericWrapper.GenericWrapperField;
-import org.nrg.xft.schema.design.SchemaElementI;
-import org.nrg.xft.search.ItemSearch;
-import org.nrg.xft.security.UserI;
-import org.nrg.xft.utils.FileUtils;
-import org.nrg.xft.utils.ResourceFile;
-import org.nrg.xft.utils.StringUtils;
-import org.nrg.xft.utils.zip.ZipI;
-import org.nrg.xft.utils.zip.ZipUtils;
-import org.nrg.xnat.turbine.utils.ArcSpecManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.zip.ZipOutputStream;
-
-@SuppressWarnings("serial")
-public class ArchiveServlet extends HttpServlet {
-    private static final Logger logger = LoggerFactory.getLogger(ArchiveServlet.class);
-
-    /* (non-Javadoc)
-     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
-     */
-    @Override
-    protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
-        doGetOrPost(arg0, arg1);
-    }
-
-    /* (non-Javadoc)
-     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
-     */
-    @Override
-    protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
-        doGetOrPost(arg0, arg1);
-    }
-
-    @SuppressWarnings("unchecked")
-    protected void getCatalog(UserI user, String path, HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
-        String rootElementName = path.substring(0, path.indexOf("/"));
-        path = path.substring(path.indexOf("/") + 1);
-
-        res.setContentType("text/xml");
-
-        if (rootElementName.equals("stored")) {
-            File f = Users.getUserCacheFile(user, "catalogs/" + path);
-            if (f.exists()) {
-                writeFile(f, res);
-                return;
-            } else {
-                return;
-            }
-        }
-
-        int indexOfSlash = path.indexOf("/");
-        final String value;
-        if (indexOfSlash == -1) {
-            value = path;
-            path = "";
-        } else {
-            value = path.substring(0, path.indexOf("/"));
-            path = path.substring(path.indexOf("/") + 1);
-        }
-
-        CatCatalogBean cat = new CatCatalogBean();
-
-        String server = TurbineUtils.GetFullServerPath(req);
-        if (!server.endsWith("/")) {
-            server += "/";
-        }
-
-        ArrayList<String> ids = StringUtils.CommaDelimitedStringToArrayList(value, true);
-
-        try {
-            final GenericWrapperElement root = GenericWrapperElement.GetElement(rootElementName);
-            final ItemSearch is = ItemSearch.GetItemSearch(root.getFullXMLName(), user);
-            int index = 0;
-            for (GenericWrapperField f : root.getAllPrimaryKeys()) {
-                is.addCriteria(f.getXMLPathString(root.getFullXMLName()), ids.get(index++));
-            }
-            final ItemI rootO = is.exec(false).getFirst();
-            final XFTItem i = (XFTItem) rootO;
-            ItemI rootOM = BaseElement.GetGeneratedItem(i);
-
-
-            String xmlPath = server + "archive/" + rootElementName + "/" + value;
-            String uri = server + "archive/cache/";
-
-            String rootPath = getRootPath(rootOM);
-            File rootDir = new File(rootPath);
-
-            final ArrayList<XFTItem> al;
-            if (!path.equals("")) {
-                al = (ArrayList<XFTItem>) i.getProperty(path, true);
-                xmlPath += "/" + path.substring(0, path.indexOf("["));
-            } else {
-                al = new ArrayList<>();
-                al.add(i);
-            }
-
-            for (XFTItem child : al) {
-                final String subString;
-                if (!path.equals("")) {
-                    subString = xmlPath + "/" + child.getPKValueString() + "/";
-                } else {
-                    subString = xmlPath;
-                }
-
-                BaseElement om = (BaseElement) BaseElement.GetGeneratedItem(child);
-                ArrayList<ResourceFile> rfs = om.getFileResources(rootPath);
-                for (ResourceFile rf : rfs) {
-                    CatEntryBean entry = new CatEntryBean();
-
-                    String relative = rf.getAbsolutePath();
-
-                    Object id = cacheFileLink(subString + rf.getXdatPath(), relative, i.getDBName(), user.getLogin());
-
-                    entry.setUri(uri + id);
-
-                    relative = relative.replace('\\', '/');
-                    String cleaned = rootPath.replace('\\', '/');
-
-                    if (relative.startsWith(cleaned)) {
-                        relative = relative.substring(cleaned.length());
-                    } else {
-                        if (relative.contains("/" + rootDir.getName() + "/")) {
-                            relative = relative.substring(relative.indexOf("/" + rootDir.getName() + "/") + 1);
-                        }
-                    }
-
-                    entry.setCachepath(relative);
-
-                    CatEntryMetafieldBean meta = new CatEntryMetafieldBean();
-                    meta.setMetafield(relative);
-                    meta.setName("RELATIVE_PATH");
-                    entry.addMetafields_metafield(meta);
-
-                    meta = new CatEntryMetafieldBean();
-                    meta.setMetafield(rf.getSize().toString());
-                    meta.setName("SIZE");
-                    entry.addMetafields_metafield(meta);
-
-
-                    cat.addEntries_entry(entry);
-                }
-            }
-
-            ServletOutputStream out = res.getOutputStream();
-
-            OutputStreamWriter sw = new OutputStreamWriter(out);
-            cat.toXML(sw, false);
-            sw.flush();
-            sw.close();
-        } catch (XFTInitException e) {
-            logger.error("An error occurred initializing XFT", e);
-        } catch (ElementNotFoundException e) {
-            logger.error("Did not find the requested element on the item", e);
-        } catch (Exception e) {
-            logger.error("An unknown exception occurred", e);
-        }
-    }
-
-    public static boolean ARCHIVE_PATH_CHECKED = false;
-
-    public static Boolean CreatedArchivePathCache(String dbName, String login) throws Exception {
-        if (!ARCHIVE_PATH_CHECKED) {
-            String query = "SELECT relname FROM pg_catalog.pg_class WHERE  relname=LOWER('xs_archive_path_cache');";
-            String exists = (String) PoolDBUtils.ReturnStatisticQuery(query, "relname", dbName, login);
-
-            if (exists != null) {
-                ARCHIVE_PATH_CHECKED = true;
-            } else {
-                query = "CREATE TABLE xs_archive_path_cache" +
-                        "\n(" +
-                        "\n  id serial," +
-                        "\n  create_date timestamp DEFAULT now()," +
-                        "\n  username VARCHAR(255)," +
-                        "\n  url text," +
-                        "\n  _token VARCHAR(255)," +
-                        "\n  absolute_path text" +
-                        "\n) " +
-                        "\nWITH OIDS;";
-
-                PoolDBUtils.ExecuteNonSelectQuery(query, dbName, login);
-
-                ARCHIVE_PATH_CHECKED = true;
-            }
-        }
-        return true;
-    }
-
-    public static Object cacheFileLink(String url, String absolutePath, String dbName, String login) throws Exception {
-        CreatedArchivePathCache(dbName, login);
-        Object o = RandomStringUtils.randomAlphanumeric(64);
-        Object exists = PoolDBUtils.ReturnStatisticQuery("SELECT id FROM xs_archive_path_cache WHERE _token='" + o + "';", "id", dbName, login);
-        while (exists != null) {
-            o = RandomStringUtils.randomAlphanumeric(64);
-            exists = PoolDBUtils.ReturnStatisticQuery("SELECT id FROM xs_archive_path_cache WHERE _token='" + o + "';", "id", dbName, login);
-        }
-        String query = "INSERT INTO xs_archive_path_cache (username,url,_token,absolute_path) VALUES ('" + login + "'," + DBAction.ValueParser(url, "string", true) + ",'" + o + "'," + DBAction.ValueParser(absolutePath, "string", true) + ");";
-        PoolDBUtils.ExecuteNonSelectQuery(query, dbName, login);
-        return o;
-    }
-
-    public Object retrieveCacheFileLink(String o, String dbName, String login) throws Exception {
-        o = StringUtils.RemoveChar(o, '\'');
-        return PoolDBUtils.ReturnStatisticQuery("SELECT absolute_path FROM xs_archive_path_cache WHERE _token='" + o + "';", "absolute_path", dbName, login);
-    }
-
-    protected String getRootPath(ItemI i) {
-        if (i instanceof XnatProjectdata) {
-            return ((XnatProjectdata) i).getRootArchivePath();
-        } else if (i instanceof XnatSubjectdata) {
-            return ((XnatSubjectdata) i).getPrimaryProject(false).getRootArchivePath();
-        } else if (i instanceof XnatExperimentdata) {
-            return ((XnatExperimentdata) i).getPrimaryProject(false).getRootArchivePath();
-        }
-        return null;
-    }
-
-    protected void writeFile(File _return, HttpServletResponse res) throws IOException {
-        writeFile(_return, res, _return.getName());
-    }
-
-    protected void writeFile(File _return, HttpServletResponse res, String name) throws IOException {
-        TurbineUtils.setContentDisposition(res, name, false);
-
-        OutputStream os = res.getOutputStream();
-        java.io.FileInputStream in = new java.io.FileInputStream(_return);
-        byte[] buf = new byte[FileUtils.LARGE_DOWNLOAD];
-        int len;
-        while ((len = in.read(buf)) > 0) {
-            os.write(buf, 0, len);
-            os.flush();
-        }
-        os.flush();
-        in.close();
-    }
-
-    protected void getDataFile(UserI user, String path, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-        logger.info("Performing " + request.getMethod() + " operation to: " + request.getPathInfo());
-        String rootElementName = path.substring(0, path.indexOf("/"));
-        path = path.substring(path.indexOf("/") + 1);
-        String value = path.substring(0, path.indexOf("/"));
-        path = path.substring(path.indexOf("/") + 1);
-
-        final ArrayList<String> ids = StringUtils.CommaDelimitedStringToArrayList(value, true);
-
-        XFTItem session = null;
-        XFTItem project = null;
-        try {
-            final GenericWrapperElement root = GenericWrapperElement.GetElement(rootElementName);
-            SchemaElementI localE = root;
-            ItemSearch is = ItemSearch.GetItemSearch(root.getFullXMLName(), user);
-            int index = 0;
-            for (GenericWrapperField f : root.getAllPrimaryKeys()) {
-                is.addCriteria(f.getXMLPathString(root.getFullXMLName()), ids.get(index++));
-            }
-
-            final ItemI rootO = is.exec(false).getFirst();
-            XFTItem i = (XFTItem) rootO;
-
-            if (i.instanceOf("xnat:projectData")) {
-                project = i;
-            } else if (i.instanceOf("xnat:imageSessionData")) {
-                session = i;
-            }
-
-            String nextPath = null;
-            GenericWrapperField lastField = null;
-            while (path.contains("/")) {
-                final String next = path.substring(0, path.indexOf("/"));
-
-                try {
-                    if (lastField == null) {
-                        lastField = localE.getGenericXFTElement().getDirectField(next);
-                    } else {
-                        lastField = lastField.getDirectField(next);
-                    }
-
-                    if (nextPath == null) {
-                        nextPath = next;
-                    } else {
-                        nextPath += "/" + next;
-                    }
-
-                    path = path.substring(path.indexOf("/") + 1);
-
-                    if (lastField.isReference()) {
-                        localE = lastField.getReferenceElement();
-                        value = path.substring(0, path.indexOf("/"));
-                        path = path.substring(path.indexOf("/") + 1);
-
-                        ids.clear();
-                        ids.addAll(StringUtils.CommaDelimitedStringToArrayList(value, true));
-
-                        is = ItemSearch.GetItemSearch(localE.getFullXMLName(), user);
-                        index = 0;
-                        for (GenericWrapperField f : localE.getGenericXFTElement().getAllPrimaryKeys()) {
-                            is.addCriteria(f.getXMLPathString(localE.getFullXMLName()), ids.get(index++));
-                        }
-                        i = (XFTItem) is.exec(false).getFirst();
-
-                        lastField = null;
-                        nextPath = null;
-
-                        if (i.instanceOf("xnat:projectData")) {
-                            project = i;
-                        } else if (i.instanceOf("xnat:imageSessionData")) {
-                            session = i;
-                        }
-                    }
-                } catch (FieldNotFoundException e) {
-                    break;
-                }
-            }
-
-            System.out.println("ENDING:" + path);
-
-
-            //identify project
-            if (project == null) {
-                if (session != null) {
-                    XnatImagesessiondata img = (XnatImagesessiondata) BaseElement.GetGeneratedItem(session);
-                    project = img.getPrimaryProject(false).getItem();
-                } else {
-                    ArrayList<XFTItem> parents = i.getParents("xnat:projectData");
-                    project = parents.get(0);
-                }
-            }
-
-            XnatProjectdata p = (XnatProjectdata) BaseElement.GetGeneratedItem(project);
-            String rootPath = p.getRootArchivePath();
-
-            BaseElement om = (BaseElement) BaseElement.GetGeneratedItem(i);
-
-            ArrayList<ResourceFile> resources = om.getFileResources(rootPath);
-
-            if (path.equals("*")) {
-                response.setContentType("application/zip");
-                TurbineUtils.setContentDisposition(response, value + ".zip", false);
-                OutputStream outStream = response.getOutputStream();
-                final ZipI zip = new ZipUtils();
-                zip.setOutputStream(outStream, ZipOutputStream.DEFLATED);
-
-                for (ResourceFile rf : resources) {
-                    File f = rf.getF();
-                    String relative = f.getAbsolutePath();
-                    if (session != null) {
-                        if (relative.contains(File.separator + session.getProperty("ID"))) {
-                            relative = relative.substring(relative.indexOf(File.separator + session.getProperty("ID")) + 1);
-                        } else if (project != null) {
-                            if (relative.contains(File.separator + project.getProperty("ID"))) {
-                                relative = relative.substring(relative.indexOf(File.separator + project.getProperty("ID")) + 1);
-                            }
-                        }
-                    } else if (project != null) {
-                        if (relative.contains(File.separator + project.getProperty("ID"))) {
-                            relative = relative.substring(relative.indexOf(File.separator + project.getProperty("ID")) + 1);
-                        }
-                    }
-                    zip.write(relative, f);
-                }
-
-                // Complete the ZIP file
-                zip.close();
-            } else {
-                File _return = null;
-                for (ResourceFile rf : resources) {
-                    if (rf.getF().getName().equals(path)) {
-                        _return = rf.getF();
-                        break;
-                    }
-                }
-
-                if (_return == null) {
-                    int count = Integer.parseInt(path);
-                    _return = resources.get(count).getF();
-                }
-
-                if (_return != null) {
-                    writeFile(_return, response);
-                }
-            }
-        } catch (XFTInitException e) {
-            logger.error("An error occurred initializing XFT", e);
-        } catch (ElementNotFoundException e) {
-            logger.error("Did not find the requested element on the item", e);
-        } catch (Exception e) {
-            logger.error("An unknown exception occurred", e);
-        }
-    }
-
-    protected void doGetOrPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-        logger.info("Performing " + request.getMethod() + " operation to: " + request.getPathInfo());
-        String path = request.getPathInfo();
-        if (path.startsWith("/")) {
-            path = path.substring(1);
-        }
-
-        UserI user = XDAT.getUserDetails();
-
-        if (path.startsWith("catalogs/")) {
-            if (user != null)
-                getCatalog(user, path.substring(9), request, response);
-        } else if (path.startsWith("cache/")) {
-            String o = path.substring(6);
-            try {
-                String dbName = GenericWrapperElement.GetElement("xdat:user").getDbName();
-                String login = null;
-                if (user != null) {
-                    login = user.getLogin();
-                }
-                String filePath = (String) retrieveCacheFileLink(o, dbName, login);
-                if (filePath != null) {
-                    File f = new File(filePath);
-                    if (f.exists()) {
-                        writeFile(f, response);
-                    }
-                }
-            } catch (Exception e) {
-                logger.error("", e);
-            }
-        } else if (user != null) {
-            getDataFile(user, path, request, response);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
-     */
-    @Override
-    public void init(ServletConfig arg0) throws ServletException {
-        super.init(arg0);
-        ArcSpecManager.GetInstance();
-    }
-}
diff --git a/src/main/java/org/nrg/xnat/turbine/modules/actions/DownloadImages.java b/src/main/java/org/nrg/xnat/turbine/modules/actions/DownloadImages.java
index 0479289a..5b115cfd 100644
--- a/src/main/java/org/nrg/xnat/turbine/modules/actions/DownloadImages.java
+++ b/src/main/java/org/nrg/xnat/turbine/modules/actions/DownloadImages.java
@@ -10,21 +10,8 @@
  */
 package org.nrg.xnat.turbine.modules.actions;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.zip.ZipOutputStream;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletResponse;
-
+import edu.sdsc.grid.io.GeneralFile;
+import org.apache.commons.lang.RandomStringUtils;
 import org.apache.log4j.Logger;
 import org.apache.turbine.util.RunData;
 import org.apache.velocity.context.Context;
@@ -39,16 +26,24 @@ import org.nrg.xdat.security.helpers.Users;
 import org.nrg.xdat.turbine.modules.actions.SecureAction;
 import org.nrg.xdat.turbine.utils.TurbineUtils;
 import org.nrg.xft.ItemI;
+import org.nrg.xft.db.DBAction;
+import org.nrg.xft.db.PoolDBUtils;
 import org.nrg.xft.schema.Wrappers.XMLWrapper.SAXWriter;
 import org.nrg.xft.security.UserI;
 import org.nrg.xft.utils.FileUtils;
 import org.nrg.xft.utils.zip.TarUtils;
 import org.nrg.xft.utils.zip.ZipI;
 import org.nrg.xft.utils.zip.ZipUtils;
-import org.nrg.xnat.servlet.ArchiveServlet;
 import org.nrg.xnat.srb.XNATDirectory;
 
-import edu.sdsc.grid.io.GeneralFile;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.*;
+import java.util.zip.ZipOutputStream;
 
 /**
  * @author timo
@@ -166,7 +161,7 @@ public class DownloadImages extends SecureAction {
                                 
                                 String relative = f.getAbsolutePath();
                                 
-                                Object file_id = ArchiveServlet.cacheFileLink(url + identifier, relative, mr.getDBName(), user.getLogin());
+                                Object file_id = cacheFileLink(url + identifier, relative, mr.getDBName(), user.getLogin());
                                 
                                 entry.setUri(uri + file_id);
                                 
@@ -445,4 +440,47 @@ public class DownloadImages extends SecureAction {
 		    
     }
 
+    public static boolean ARCHIVE_PATH_CHECKED = false;
+
+    public static Boolean CreatedArchivePathCache(String dbName, String login) throws Exception {
+        if (!ARCHIVE_PATH_CHECKED) {
+            String query = "SELECT relname FROM pg_catalog.pg_class WHERE  relname=LOWER('xs_archive_path_cache');";
+            String exists = (String) PoolDBUtils.ReturnStatisticQuery(query, "relname", dbName, login);
+
+            if (exists != null) {
+                ARCHIVE_PATH_CHECKED = true;
+            } else {
+                query = "CREATE TABLE xs_archive_path_cache" +
+                        "\n(" +
+                        "\n  id serial," +
+                        "\n  create_date timestamp DEFAULT now()," +
+                        "\n  username VARCHAR(255)," +
+                        "\n  url text," +
+                        "\n  _token VARCHAR(255)," +
+                        "\n  absolute_path text" +
+                        "\n) " +
+                        "\nWITH OIDS;";
+
+                PoolDBUtils.ExecuteNonSelectQuery(query, dbName, login);
+
+                ARCHIVE_PATH_CHECKED = true;
+            }
+        }
+        return true;
+    }
+
+    public static Object cacheFileLink(String url, String absolutePath, String dbName, String login) throws Exception {
+        CreatedArchivePathCache(dbName, login);
+        Object o = RandomStringUtils.randomAlphanumeric(64);
+        Object exists = PoolDBUtils.ReturnStatisticQuery("SELECT id FROM xs_archive_path_cache WHERE _token='" + o + "';", "id", dbName, login);
+        while (exists != null) {
+            o = RandomStringUtils.randomAlphanumeric(64);
+            exists = PoolDBUtils.ReturnStatisticQuery("SELECT id FROM xs_archive_path_cache WHERE _token='" + o + "';", "id", dbName, login);
+        }
+        String query = "INSERT INTO xs_archive_path_cache (username,url,_token,absolute_path) VALUES ('" + login + "'," + DBAction.ValueParser(url, "string", true) + ",'" + o + "'," + DBAction.ValueParser(absolutePath, "string", true) + ");";
+        PoolDBUtils.ExecuteNonSelectQuery(query, dbName, login);
+        return o;
+    }
+
+
 }
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index d581085a..be7a9476 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -1,326 +1,54 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~ D:/Development/XNAT/1.6/xnat_builder_1_6dev/plugin-resources/originals/application-web.xml
   ~ XNAT http://www.xnat.org
-  ~ Copyright (c) 2014, Washington University School of Medicine
+  ~ Copyright (c) 2016, Washington University School of Medicine
   ~ All Rights Reserved
   ~
   ~ Released under the Simplified BSD.
-  ~
-  ~ Last modified 2/7/14 12:19 PM
   -->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
-  <!-- ======================================================================== -->
-  <!--                                                                          -->
-  <!-- Uncomment the following block if you want to use the Session Service     -->
-  <!--                                                                          -->
-  <!-- ======================================================================== -->
-  <!--
-  	<listener>
-    	<listener-class>org.apache.turbine.services.session.SessionListener</listener-class>
-  	</listener>
-	-->
-  <!-- HttpSessionEventPublisher enables session counting for the concurrent session filter, XnatSessionEventPublisher requires the contextAttribute parameter -->
-  <context-param>
-    <param-name>contextAttribute</param-name>
-    <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring-mvc</param-value>
-  </context-param>
-  <context-param>
-    <param-name>org.restlet.component</param-name>
-    <param-value>org.nrg.xnat.restlet.XNATComponent</param-value>
-  </context-param>
-  <!--
-    	 This setting will be automatically configured according to xdat.url in build.properties.
-    	 You can still set it manually if desired (not here - do it in xnat/projects/xnat/src/web-conf/web-projectMerge.xml).
-    -->
-  <context-param>
-    <param-name>org.restlet.autoWire</param-name>
-    <param-value>false</param-value>
-  </context-param>
-  <filter>
-    <filter-name>springSecurityFilterChain</filter-name>
-    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
-    <init-param>
-      <param-name>contextAttribute</param-name>
-      <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring-mvc</param-value>
-    </init-param>
-  </filter>
-  <filter>
-    <filter-name>updateExpirationCookie</filter-name>
-    <filter-class>org.nrg.xnat.restlet.util.UpdateExpirationCookie</filter-class>
-  </filter>
-  <filter-mapping>
-    <filter-name>springSecurityFilterChain</filter-name>
-    <url-pattern>/*</url-pattern>
-  </filter-mapping>
-  <filter-mapping>
-    <filter-name>updateExpirationCookie</filter-name>
-    <url-pattern>/*</url-pattern>
-  </filter-mapping>
-  <listener>
-    <listener-class>org.nrg.xnat.security.XnatSessionEventPublisher</listener-class>
-  </listener>
-  <listener>
-    <listener-class>org.apache.axis.transport.http.AxisHTTPSessionListener</listener-class>
-  </listener>
-  <servlet>
-    <servlet-name>xnat17</servlet-name>
-    <servlet-class>org.apache.turbine.Turbine</servlet-class>
-    <init-param>
-      <param-name>properties</param-name>
-      <param-value>WEB-INF/conf/TurbineResources.properties</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  <!-- BEGIN XNAT CUSTOMIZATIONS -->
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Spring Framework -->
-  <!-- ======================================================================== -->
-  <servlet>
-    <servlet-name>spring-mvc</servlet-name>
-    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
-    <init-param>
-      <param-name>contextConfigLocation</param-name>
-      <param-value>/WEB-INF/conf/root-spring-config.xml</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  <servlet>
-    <servlet-name>xdat</servlet-name>
-    <servlet-class>org.nrg.xdat.servlet.XDATServlet</servlet-class>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR RESTServlet -->
-  <!-- ======================================================================== -->
-  <servlet>
-    <servlet-name>RestletServlet</servlet-name>
-    <servlet-class>org.nrg.xnat.restlet.servlet.XNATRestletServlet</servlet-class>
-    <load-on-startup>2</load-on-startup>
-  </servlet>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR ArchiveServlet -->
-  <!-- ======================================================================== -->
-  <servlet>
-    <servlet-name>ArchiveServlet</servlet-name>
-    <servlet-class>org.nrg.xnat.servlet.ArchiveServlet</servlet-class>
-    <load-on-startup>2</load-on-startup>
-  </servlet>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Ajax -->
-  <!-- ======================================================================== -->
-  <servlet>
-    <servlet-name>XDATAjaxServlet</servlet-name>
-    <servlet-class>org.nrg.xdat.servlet.XDATAjaxServlet</servlet-class>
-  </servlet>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Apache Axis -->
-  <!-- ======================================================================== -->
-  <servlet>
-    <servlet-name>AxisServlet</servlet-name>
-    <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>AdminServlet</servlet-name>
-    <servlet-class>org.apache.axis.transport.http.AdminServlet</servlet-class>
-    <load-on-startup>100</load-on-startup>
-  </servlet>
-  <servlet>
-    <servlet-name>SOAPMonitorService</servlet-name>
-    <servlet-class>org.apache.axis.monitor.SOAPMonitorService</servlet-class>
-    <init-param>
-      <param-name>SOAPMonitorPort</param-name>
-      <param-value>5001</param-value>
-    </init-param>
-    <load-on-startup>100</load-on-startup>
-  </servlet>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Image Viewer -->
-  <!-- ======================================================================== -->
-  <servlet>
-    <servlet-name>PopulateServlet</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.PopulateServlet</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>ImageDistributorServlet</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.ImageDistributorServlet</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>ImageLoaderServlet</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.ImageLoaderServlet</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>MontageImageLoaderServlet</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.MontageImageLoaderServlet</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>GetRecFileContents</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.GetRecFileContents</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>getAsegRegionVolumes</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.getAsegRegionVolumes</servlet-class>
-  </servlet>
-  <servlet>
-    <servlet-name>PublisherServlet</servlet-name>
-    <servlet-class>org.nrg.plexiViewer.Servlet.PublisherServlet</servlet-class>
-  </servlet>
-  <servlet-mapping>
-    <servlet-name>spring-mvc</servlet-name>
-    <url-pattern>/admin/*</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>spring-mvc</servlet-name>
-    <url-pattern>/xapi/*</url-pattern>
-  </servlet-mapping>
-  <!-- END XNAT CUSTOMIZATIONS -->
-  <servlet-mapping>
-    <servlet-name>xnat17</servlet-name>
-    <url-pattern>/app/*</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>xdat</servlet-name>
-    <url-pattern>/xdat/*</url-pattern>
-  </servlet-mapping>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR RESTServlet  -->
-  <!-- ======================================================================== -->
-  <servlet-mapping>
-    <servlet-name>RestletServlet</servlet-name>
-    <url-pattern>/REST/*</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>RestletServlet</servlet-name>
-    <url-pattern>/data/*</url-pattern>
-  </servlet-mapping>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Ajax -->
-  <!-- ======================================================================== -->
-  <servlet-mapping>
-    <servlet-name>XDATAjaxServlet</servlet-name>
-    <url-pattern>/ajax/*</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>XDATAjaxServlet</servlet-name>
-    <url-pattern>/servlet/XDATAjaxServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>XDATAjaxServlet</servlet-name>
-    <url-pattern>/servlet/AjaxServlet</url-pattern>
-  </servlet-mapping>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Apache Axis -->
-  <!-- ======================================================================== -->
-  <servlet-mapping>
-    <servlet-name>AdminServlet</servlet-name>
-    <url-pattern>/servlet/AdminServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>AxisServlet</servlet-name>
-    <url-pattern>/servlet/AxisServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>AxisServlet</servlet-name>
-    <url-pattern>*.jws</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>AxisServlet</servlet-name>
-    <url-pattern>/services/*</url-pattern>
-  </servlet-mapping>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR Image Viewer -->
-  <!-- ======================================================================== -->
-  <servlet-mapping>
-    <servlet-name>SOAPMonitorService</servlet-name>
-    <url-pattern>/SOAPMonitor</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>PopulateServlet</servlet-name>
-    <url-pattern>/servlet/PopulateServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>ImageDistributorServlet</servlet-name>
-    <url-pattern>/servlet/ImageDistributorServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>ImageLoaderServlet</servlet-name>
-    <url-pattern>/servlet/ImageLoaderServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>MontageImageLoaderServlet</servlet-name>
-    <url-pattern>/servlet/MontageImageLoaderServlet</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GetRecFileContents</servlet-name>
-    <url-pattern>/servlet/GetRecFileContents</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>getAsegRegionVolumes</servlet-name>
-    <url-pattern>/servlet/getAsegRegionVolumes</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>PublisherServlet</servlet-name>
-    <url-pattern>/servlet/PublisherServlet</url-pattern>
-  </servlet-mapping>
-  <!-- ======================================================================== -->
-  <!-- INSERTED FOR ArchiveServlet -->
-  <!-- ======================================================================== -->
-  <servlet-mapping>
-    <servlet-name>ArchiveServlet</servlet-name>
-    <url-pattern>/archive/*</url-pattern>
-  </servlet-mapping>
-  <session-config>
-    <!-- Default to 15 minute session timeouts -->
-    <session-timeout>15</session-timeout>
-  </session-config>
-  <mime-mapping>
-    <extension>wsdl</extension>
-    <mime-type>text/xml</mime-type>
-  </mime-mapping>
-  <mime-mapping>
-    <extension>xsd</extension>
-    <mime-type>text/xml</mime-type>
-  </mime-mapping>
-  <!-- ======================================================================== -->
-  <!--                                                                          -->
-  <!-- Redirect the home page of the application to the turbine servlet         -->
-  <!--                                                                          -->
-  <!-- ======================================================================== -->
-  <welcome-file-list>
-    <welcome-file>index.jsp</welcome-file>
-    <welcome-file>app</welcome-file>
-  </welcome-file-list>
-  <!-- ======================================================================== -->
-  <!--                                                                          -->
-  <!-- Mapping HTTP error codes and exceptions to custom error pages to make    -->
-  <!-- the display a bit more pleasant and preserve system confidentiality.     -->
-  <!--                                                                          -->
-  <!-- ======================================================================== -->
-  <error-page>
-    <exception-type>java.lang.Throwable</exception-type>
-    <location>/app/template/Error.vm</location>
-  </error-page>
-  <!-- ======================================================================== -->
-  <!--                                                                          -->
-  <!-- Make sure that templates, resources and logs are not available through   -->
-  <!-- the servlet container. Remove security constraints or add an authen-     -->
-  <!-- tication role if you need access to these paths.                         -->
-  <!--                                                                          -->
-  <!-- ======================================================================== -->
-  <security-constraint>
-    <web-resource-collection>
-      <web-resource-name>templates</web-resource-name>
-      <url-pattern>/templates/*</url-pattern>
-    </web-resource-collection>
-    <web-resource-collection>
-      <web-resource-name>logs</web-resource-name>
-      <url-pattern>/logs/*</url-pattern>
-    </web-resource-collection>
-    <web-resource-collection>
-      <web-resource-name>resources</web-resource-name>
-      <url-pattern>/resources/*</url-pattern>
-    </web-resource-collection>
-    <auth-constraint />
-  </security-constraint>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+    <!-- ======================================================================== -->
+    <!--                                                                          -->
+    <!-- Redirect the home page of the application to the turbine servlet         -->
+    <!--                                                                          -->
+    <!-- ======================================================================== -->
+    <welcome-file-list>
+        <welcome-file>index.jsp</welcome-file>
+        <welcome-file>app</welcome-file>
+    </welcome-file-list>
+    <!-- ======================================================================== -->
+    <!--                                                                          -->
+    <!-- Mapping HTTP error codes and exceptions to custom error pages to make    -->
+    <!-- the display a bit more pleasant and preserve system confidentiality.     -->
+    <!--                                                                          -->
+    <!-- ======================================================================== -->
+    <error-page>
+        <exception-type>java.lang.Throwable</exception-type>
+        <location>/app/template/Error.vm</location>
+    </error-page>
+    <!-- ======================================================================== -->
+    <!--                                                                          -->
+    <!-- Make sure that templates, resources and logs are not available through   -->
+    <!-- the servlet container. Remove security constraints or add an authen-     -->
+    <!-- tication role if you need access to these paths.                         -->
+    <!--                                                                          -->
+    <!-- ======================================================================== -->
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>templates</web-resource-name>
+            <url-pattern>/templates/*</url-pattern>
+        </web-resource-collection>
+        <web-resource-collection>
+            <web-resource-name>logs</web-resource-name>
+            <url-pattern>/logs/*</url-pattern>
+        </web-resource-collection>
+        <web-resource-collection>
+            <web-resource-name>resources</web-resource-name>
+            <url-pattern>/resources/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint/>
+    </security-constraint>
 </web-app>
 
-- 
GitLab