s_dateFormat = new ThreadLocal<>();
- // Request/Response abstractions to simplify our code
- protected interface Request
- {
-
- /**
- * Returns the value of the specified request header as a String
. If the request did not include a header of the
- * specified name, this method returns null
. If there are multiple headers with the same name, this method returns the
- * first head in the request. The header name is case insensitive. You can use this method with any request header.
- *
- * @param name
- * a String
specifying the
- * header name
- *
- * @return a String
containing the
- * value of the requested
- * header, or null
- * if the request does not
- * have a header of that name
- *
- * @see HttpServletRequest#getHeader(String)
- * @see WebScriptRequest#getHeader(String)
- *
- */
- String getHeader(String name);
- }
-
- protected interface Response
- {
-
- /**
- *
- * Sets the status code for this response. This method is used to set the return status code when there is no error (for example,
- * for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, and the caller wishes to invoke an error-page defined
- * in the web application, the sendError
method should be used instead.
- *
- *
- *
- * The container clears the buffer and sets the Location header, preserving cookies and other headers.
- *
- *
- * @param status
- * the status code
- *
- * @see HttpServletResponse#setStatus(int)
- * @see WebScriptResponse#setStatus(int)
- */
- void setStatus(int status);
-
- /**
- * Sets a response header with the given name and value.If the header had already been set, the new value overwrites the previous
- * one. The containsHeader
method can be used to test for the presence of a header before setting its value.
- *
- * @param name
- * the name of the header
- * @param value
- * the header value If it contains octet string,
- * it should be encoded according to RFC 2047
- * (http://www.ietf.org/rfc/rfc2047.txt)
- *
- * @see HttpServletResponse#setHeader(String, String)
- * @see WebScriptResponse#setHeader(String, String)
- *
- */
- void setHeader(String name, String value);
-
- /**
- * Sets the Content Type
- *
- * @param contentType
- * String
- *
- * @see HttpServletResponse#setContentType(String)
- * @see WebScriptResponse#setContentType(String)
- */
- void setContentType(String contentType);
-
- /**
- * Sets the Content Encoding
- *
- * @param contentEncoding
- * String
- *
- * @see WebScriptResponse#setContentEncoding(String)
- */
- void setContentEncoding(String contentEncoding);
-
- /**
- * Sets the Cache control
- *
- * @param cache
- * cache control
- *
- * @see WebScriptResponse#setCache(Cache)
- */
- void setCache(Cache cache);
-
- /**
- * Returns a {@link OutputStream} suitable for writing binary data in the response. The servlet container does not encode the binary
- * data.
- *
- * @return a {@link OutputStream} for writing binary data
- *
- * @exception IOException
- * if an input or output exception occurred
- *
- * @see HttpServletResponse#getOutputStream()
- * @see WebScriptResponse#getOutputStream()
- */
- OutputStream getOutputStream() throws IOException;
- }
-
- protected static class WebScriptRequestWrapper implements Request
- {
-
- protected final WebScriptRequest req;
-
- protected WebScriptRequestWrapper(final WebScriptRequest req)
- {
- this.req = req;
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public String getHeader(final String name)
- {
- return this.req.getHeader(name);
- }
- }
-
- protected static class HttpServletRequestWrapper implements Request
- {
-
- protected final HttpServletRequest req;
-
- protected HttpServletRequestWrapper(final HttpServletRequest req)
- {
- this.req = req;
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public String getHeader(final String name)
- {
- return this.req.getHeader(name);
- }
- }
-
- protected static class WebScriptResponseWrapper implements Response
- {
-
- protected final WebScriptResponse res;
-
- protected WebScriptResponseWrapper(final WebScriptResponse res)
- {
- this.res = res;
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setStatus(final int status)
- {
- this.res.setStatus(status);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setHeader(final String name, final String value)
- {
- this.res.setHeader(name, value);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setContentType(final String contentType)
- {
- this.res.setContentType(contentType);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setContentEncoding(final String contentEncoding)
- {
- this.res.setContentEncoding(contentEncoding);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setCache(final Cache cache)
- {
- this.res.setCache(cache);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public OutputStream getOutputStream() throws IOException
- {
- return this.res.getOutputStream();
- }
-
- }
-
- protected static class HttpServletResponseWrapper implements Response
- {
-
- protected final HttpServletResponse res;
-
- protected HttpServletResponseWrapper(final HttpServletResponse res)
- {
- this.res = res;
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setStatus(final int status)
- {
- this.res.setStatus(status);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setHeader(final String name, final String value)
- {
- this.res.setHeader(name, value);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setContentType(final String contentType)
- {
- this.res.setContentType(contentType);
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public void setContentEncoding(final String contentEncoding)
- {
- this.res.setCharacterEncoding(contentEncoding);
- }
-
- @Override
- public void setCache(final Cache cache)
- {
- // copied from WebScriptServletResponseImpl and adapted to avoid +-concatenation
- // set Cache-Control
- final StringBuilder cacheControl = new StringBuilder(64);
- String pragma = "";
- if (cache.getIsPublic())
- {
- cacheControl.append("public");
- }
- if (cache.getNeverCache())
- {
- if (cacheControl.length() > 0)
- {
- cacheControl.append(", ");
- }
- cacheControl.append(NO_CACHE);
- pragma = NO_CACHE;
- }
- if (cache.getMaxAge() != null && cache.getNeverCache() == false)
- {
- if (cacheControl.length() > 0)
- {
- cacheControl.append(", ");
- }
- cacheControl.append("max-age=").append(cache.getMaxAge());
- }
- if (cache.getMustRevalidate() && cache.getNeverCache() == false)
- {
- if (cacheControl.length() > 0)
- {
- cacheControl.append(", ");
- }
- cacheControl.append("must-revalidate");
- }
- if (cacheControl.length() > 0)
- {
- final String cacheControlValue = cacheControl.toString();
- this.res.setHeader("Cache-Control", cacheControlValue);
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Cache - set response header Cache-Control: " + cacheControl);
- }
- // special case for IE Ajax request handling
- if (NO_CACHE.equals(cacheControlValue))
- {
- this.res.setHeader("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
- }
- }
- if (pragma.length() > 0)
- {
- this.res.setHeader("Pragma", pragma);
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Cache - set response header Pragma: " + pragma);
- }
- }
-
- // set ETag
- if (cache.getETag() != null)
- {
- final String eTag = "\"" + cache.getETag() + "\"";
- this.res.setHeader("ETag", eTag);
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Cache - set response header ETag: " + eTag);
- }
- }
-
- // set Last Modified
- if (cache.getLastModified() != null)
- {
- this.res.setDateHeader("Last-Modified", cache.getLastModified().getTime());
- if (LOGGER.isDebugEnabled())
- {
- final SimpleDateFormat formatter = getHTTPDateFormat();
- final String lastModified = formatter.format(cache.getLastModified());
- LOGGER.debug("Cache - set response header Last-Modified: " + lastModified);
- }
- }
- }
-
- /**
- *
- * {@inheritDoc}
- */
- @Override
- public OutputStream getOutputStream() throws IOException
- {
- return this.res.getOutputStream();
- }
-
- }
-
// provide method variants for specific request / response types
- protected void streamContent(final WebScriptRequest req, final WebScriptResponse res, final File file, final Long modifiedTime,
+ protected void streamContent(final Supplier req, final Supplier res, final File file, final Long modifiedTime,
final boolean attach, final String attachFileName, final Map model, final String mimetype) throws IOException
{
- final WebScriptRequestWrapper reqWrapper = new WebScriptRequestWrapper(req);
- final WebScriptResponseWrapper resWrapper = new WebScriptResponseWrapper(res);
- this.streamContent(reqWrapper, resWrapper, file, modifiedTime, attach, attachFileName, model, mimetype);
- }
-
- protected void streamContent(final HttpServletRequest req, final HttpServletResponse res, final File file, final Long modifiedTime,
- final boolean attach, final String attachFileName, final Map model, final String mimetype) throws IOException
- {
- final HttpServletRequestWrapper reqWrapper = new HttpServletRequestWrapper(req);
- final HttpServletResponseWrapper resWrapper = new HttpServletResponseWrapper(res);
- this.streamContent(reqWrapper, resWrapper, file, modifiedTime, attach, attachFileName, model, mimetype);
+ this.streamContent(req.get(), res.get(), file, modifiedTime, attach, attachFileName, model, mimetype);
}
// copied from Repo-tier ContentStreamer and base classes since they aren't available in Share
@@ -650,7 +266,7 @@ protected boolean processSingleRange(final Response res, final File file, final
LOGGER.debug("Failed to parse range header - returning 416 status code: " + err.getMessage());
}
- res.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
+ res.setStatus(Status.STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
res.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
res.getOutputStream().close();
return true;
@@ -659,7 +275,7 @@ protected boolean processSingleRange(final Response res, final File file, final
// set Partial Content status and range headers
final String contentRange = "bytes " + Long.toString(r.start) + "-" + Long.toString(r.end) + "/" + Long.toString(file.length());
- res.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+ res.setStatus(Status.STATUS_PARTIAL_CONTENT);
res.setContentType(mimetype);
res.setHeader(HEADER_CONTENT_RANGE, contentRange);
res.setHeader(HEADER_CONTENT_LENGTH, Long.toString((r.end - r.start) + 1L));
@@ -777,13 +393,13 @@ protected static class Range implements Comparable
* Constructor
*
* @param contentType
- * Mimetype of the range content
+ * Mimetype of the range content
* @param start
- * Start position in the parent entity
+ * Start position in the parent entity
* @param end
- * End position in the parent entity
+ * End position in the parent entity
* @param entityLength
- * Length of the parent entity
+ * Length of the parent entity
*/
Range(final String contentType, final long start, final long end, final long entityLength)
{
@@ -797,16 +413,16 @@ protected static class Range implements Comparable
* Factory method to construct a byte range from a range header value.
*
* @param range
- * Range header value
+ * Range header value
* @param contentType
- * Mimetype of the range
+ * Mimetype of the range
* @param entityLength
- * Length of the parent entity
+ * Length of the parent entity
*
* @return Range
*
* @throws IllegalArgumentException
- * for an invalid range
+ * for an invalid range
*/
static Range constructRange(String range, final String contentType, final long entityLength)
{
@@ -855,19 +471,6 @@ static Range constructRange(String range, final String contentType, final long e
}
}
- /**
- * Output the header bytes for a multi-part byte range header
- */
- void outputHeader(final ServletOutputStream os) throws IOException
- {
- // output multi-part boundry separator
- os.println(MULTIPART_BYTERANGES_BOUNDRY_SEP);
- // output content type and range size sub-header for this part
- os.println(this.contentType);
- os.println(this.getContentRange());
- os.println();
- }
-
/**
* @return the length in bytes of the byte range content including the header bytes
*/
@@ -908,12 +511,12 @@ public int compareTo(final Range o)
}
// copied from Repo-tier WebDAVHelper
- protected final static String encodeURL(final String s)
+ protected static final String encodeURL(final String s)
{
return encodeURL(s, null);
}
- protected final static String encodeURL(final String s, final String userAgent)
+ protected static final String encodeURL(final String s, final String userAgent)
{
return URLEncoder.encode(s);
}
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaHttpServletRequestWrapper.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaHttpServletRequestWrapper.java
new file mode 100644
index 00000000..5cdd72bd
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaHttpServletRequestWrapper.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * This class is used to wrap a (Java EE) {@link HttpServletRequest servlet request} for use in the {@link ContentStreamer} and
+ * {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public class JakartaHttpServletRequestWrapper implements Request
+{
+
+ protected final HttpServletRequest req;
+
+ protected JakartaHttpServletRequestWrapper(final HttpServletRequest req)
+ {
+ this.req = req;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHeader(final String name)
+ {
+ return this.req.getHeader(name);
+ }
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaHttpServletResponseWrapper.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaHttpServletResponseWrapper.java
new file mode 100644
index 00000000..d3aca011
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaHttpServletResponseWrapper.java
@@ -0,0 +1,208 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+
+import jakarta.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.extensions.webscripts.Cache;
+
+/**
+ * This class is used to wrap a (Java EE) {@link HttpServletResponse servlet response} for use in the {@link ContentStreamer} and
+ * {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public class JakartaHttpServletResponseWrapper implements Response
+{
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JakartaHttpServletResponseWrapper.class);
+
+ private final HttpServletResponse res;
+
+ public JakartaHttpServletResponseWrapper(final HttpServletResponse res)
+ {
+ this.res = res;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setStatus(final int status)
+ {
+ this.res.setStatus(status);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setHeader(final String name, final String value)
+ {
+ this.res.setHeader(name, value);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setContentType(final String contentType)
+ {
+ this.res.setContentType(contentType);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setContentEncoding(final String contentEncoding)
+ {
+ this.res.setCharacterEncoding(contentEncoding);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setCache(final Cache cache)
+ {
+ // copied from WebScriptServletResponseImpl and adapted to avoid +-concatenation
+ // set Cache-Control
+ final StringBuilder cacheControl = new StringBuilder(64);
+ String pragma = "";
+ if (cache.getIsPublic())
+ {
+ cacheControl.append("public");
+ }
+ if (cache.getNeverCache())
+ {
+ if (cacheControl.length() > 0)
+ {
+ cacheControl.append(", ");
+ }
+ cacheControl.append(ContentStreamer.NO_CACHE);
+ pragma = ContentStreamer.NO_CACHE;
+ }
+ if (cache.getMaxAge() != null && cache.getNeverCache() == false)
+ {
+ if (cacheControl.length() > 0)
+ {
+ cacheControl.append(", ");
+ }
+ cacheControl.append("max-age=").append(cache.getMaxAge());
+ }
+ if (cache.getMustRevalidate() && cache.getNeverCache() == false)
+ {
+ if (cacheControl.length() > 0)
+ {
+ cacheControl.append(", ");
+ }
+ cacheControl.append("must-revalidate");
+ }
+ if (cacheControl.length() > 0)
+ {
+ final String cacheControlValue = cacheControl.toString();
+ this.res.setHeader("Cache-Control", cacheControlValue);
+ LOGGER.debug("Cache - set response header Cache-Control: {}", cacheControl);
+ // special case for IE Ajax request handling
+ if (ContentStreamer.NO_CACHE.equals(cacheControlValue))
+ {
+ this.res.setHeader("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
+ }
+ }
+ if (pragma.length() > 0)
+ {
+ this.res.setHeader("Pragma", pragma);
+ LOGGER.debug("Cache - set response header Pragma: {}", pragma);
+ }
+
+ // set ETag
+ if (cache.getETag() != null)
+ {
+ final String eTag = "\"" + cache.getETag() + "\"";
+ this.res.setHeader("ETag", eTag);
+ LOGGER.debug("Cache - set response header ETag: {}", eTag);
+ }
+
+ // set Last Modified
+ if (cache.getLastModified() != null)
+ {
+ this.res.setDateHeader("Last-Modified", cache.getLastModified().getTime());
+ if (LOGGER.isDebugEnabled())
+ {
+ final SimpleDateFormat formatter = ContentStreamer.getHTTPDateFormat();
+ final String lastModified = formatter.format(cache.getLastModified());
+ LOGGER.debug("Cache - set response header Last-Modified: {}", lastModified);
+ }
+ }
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public OutputStream getOutputStream() throws IOException
+ {
+ return this.res.getOutputStream();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCommitted()
+ {
+ return res.isCommitted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void reset()
+ {
+ res.reset();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendError(int status, String message) throws IOException
+ {
+ res.sendError(status, message);
+ }
+
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaLogFileGetServlet.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaLogFileGetServlet.java
new file mode 100644
index 00000000..60f5d9d8
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaLogFileGetServlet.java
@@ -0,0 +1,158 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.extensions.surf.FrameworkBean;
+import org.springframework.extensions.surf.LinkBuilder;
+import org.springframework.extensions.surf.LinkBuilderFactory;
+import org.springframework.extensions.surf.RequestContext;
+import org.springframework.extensions.surf.UserFactory;
+import org.springframework.extensions.surf.WebFrameworkServiceRegistry;
+import org.springframework.extensions.surf.support.ServletRequestContext;
+import org.springframework.extensions.surf.util.URLDecoder;
+import org.springframework.extensions.webscripts.Cache;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.connector.User;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * @author Axel Faust
+ */
+@WebServlet(name = "OOTBee Support Tools - Log File Download", urlPatterns = { "/ootbee-support-tools/log4j-log-file/*" })
+public class JakartaLogFileGetServlet extends HttpServlet
+{
+
+ private static final long serialVersionUID = 5162376729083905078L;
+
+ protected LogFileHandler logFileHandler;
+
+ protected WebFrameworkServiceRegistry serviceRegistry;
+
+ protected FrameworkBean frameworkBean;
+
+ protected LinkBuilder linkBuilder;
+
+ protected UserFactory userFactory;
+
+ protected Method userFactoryInitialiseUserMethod;
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void init() throws ServletException
+ {
+ super.init();
+ try
+ {
+ final Method getWebApplicationContextMethod = WebApplicationContextUtils.class.getMethod("getRequiredWebApplicationContext",
+ ServletContext.class);
+ final ApplicationContext context = (ApplicationContext) getWebApplicationContextMethod.invoke(null, this.getServletContext());
+ this.logFileHandler = context.getBean(LogFileHandler.class);
+ this.serviceRegistry = context.getBean("webframework.service.registry", WebFrameworkServiceRegistry.class);
+ this.frameworkBean = context.getBean("framework.utils", FrameworkBean.class);
+ this.linkBuilder = context.getBean("webframework.factory.linkbuilder.servlet", LinkBuilderFactory.class).newInstance();
+ this.userFactory = context.getBean("user.factory", UserFactory.class);
+
+ this.userFactoryInitialiseUserMethod = UserFactory.class.getMethod("initialiseUser", RequestContext.class,
+ HttpServletRequest.class, String.class);
+ }
+ catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e)
+ {
+ throw new ServletException("Unable to init servlet", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException
+ {
+ if (req.getCharacterEncoding() == null)
+ {
+ req.setCharacterEncoding("UTF-8");
+ }
+
+ User user = null;
+
+ final ServletRequestContext context = new ServletRequestContext(this.serviceRegistry, this.frameworkBean, this.linkBuilder);
+ final String userEndpointId = (String) context.getAttribute(RequestContext.USER_ENDPOINT);
+ try
+ {
+ user = (User) this.userFactoryInitialiseUserMethod.invoke(this.userFactory, context, req, userEndpointId);
+ }
+ catch (InvocationTargetException e)
+ {
+ res.sendError(Status.STATUS_INTERNAL_SERVER_ERROR, e.getCause().getMessage());
+ }
+ catch (final IllegalAccessException e)
+ {
+ res.sendError(Status.STATUS_INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+
+ if (user != null && user.isAdmin())
+ {
+ final String requestURI = req.getRequestURI();
+ String filePath = URLDecoder.decode(requestURI.substring(req.getContextPath().length() + req.getServletPath().length() + 1));
+ if (!filePath.startsWith("/"))
+ {
+ filePath = "/" + filePath;
+ }
+
+ final Map model = new HashMap<>();
+ final Status status = new Status();
+ final Cache cache = new Cache();
+ cache.setNeverCache(true);
+ model.put("status", status);
+ model.put("cache", cache);
+
+ final String attachParam = req.getParameter("a");
+ final boolean attach = attachParam != null && Boolean.parseBoolean(attachParam);
+
+ final JakartaHttpServletRequestWrapper reqW = new JakartaHttpServletRequestWrapper(req);
+ final JakartaHttpServletResponseWrapper resW = new JakartaHttpServletResponseWrapper(res);
+ this.logFileHandler.handleLogFileRequest(filePath, attach, () -> reqW, () -> resW, model);
+ }
+ else
+ {
+ res.sendError(Status.STATUS_FORBIDDEN);
+ }
+ }
+
+}
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaLogFilesZIPPostServlet.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaLogFilesZIPPostServlet.java
new file mode 100644
index 00000000..9dd3c8e4
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/JakartaLogFilesZIPPostServlet.java
@@ -0,0 +1,170 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.extensions.surf.FrameworkBean;
+import org.springframework.extensions.surf.LinkBuilder;
+import org.springframework.extensions.surf.LinkBuilderFactory;
+import org.springframework.extensions.surf.RequestContext;
+import org.springframework.extensions.surf.UserFactory;
+import org.springframework.extensions.surf.WebFrameworkServiceRegistry;
+import org.springframework.extensions.surf.support.ServletRequestContext;
+import org.springframework.extensions.webscripts.Cache;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.connector.User;
+import org.springframework.extensions.webscripts.servlet.FormData;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * @author Axel Faust
+ */
+@WebServlet(name = "OOTBee Support Tools - Log ZIP File Download", urlPatterns = { "/ootbee-support-tools/log4j-log-files.zip" })
+public class JakartaLogFilesZIPPostServlet extends HttpServlet
+{
+
+ private static final long serialVersionUID = 6594146886154738251L;
+
+ protected LogFileHandler logFileHandler;
+
+ protected WebFrameworkServiceRegistry serviceRegistry;
+
+ protected FrameworkBean frameworkBean;
+
+ protected LinkBuilder linkBuilder;
+
+ protected UserFactory userFactory;
+
+ protected Method userFactoryInitialiseUserMethod;
+
+ protected Constructor formDataCtor;
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void init() throws ServletException
+ {
+ super.init();
+ try
+ {
+ final Method getWebApplicationContextMethod = WebApplicationContextUtils.class.getMethod("getRequiredWebApplicationContext",
+ ServletContext.class);
+ final ApplicationContext context = (ApplicationContext) getWebApplicationContextMethod.invoke(null, this.getServletContext());
+ this.logFileHandler = context.getBean(LogFileHandler.class);
+ this.serviceRegistry = context.getBean("webframework.service.registry", WebFrameworkServiceRegistry.class);
+ this.frameworkBean = context.getBean("framework.utils", FrameworkBean.class);
+ this.linkBuilder = context.getBean("webframework.factory.linkbuilder.servlet", LinkBuilderFactory.class).newInstance();
+ this.userFactory = context.getBean("user.factory", UserFactory.class);
+
+ this.userFactoryInitialiseUserMethod = UserFactory.class.getMethod("initialiseUser", RequestContext.class,
+ HttpServletRequest.class, String.class);
+ this.formDataCtor = FormData.class.getConstructor(HttpServletRequest.class);
+ }
+ catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e)
+ {
+ throw new ServletException("Unable to init servlet", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doPost(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException
+ {
+ if (req.getCharacterEncoding() == null)
+ {
+ req.setCharacterEncoding("UTF-8");
+ }
+
+ User user = null;
+
+ final ServletRequestContext context = new ServletRequestContext(this.serviceRegistry, this.frameworkBean, this.linkBuilder);
+ final String userEndpointId = (String) context.getAttribute(RequestContext.USER_ENDPOINT);
+ try
+ {
+ user = (User) this.userFactoryInitialiseUserMethod.invoke(this.userFactory, context, req, userEndpointId);
+ }
+ catch (InvocationTargetException e)
+ {
+ res.sendError(Status.STATUS_INTERNAL_SERVER_ERROR, e.getCause().getMessage());
+ }
+ catch (final IllegalAccessException e)
+ {
+ res.sendError(Status.STATUS_INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+
+ if (user != null && user.isAdmin())
+ {
+ final Map model = new HashMap<>();
+ final Status status = new Status();
+ final Cache cache = new Cache();
+ cache.setNeverCache(true);
+ model.put("status", status);
+ model.put("cache", cache);
+
+ final FormData rqData;
+ try
+ {
+ rqData = this.formDataCtor.newInstance(req);
+ }
+ catch (InvocationTargetException | InstantiationException | IllegalAccessException e)
+ {
+ res.sendError(Status.STATUS_INTERNAL_SERVER_ERROR, e.getMessage());
+ return;
+ }
+
+ final List filePaths = new ArrayList<>();
+ final String[] paths = rqData.getParameters().get("paths");
+ filePaths.addAll(Arrays.asList(paths));
+
+ final JakartaHttpServletRequestWrapper reqW = new JakartaHttpServletRequestWrapper(req);
+ final JakartaHttpServletResponseWrapper resW = new JakartaHttpServletResponseWrapper(res);
+ this.logFileHandler.handleLogZipRequest(filePaths, () -> reqW, () -> resW, model);
+ }
+ else
+ {
+ res.sendError(Status.STATUS_FORBIDDEN);
+ }
+ }
+
+}
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyHttpServletRequestWrapper.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyHttpServletRequestWrapper.java
new file mode 100644
index 00000000..101c5ae9
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyHttpServletRequestWrapper.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This class is used to wrap a (Java EE) {@link HttpServletRequest servlet request} for use in the {@link ContentStreamer} and
+ * {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public class LegacyHttpServletRequestWrapper implements Request
+{
+
+ protected final HttpServletRequest req;
+
+ protected LegacyHttpServletRequestWrapper(final HttpServletRequest req)
+ {
+ this.req = req;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHeader(final String name)
+ {
+ return this.req.getHeader(name);
+ }
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyHttpServletResponseWrapper.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyHttpServletResponseWrapper.java
new file mode 100644
index 00000000..bed8df53
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyHttpServletResponseWrapper.java
@@ -0,0 +1,208 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.extensions.webscripts.Cache;
+
+/**
+ * This class is used to wrap a (Java EE) {@link HttpServletResponse servlet response} for use in the {@link ContentStreamer} and
+ * {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public class LegacyHttpServletResponseWrapper implements Response
+{
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LegacyHttpServletResponseWrapper.class);
+
+ private final HttpServletResponse res;
+
+ public LegacyHttpServletResponseWrapper(final HttpServletResponse res)
+ {
+ this.res = res;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setStatus(final int status)
+ {
+ this.res.setStatus(status);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setHeader(final String name, final String value)
+ {
+ this.res.setHeader(name, value);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setContentType(final String contentType)
+ {
+ this.res.setContentType(contentType);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setContentEncoding(final String contentEncoding)
+ {
+ this.res.setCharacterEncoding(contentEncoding);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setCache(final Cache cache)
+ {
+ // copied from WebScriptServletResponseImpl and adapted to avoid +-concatenation
+ // set Cache-Control
+ final StringBuilder cacheControl = new StringBuilder(64);
+ String pragma = "";
+ if (cache.getIsPublic())
+ {
+ cacheControl.append("public");
+ }
+ if (cache.getNeverCache())
+ {
+ if (cacheControl.length() > 0)
+ {
+ cacheControl.append(", ");
+ }
+ cacheControl.append(ContentStreamer.NO_CACHE);
+ pragma = ContentStreamer.NO_CACHE;
+ }
+ if (cache.getMaxAge() != null && cache.getNeverCache() == false)
+ {
+ if (cacheControl.length() > 0)
+ {
+ cacheControl.append(", ");
+ }
+ cacheControl.append("max-age=").append(cache.getMaxAge());
+ }
+ if (cache.getMustRevalidate() && cache.getNeverCache() == false)
+ {
+ if (cacheControl.length() > 0)
+ {
+ cacheControl.append(", ");
+ }
+ cacheControl.append("must-revalidate");
+ }
+ if (cacheControl.length() > 0)
+ {
+ final String cacheControlValue = cacheControl.toString();
+ this.res.setHeader("Cache-Control", cacheControlValue);
+ LOGGER.debug("Cache - set response header Cache-Control: {}", cacheControl);
+ // special case for IE Ajax request handling
+ if (ContentStreamer.NO_CACHE.equals(cacheControlValue))
+ {
+ this.res.setHeader("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
+ }
+ }
+ if (pragma.length() > 0)
+ {
+ this.res.setHeader("Pragma", pragma);
+ LOGGER.debug("Cache - set response header Pragma: {}", pragma);
+ }
+
+ // set ETag
+ if (cache.getETag() != null)
+ {
+ final String eTag = "\"" + cache.getETag() + "\"";
+ this.res.setHeader("ETag", eTag);
+ LOGGER.debug("Cache - set response header ETag: {}", eTag);
+ }
+
+ // set Last Modified
+ if (cache.getLastModified() != null)
+ {
+ this.res.setDateHeader("Last-Modified", cache.getLastModified().getTime());
+ if (LOGGER.isDebugEnabled())
+ {
+ final SimpleDateFormat formatter = ContentStreamer.getHTTPDateFormat();
+ final String lastModified = formatter.format(cache.getLastModified());
+ LOGGER.debug("Cache - set response header Last-Modified: {}", lastModified);
+ }
+ }
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public OutputStream getOutputStream() throws IOException
+ {
+ return this.res.getOutputStream();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCommitted()
+ {
+ return res.isCommitted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void reset()
+ {
+ res.reset();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendError(int status, String message) throws IOException
+ {
+ res.sendError(status, message);
+ }
+
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGetServlet.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyLogFileGetServlet.java
similarity index 88%
rename from share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGetServlet.java
rename to share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyLogFileGetServlet.java
index 0611f294..98e493ce 100644
--- a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGetServlet.java
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyLogFileGetServlet.java
@@ -27,6 +27,7 @@
import java.util.Map;
import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -49,7 +50,8 @@
/**
* @author Axel Faust
*/
-public class LogFileGetServlet extends HttpServlet
+@WebServlet(name = "OOTBee Support Tools - Log File Download", urlPatterns = { "/ootbee-support-tools/log4j-log-file/*" })
+public class LegacyLogFileGetServlet extends HttpServlet
{
private static final long serialVersionUID = 5162376729083905078L;
@@ -107,8 +109,7 @@ protected void doGet(final HttpServletRequest req, final HttpServletResponse res
if (user != null && user.isAdmin())
{
final String requestURI = req.getRequestURI();
- String filePath = URLDecoder
- .decode(requestURI.substring(req.getContextPath().length() + req.getServletPath().length() + 1));
+ String filePath = URLDecoder.decode(requestURI.substring(req.getContextPath().length() + req.getServletPath().length() + 1));
if (!filePath.startsWith("/"))
{
filePath = "/" + filePath;
@@ -124,7 +125,9 @@ protected void doGet(final HttpServletRequest req, final HttpServletResponse res
final String attachParam = req.getParameter("a");
final boolean attach = attachParam != null && Boolean.parseBoolean(attachParam);
- this.logFileHandler.handleLogFileRequest(filePath, attach, req, res, model);
+ final LegacyHttpServletRequestWrapper reqW = new LegacyHttpServletRequestWrapper(req);
+ final LegacyHttpServletResponseWrapper resW = new LegacyHttpServletResponseWrapper(res);
+ this.logFileHandler.handleLogFileRequest(filePath, attach, () -> reqW, () -> resW, model);
}
else
{
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPostServlet.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyLogFilesZIPPostServlet.java
similarity index 89%
rename from share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPostServlet.java
rename to share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyLogFilesZIPPostServlet.java
index 457851e0..4d35bce6 100644
--- a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPostServlet.java
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LegacyLogFilesZIPPostServlet.java
@@ -30,6 +30,7 @@
import java.util.Map;
import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -52,7 +53,8 @@
/**
* @author Axel Faust
*/
-public class LogFilesZIPPostServlet extends HttpServlet
+@WebServlet(name = "OOTBee Support Tools - Log ZIP File Download", urlPatterns = { "/ootbee-support-tools/log4j-log-files.zip" })
+public class LegacyLogFilesZIPPostServlet extends HttpServlet
{
private static final long serialVersionUID = 6594146886154738251L;
@@ -121,7 +123,9 @@ protected void doPost(final HttpServletRequest req, final HttpServletResponse re
final String[] paths = rqData.getParameters().get("paths");
filePaths.addAll(Arrays.asList(paths));
- this.logFileHandler.handleLogZipRequest(filePaths, req, res, model);
+ final LegacyHttpServletRequestWrapper reqW = new LegacyHttpServletRequestWrapper(req);
+ final LegacyHttpServletResponseWrapper resW = new LegacyHttpServletResponseWrapper(res);
+ this.logFileHandler.handleLogZipRequest(filePaths, () -> reqW, () -> resW, model);
}
else
{
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGet.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGet.java
index b829c695..d250b69e 100644
--- a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGet.java
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileGet.java
@@ -55,6 +55,8 @@ public void execute(final WebScriptRequest req, final WebScriptResponse res) thr
final String attachParam = req.getParameter("a");
final boolean attach = attachParam != null && Boolean.parseBoolean(attachParam);
- this.logFileHandler.handleLogFileRequest(filePath, attach, req, res, model);
+ final WebScriptRequestWrapper reqW = new WebScriptRequestWrapper(req);
+ final WebScriptResponseWrapper resW = new WebScriptResponseWrapper(res);
+ this.logFileHandler.handleLogFileRequest(filePath, attach, () -> reqW, () -> resW, model);
}
}
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileHandler.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileHandler.java
index b2f7f082..83b37d9e 100644
--- a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileHandler.java
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFileHandler.java
@@ -25,13 +25,12 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import java.util.function.Supplier;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.TempFileProvider;
@@ -43,7 +42,6 @@
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
-import org.springframework.extensions.webscripts.WebScriptResponse;
/**
* This class is used to consolidate the log file handling logic that may need to be shared between web script and servlet based log file
@@ -178,17 +176,8 @@ public void setContentStreamer(final ContentStreamer contentStreamer)
this.contentStreamer = contentStreamer;
}
- protected void handleLogFileRequest(final String filePath, final boolean attach, final WebScriptRequest req,
- final WebScriptResponse res, final Map model) throws IOException
- {
- final File file = validateFilePath(filePath);
-
- final String mimetype = determineMimetypeFromFileName(file);
- this.contentStreamer.streamContent(req, res, file, file.lastModified(), attach, file.getName(), model, mimetype);
- }
-
- protected void handleLogFileRequest(final String filePath, final boolean attach, final HttpServletRequest req,
- final HttpServletResponse res, final Map model) throws IOException
+ protected void handleLogFileRequest(final String filePath, final boolean attach, final Supplier req,
+ final Supplier res, final Map model) throws IOException
{
try
{
@@ -199,41 +188,24 @@ protected void handleLogFileRequest(final String filePath, final boolean attach,
}
catch (final WebScriptException wsex)
{
- if (!res.isCommitted())
+ Response rres = res.get();
+ if (!rres.isCommitted())
{
- res.reset();
- res.sendError(wsex.getStatus(), wsex.getMessage());
+ rres.reset();
+ rres.sendError(wsex.getStatus(), wsex.getMessage());
}
- else
+ else if (!(rres instanceof WebScriptResponseWrapper))
{
LOGGER.info("Could not send error via committed response", wsex);
}
- }
- }
-
- protected void handleLogZipRequest(final List filePaths, final WebScriptRequest req, final WebScriptResponse res,
- final Map model) throws IOException
- {
- final List files = LogFileHandler.validateFilePaths(filePaths);
- final File logFileZip = TempFileProvider.createTempFile("ootbee-support-tools-logFiles", "zip");
- try
- {
- this.createZip(files, logFileZip);
-
- this.contentStreamer.streamContent(req, res, logFileZip, logFileZip.lastModified(), false, "log-files.zip", model,
- "application/zip");
- }
- finally
- {
- // eager cleanup
- if (!logFileZip.delete())
+ else
{
- logFileZip.deleteOnExit();
+ throw wsex;
}
}
}
- protected void handleLogZipRequest(final List filePaths, final HttpServletRequest req, final HttpServletResponse res,
+ protected void handleLogZipRequest(final List filePaths, final Supplier req, final Supplier res,
final Map model) throws IOException
{
try
@@ -250,7 +222,7 @@ protected void handleLogZipRequest(final List filePaths, final HttpServl
finally
{
// eager cleanup
- if (!logFileZip.delete())
+ if (!Files.deleteIfExists(logFileZip.toPath()))
{
logFileZip.deleteOnExit();
}
@@ -258,15 +230,20 @@ protected void handleLogZipRequest(final List filePaths, final HttpServl
}
catch (final WebScriptException wsex)
{
- if (!res.isCommitted())
+ Response rres = res.get();
+ if (!rres.isCommitted())
{
- res.reset();
- res.sendError(wsex.getStatus(), wsex.getMessage());
+ rres.reset();
+ rres.sendError(wsex.getStatus(), wsex.getMessage());
}
- else
+ else if (!(rres instanceof WebScriptResponseWrapper))
{
LOGGER.info("Could not send error via committed response", wsex);
}
+ else
+ {
+ throw wsex;
+ }
}
}
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPost.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPost.java
index f737ea66..e160efc2 100644
--- a/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPost.java
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/LogFilesZIPPost.java
@@ -66,7 +66,9 @@ public void execute(final WebScriptRequest req, final WebScriptResponse res) thr
final String[] paths = rqData.getParameters().get("paths");
filePaths.addAll(Arrays.asList(paths));
- this.logFileHandler.handleLogZipRequest(filePaths, req, res, model);
+ final WebScriptRequestWrapper reqW = new WebScriptRequestWrapper(req);
+ final WebScriptResponseWrapper resW = new WebScriptResponseWrapper(res);
+ this.logFileHandler.handleLogZipRequest(filePaths, () -> reqW, () -> resW, model);
}
}
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/Request.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/Request.java
new file mode 100644
index 00000000..8a35a318
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/Request.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+/**
+ * This interface is used to abstract the actual request away for our {@link ContentStreamer} and {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public interface Request
+{
+
+ /**
+ * Returns the value of the specified request header as a String
. If the request did not include a header of the
+ * specified name, this method returns null
. If there are multiple headers with the same name, this method returns the
+ * first head in the request. The header name is case insensitive. You can use this method with any request header.
+ *
+ * @param name
+ * a String
specifying the
+ * header name
+ *
+ * @return a String
containing the
+ * value of the requested
+ * header, or null
+ * if the request does not
+ * have a header of that name
+ *
+ */
+ String getHeader(String name);
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/Response.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/Response.java
new file mode 100644
index 00000000..c73c8663
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/Response.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.springframework.extensions.webscripts.Cache;
+
+/**
+ * This interface is used to abstract the actual response away for our {@link ContentStreamer} and {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public interface Response
+{
+
+ /**
+ *
+ * Sets the status code for this response. This method is used to set the return status code when there is no error (for example,
+ * for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, and the caller wishes to invoke an error-page defined
+ * in the web application, the sendError
method should be used instead.
+ *
+ *
+ *
+ * The container clears the buffer and sets the Location header, preserving cookies and other headers.
+ *
+ *
+ * @param status
+ * the status code
+ *
+ */
+ void setStatus(int status);
+
+ /**
+ * Sets a response header with the given name and value.If the header had already been set, the new value overwrites the previous
+ * one. The containsHeader
method can be used to test for the presence of a header before setting its value.
+ *
+ * @param name
+ * the name of the header
+ * @param value
+ * the header value If it contains octet string,
+ * it should be encoded according to RFC 2047
+ * (http://www.ietf.org/rfc/rfc2047.txt)
+ *
+ */
+ void setHeader(String name, String value);
+
+ /**
+ * Sets the Content Type
+ *
+ * @param contentType
+ * String
+ *
+ */
+ void setContentType(String contentType);
+
+ /**
+ * Sets the Content Encoding
+ *
+ * @param contentEncoding
+ * String
+ *
+ */
+ void setContentEncoding(String contentEncoding);
+
+ /**
+ * Sets the Cache control
+ *
+ * @param cache
+ * cache control
+ *
+ */
+ void setCache(Cache cache);
+
+ /**
+ * Returns a {@link OutputStream} suitable for writing binary data in the response. The servlet container does not encode the binary
+ * data.
+ *
+ * @return a {@link OutputStream} for writing binary data
+ *
+ * @exception IOException
+ * if an input or output exception occurred
+ *
+ */
+ OutputStream getOutputStream() throws IOException;
+
+ /**
+ * Retrieves the flag denoting whether the response was already committed.
+ *
+ * @return {@code true} if the response was already committed
+ */
+ boolean isCommitted();
+
+ /**
+ * Reset the response.
+ */
+ void reset();
+
+ /**
+ * Send an error status.
+ *
+ * @param status
+ * the status code
+ * @param message
+ * the error message
+ */
+ void sendError(int status, String message) throws IOException;
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/WebScriptRequestWrapper.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/WebScriptRequestWrapper.java
new file mode 100644
index 00000000..28869b85
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/WebScriptRequestWrapper.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * This class is used to wrap a {@link WebScriptRequest web script request} for use in the {@link ContentStreamer} and
+ * {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public class WebScriptRequestWrapper implements Request
+{
+
+ protected final WebScriptRequest req;
+
+ protected WebScriptRequestWrapper(final WebScriptRequest req)
+ {
+ this.req = req;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHeader(final String name)
+ {
+ return this.req.getHeader(name);
+ }
+}
\ No newline at end of file
diff --git a/share/src/main/java/org/orderofthebee/addons/support/tools/share/WebScriptResponseWrapper.java b/share/src/main/java/org/orderofthebee/addons/support/tools/share/WebScriptResponseWrapper.java
new file mode 100644
index 00000000..14f806fb
--- /dev/null
+++ b/share/src/main/java/org/orderofthebee/addons/support/tools/share/WebScriptResponseWrapper.java
@@ -0,0 +1,141 @@
+/**
+ * Copyright (C) 2016 - 2023 Order of the Bee
+ *
+ * This file is part of OOTBee Support Tools
+ *
+ * OOTBee Support Tools is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OOTBee Support Tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OOTBee Support Tools. If not, see
+ * .
+ *
+ * Linked to Alfresco
+ * Copyright (C) 2005 - 2023 Alfresco Software Limited.
+ */
+package org.orderofthebee.addons.support.tools.share;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.springframework.extensions.webscripts.Cache;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+/**
+ * This class is used to wrap a {@link WebScriptResponse web script response} for use in the {@link ContentStreamer} and
+ * {@link LogFileHandler}.
+ *
+ * @author Axel Faust
+ */
+public class WebScriptResponseWrapper implements Response
+{
+
+ private final WebScriptResponse res;
+
+ public WebScriptResponseWrapper(final WebScriptResponse res)
+ {
+ this.res = res;
+ }
+
+ /**
+ * @return the res
+ */
+ public WebScriptResponse getWebScriptResponse()
+ {
+ return res;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setStatus(final int status)
+ {
+ this.res.setStatus(status);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setHeader(final String name, final String value)
+ {
+ this.res.setHeader(name, value);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setContentType(final String contentType)
+ {
+ this.res.setContentType(contentType);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setContentEncoding(final String contentEncoding)
+ {
+ this.res.setContentEncoding(contentEncoding);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void setCache(final Cache cache)
+ {
+ this.res.setCache(cache);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public OutputStream getOutputStream() throws IOException
+ {
+ return this.res.getOutputStream();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCommitted()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void reset()
+ {
+ // NO-OP
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendError(int status, String message)
+ {
+ // NO-OP
+ }
+}
\ No newline at end of file
diff --git a/share/src/main/resources/META-INF/web-fragment.xml b/share/src/main/resources/META-INF/web-fragment.xml
deleted file mode 100644
index 78e876ff..00000000
--- a/share/src/main/resources/META-INF/web-fragment.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- ${moduleId}-web-fragment
-
-
-
-
-
-
-
-
- OOTBee Support Tools - Log File Download
- org.orderofthebee.addons.support.tools.share.LogFileGetServlet
-
-
-
- OOTBee Support Tools - Log ZIP File Download
- org.orderofthebee.addons.support.tools.share.LogFilesZIPPostServlet
-
-
-
- OOTBee Support Tools - Log File Download
- /ootbee-support-tools/log4j-log-file/*
-
-
-
- OOTBee Support Tools - Log ZIP File Download
- /ootbee-support-tools/log4j-log-files.zip
-
-
-
\ No newline at end of file