alternative servlet method, tested with wiki

may become the future method to store servlets
pull/533/head
Michael Peter Christen 2 years ago
parent d23dea2642
commit 48fcf3b3b5

@ -1,3 +1,4 @@
package net.yacy.htroot;
// Wiki.java // Wiki.java
// ----------------------- // -----------------------
// part of the AnomicHTTPD caching proxy // part of the AnomicHTTPD caching proxy

@ -144,45 +144,45 @@ public class YaCyDefaultServlet extends HttpServlet {
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public void init() throws UnavailableException { public void init() throws UnavailableException {
Switchboard sb = Switchboard.getSwitchboard(); final Switchboard sb = Switchboard.getSwitchboard();
_htDocsPath = sb.htDocsPath; this._htDocsPath = sb.htDocsPath;
_htLocalePath = sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"); this._htLocalePath = sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot");
_servletContext = getServletContext(); this._servletContext = getServletContext();
_mimeTypes = new MimeTypes(); this._mimeTypes = new MimeTypes();
String tmpstr = this.getServletContext().getInitParameter("welcomeFile"); final String tmpstr = this.getServletContext().getInitParameter("welcomeFile");
if (tmpstr == null) { if (tmpstr == null) {
_welcomes = HTTPDFileHandler.defaultFiles; this._welcomes = HTTPDFileHandler.defaultFiles;
} else { } else {
_welcomes = new String[]{tmpstr,"index.html"}; this._welcomes = new String[]{tmpstr,"index.html"};
} }
_acceptRanges = getInitBoolean("acceptRanges", _acceptRanges); this._acceptRanges = getInitBoolean("acceptRanges", this._acceptRanges);
_dirAllowed = getInitBoolean("dirAllowed", _dirAllowed); this._dirAllowed = getInitBoolean("dirAllowed", this._dirAllowed);
Resource.setDefaultUseCaches(false); // caching is handled internally (prevent double caching) Resource.setDefaultUseCaches(false); // caching is handled internally (prevent double caching)
String rb = getInitParameter("resourceBase"); final String rb = getInitParameter("resourceBase");
try { try {
if (rb != null) { if (rb != null) {
_resourceBase = Resource.newResource(rb); this._resourceBase = Resource.newResource(rb);
} else { } else {
_resourceBase = Resource.newResource(sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT)); //default this._resourceBase = Resource.newResource(sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT)); //default
} }
} catch (IOException e) { } catch (final IOException e) {
ConcurrentLog.severe("FILEHANDLER", "YaCyDefaultServlet: resource base (htRootPath) missing"); ConcurrentLog.severe("FILEHANDLER", "YaCyDefaultServlet: resource base (htRootPath) missing");
ConcurrentLog.logException(e); ConcurrentLog.logException(e);
throw new UnavailableException(e.toString()); throw new UnavailableException(e.toString());
} }
if (ConcurrentLog.isFine("FILEHANDLER")) { if (ConcurrentLog.isFine("FILEHANDLER")) {
ConcurrentLog.fine("FILEHANDLER","YaCyDefaultServlet: resource base = " + _resourceBase); ConcurrentLog.fine("FILEHANDLER","YaCyDefaultServlet: resource base = " + this._resourceBase);
} }
templateMethodCache = new ConcurrentHashMap<File, SoftReference<Method>>(); this.templateMethodCache = new ConcurrentHashMap<File, SoftReference<Method>>();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected boolean getInitBoolean(String name, boolean dft) { protected boolean getInitBoolean(final String name, final boolean dft) {
String value = getInitParameter(name); final String value = getInitParameter(name);
if (value == null || value.length() == 0) { if (value == null || value.length() == 0) {
return dft; return dft;
} }
@ -202,20 +202,20 @@ public class YaCyDefaultServlet extends HttpServlet {
* @param pathInContext The path to find a resource for. * @param pathInContext The path to find a resource for.
* @return The resource to serve. * @return The resource to serve.
*/ */
public Resource getResource(String pathInContext) { public Resource getResource(final String pathInContext) {
Resource r = null; Resource r = null;
try { try {
if (_resourceBase != null) { if (this._resourceBase != null) {
r = _resourceBase.addPath(pathInContext); r = this._resourceBase.addPath(pathInContext);
} else { } else {
URL u = _servletContext.getResource(pathInContext); final URL u = this._servletContext.getResource(pathInContext);
r = Resource.newResource(u); r = Resource.newResource(u);
} }
if (ConcurrentLog.isFine("FILEHANDLER")) { if (ConcurrentLog.isFine("FILEHANDLER")) {
ConcurrentLog.fine("FILEHANDLER","YaCyDefaultServlet: Resource " + pathInContext + "=" + r); ConcurrentLog.fine("FILEHANDLER","YaCyDefaultServlet: Resource " + pathInContext + "=" + r);
} }
} catch (IOException e) { } catch (final IOException e) {
// ConcurrentLog.logException(e); // ConcurrentLog.logException(e);
} }
@ -223,17 +223,17 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected boolean hasDefinedRange(Enumeration<String> reqRanges) { protected boolean hasDefinedRange(final Enumeration<String> reqRanges) {
return (reqRanges != null && reqRanges.hasMoreElements()); return (reqRanges != null && reqRanges.hasMoreElements());
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
String pathInfo; String pathInfo;
Enumeration<String> reqRanges = null; Enumeration<String> reqRanges = null;
boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; final boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
if (included) { if (included) {
pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO); pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
if (pathInfo == null) { if (pathInfo == null) {
@ -250,7 +250,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
String pathInContext = pathInfo == null ? "/" : pathInfo; // this is the path of the resource in _resourceBase (= path within htroot respective htDocs) String pathInContext = pathInfo == null ? "/" : pathInfo; // this is the path of the resource in _resourceBase (= path within htroot respective htDocs)
boolean endsWithSlash = pathInContext.endsWith(URIUtil.SLASH); final boolean endsWithSlash = pathInContext.endsWith(URIUtil.SLASH);
// Find the resource // Find the resource
Resource resource = null; Resource resource = null;
@ -262,21 +262,26 @@ public class YaCyDefaultServlet extends HttpServlet {
if (reqRanges == null && !endsWithSlash) { if (reqRanges == null && !endsWithSlash) {
final int p = pathInContext.lastIndexOf('.'); final int p = pathInContext.lastIndexOf('.');
if (p >= 0) { if (p >= 0) {
String pathofClass = pathInContext.substring(0, p) + ".class"; final Class<?> servletClass = rewriteClass(pathInContext);
Resource classresource = _resourceBase.addPath(pathofClass); if (servletClass != null) {
hasClass = true;
} else {
final String pathofClass = pathInContext.substring(0, p) + ".class";
final Resource classresource = this._resourceBase.addPath(pathofClass);
// Does a class resource exist? // Does a class resource exist?
if (classresource != null && classresource.exists() && !classresource.isDirectory()) { if (classresource != null && classresource.exists() && !classresource.isDirectory()) {
hasClass = true; hasClass = true;
} }
} }
} }
}
// find resource // find resource
resource = getResource(pathInContext); resource = getResource(pathInContext);
if (!hasClass && (resource == null || !resource.exists()) && !pathInContext.contains("..")) { if (!hasClass && (resource == null || !resource.exists()) && !pathInContext.contains("..")) {
// try to get this in the alternative htDocsPath // try to get this in the alternative htDocsPath
resource = Resource.newResource(new File(_htDocsPath, pathInContext)); resource = Resource.newResource(new File(this._htDocsPath, pathInContext));
} }
if (ConcurrentLog.isFine("FILEHANDLER")) { if (ConcurrentLog.isFine("FILEHANDLER")) {
@ -291,12 +296,12 @@ public class YaCyDefaultServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_NOT_FOUND); response.sendError(HttpServletResponse.SC_NOT_FOUND);
} else if (!resource.isDirectory()) { } else if (!resource.isDirectory()) {
if (endsWithSlash && pathInContext.length() > 1) { if (endsWithSlash && pathInContext.length() > 1) {
String q = request.getQueryString(); final String q = request.getQueryString();
pathInContext = pathInContext.substring(0, pathInContext.length() - 1); pathInContext = pathInContext.substring(0, pathInContext.length() - 1);
if (q != null && q.length() != 0) { if (q != null && q.length() != 0) {
pathInContext += "?" + q; pathInContext += "?" + q;
} }
response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(_servletContext.getContextPath(), pathInContext))); response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(this._servletContext.getContextPath(), pathInContext)));
} else { } else {
if (hasClass) { // this is a YaCy servlet, handle the template if (hasClass) { // this is a YaCy servlet, handle the template
handleTemplate(pathInfo, request, response); handleTemplate(pathInfo, request, response);
@ -310,15 +315,15 @@ public class YaCyDefaultServlet extends HttpServlet {
String welcome; String welcome;
if (!endsWithSlash) { if (!endsWithSlash) {
StringBuffer buf = request.getRequestURL(); final StringBuffer buf = request.getRequestURL();
synchronized (buf) { synchronized (buf) {
int param = buf.lastIndexOf(";"); final int param = buf.lastIndexOf(";");
if (param < 0) { if (param < 0) {
buf.append('/'); buf.append('/');
} else { } else {
buf.insert(param, '/'); buf.insert(param, '/');
} }
String q = request.getQueryString(); final String q = request.getQueryString();
if (q != null && q.length() != 0) { if (q != null && q.length() != 0) {
buf.append('?'); buf.append('?');
buf.append(q); buf.append(q);
@ -331,7 +336,7 @@ public class YaCyDefaultServlet extends HttpServlet {
ConcurrentLog.fine("FILEHANDLER","welcome={}" + welcome); ConcurrentLog.fine("FILEHANDLER","welcome={}" + welcome);
// Forward to the index // Forward to the index
RequestDispatcher dispatcher = request.getRequestDispatcher(welcome); final RequestDispatcher dispatcher = request.getRequestDispatcher(welcome);
if (dispatcher != null) { if (dispatcher != null) {
if (included) { if (included) {
dispatcher.include(request, response); dispatcher.include(request, response);
@ -345,7 +350,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} }
} }
} catch (IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
ConcurrentLog.logException(e); ConcurrentLog.logException(e);
if (!response.isCommitted()) { if (!response.isCommitted()) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
@ -359,7 +364,7 @@ public class YaCyDefaultServlet extends HttpServlet {
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
doGet(request, response); doGet(request, response);
} }
@ -369,13 +374,13 @@ public class YaCyDefaultServlet extends HttpServlet {
* @see javax.servlet.http.HttpServlet#doTrace(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) * @see javax.servlet.http.HttpServlet#doTrace(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/ */
@Override @Override
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doTrace(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) protected void doOptions(final HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException { throws ServletException, IOException {
resp.setHeader("Allow", "GET,HEAD,POST,OPTIONS"); resp.setHeader("Allow", "GET,HEAD,POST,OPTIONS");
} }
@ -388,13 +393,13 @@ public class YaCyDefaultServlet extends HttpServlet {
* @param pathInContext path in context * @param pathInContext path in context
* @return The path of the matching welcome file in context or null. * @return The path of the matching welcome file in context or null.
*/ */
protected String getWelcomeFile(String pathInContext) { protected String getWelcomeFile(final String pathInContext) {
if (_welcomes == null) { if (this._welcomes == null) {
return null; return null;
} }
for (String _welcome : _welcomes) { for (final String _welcome : this._welcomes) {
String welcome_in_context = URIUtil.addPaths(pathInContext, _welcome); final String welcome_in_context = URIUtil.addPaths(pathInContext, _welcome);
Resource welcome = getResource(welcome_in_context); final Resource welcome = getResource(welcome_in_context);
if (welcome != null && welcome.exists()) { if (welcome != null && welcome.exists()) {
return _welcome; return _welcome;
} }
@ -405,15 +410,15 @@ public class YaCyDefaultServlet extends HttpServlet {
/* Check modification date headers. /* Check modification date headers.
* send a 304 response instead of content if not modified since * send a 304 response instead of content if not modified since
*/ */
protected boolean passConditionalHeaders(HttpServletRequest request, HttpServletResponse response, Resource resource) protected boolean passConditionalHeaders(final HttpServletRequest request, final HttpServletResponse response, final Resource resource)
throws IOException { throws IOException {
try { try {
if (!request.getMethod().equals(HttpMethod.HEAD.asString())) { if (!request.getMethod().equals(HttpMethod.HEAD.asString())) {
String ifms = request.getHeader(HttpHeader.IF_MODIFIED_SINCE.asString()); final String ifms = request.getHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
if (ifms != null) { if (ifms != null) {
long ifmsl = request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.asString()); final long ifmsl = request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
if (ifmsl != -1) { if (ifmsl != -1) {
if (resource.lastModified() / 1000 <= ifmsl / 1000) { if (resource.lastModified() / 1000 <= ifmsl / 1000) {
response.reset(); response.reset();
@ -425,7 +430,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
// Parse the if[un]modified dates and compare to resource // Parse the if[un]modified dates and compare to resource
long date = request.getDateHeader(HttpHeader.IF_UNMODIFIED_SINCE.asString()); final long date = request.getDateHeader(HttpHeader.IF_UNMODIFIED_SINCE.asString());
if (date != -1) { if (date != -1) {
if (resource.lastModified() / 1000 > date / 1000) { if (resource.lastModified() / 1000 > date / 1000) {
@ -434,7 +439,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} }
} }
} catch (IllegalArgumentException iae) { } catch (final IllegalArgumentException iae) {
if (!response.isCommitted()) { if (!response.isCommitted()) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, iae.getMessage()); response.sendError(HttpServletResponse.SC_BAD_REQUEST, iae.getMessage());
return false; return false;
@ -445,25 +450,25 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
protected void sendDirectory(HttpServletRequest request, protected void sendDirectory(final HttpServletRequest request,
HttpServletResponse response, final HttpServletResponse response,
Resource resource, final Resource resource,
String pathInContext) final String pathInContext)
throws IOException { throws IOException {
if (!_dirAllowed) { if (!this._dirAllowed) {
response.sendError(HttpServletResponse.SC_FORBIDDEN); response.sendError(HttpServletResponse.SC_FORBIDDEN);
return; return;
} }
String base = URIUtil.addPaths(request.getRequestURI(), URIUtil.SLASH); final String base = URIUtil.addPaths(request.getRequestURI(), URIUtil.SLASH);
String dir = resource.getListHTML(base, pathInContext.length() > 1, null); final String dir = resource.getListHTML(base, pathInContext.length() > 1, null);
if (dir == null) { if (dir == null) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "No directory"); response.sendError(HttpServletResponse.SC_FORBIDDEN, "No directory");
return; return;
} }
byte[] data = dir.getBytes(StandardCharsets.UTF_8); final byte[] data = dir.getBytes(StandardCharsets.UTF_8);
response.setContentType(MimeTypes.Type.TEXT_HTML_UTF_8.asString()); response.setContentType(MimeTypes.Type.TEXT_HTML_UTF_8.asString());
response.setContentLength(data.length); response.setContentLength(data.length);
response.setHeader(HeaderFramework.CACHE_CONTROL, "no-cache, no-store"); response.setHeader(HeaderFramework.CACHE_CONTROL, "no-cache, no-store");
@ -483,11 +488,11 @@ public class YaCyDefaultServlet extends HttpServlet {
* @param reqRanges * @param reqRanges
* @throws IOException * @throws IOException
*/ */
protected void sendData(HttpServletRequest request, protected void sendData(final HttpServletRequest request,
HttpServletResponse response, final HttpServletResponse response,
boolean include, final boolean include,
Resource resource, final Resource resource,
Enumeration<String> reqRanges) final Enumeration<String> reqRanges)
throws IOException { throws IOException {
final long content_length = resource.length(); final long content_length = resource.length();
@ -496,7 +501,7 @@ public class YaCyDefaultServlet extends HttpServlet {
OutputStream out; OutputStream out;
try { try {
out = response.getOutputStream(); out = response.getOutputStream();
} catch (IllegalStateException e) { } catch (final IllegalStateException e) {
out = new WriterOutputStream(response.getWriter()); out = new WriterOutputStream(response.getWriter());
} }
@ -541,7 +546,7 @@ public class YaCyDefaultServlet extends HttpServlet {
// since were here now), send that range with a 216 response // since were here now), send that range with a 216 response
if (ranges.size() == 1) { if (ranges.size() == 1) {
final InclusiveByteRange singleSatisfiableRange = ranges.iterator().next(); final InclusiveByteRange singleSatisfiableRange = ranges.iterator().next();
long singleLength = singleSatisfiableRange.getSize(); final long singleLength = singleSatisfiableRange.getSize();
writeHeaders(response, resource, singleLength); writeHeaders(response, resource, singleLength);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.setHeader(HttpHeader.CONTENT_RANGE.asString(), response.setHeader(HttpHeader.CONTENT_RANGE.asString(),
@ -556,11 +561,11 @@ public class YaCyDefaultServlet extends HttpServlet {
// content-length header // content-length header
// //
writeHeaders(response, resource, -1); writeHeaders(response, resource, -1);
String mimetype = response.getContentType(); final String mimetype = response.getContentType();
if (mimetype == null) { if (mimetype == null) {
ConcurrentLog.warn("FILEHANDLER","YaCyDefaultServlet: Unknown mimetype for " + request.getRequestURI()); ConcurrentLog.warn("FILEHANDLER","YaCyDefaultServlet: Unknown mimetype for " + request.getRequestURI());
} }
MultiPartOutputStream multi = new MultiPartOutputStream(out); final MultiPartOutputStream multi = new MultiPartOutputStream(out);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
// If the request has a "Request-Range" header then we need to // If the request has a "Request-Range" header then we need to
@ -579,9 +584,9 @@ public class YaCyDefaultServlet extends HttpServlet {
// calculate the content-length // calculate the content-length
int length = 0; int length = 0;
String[] header = new String[ranges.size()]; final String[] header = new String[ranges.size()];
for (int i = 0; i < ranges.size(); i++) { for (int i = 0; i < ranges.size(); i++) {
InclusiveByteRange ibr = ranges.get(i); final InclusiveByteRange ibr = ranges.get(i);
header[i] = ibr.toHeaderRangeString(content_length); header[i] = ibr.toHeaderRangeString(content_length);
length += length +=
((i > 0) ? 2 : 0) ((i > 0) ? 2 : 0)
@ -595,11 +600,11 @@ public class YaCyDefaultServlet extends HttpServlet {
response.setContentLength(length); response.setContentLength(length);
for (int i = 0; i < ranges.size(); i++) { for (int i = 0; i < ranges.size(); i++) {
InclusiveByteRange ibr = ranges.get(i); final InclusiveByteRange ibr = ranges.get(i);
multi.startPart(mimetype, new String[]{HeaderFramework.CONTENT_RANGE + ": " + header[i]}); multi.startPart(mimetype, new String[]{HeaderFramework.CONTENT_RANGE + ": " + header[i]});
long start = ibr.getFirst(); final long start = ibr.getFirst();
long size = ibr.getSize(); final long size = ibr.getSize();
if (in != null) { if (in != null) {
// Handle non cached resource // Handle non cached resource
if (start < pos) { if (start < pos) {
@ -626,10 +631,10 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected void writeHeaders(HttpServletResponse response, Resource resource, long count) { protected void writeHeaders(final HttpServletResponse response, final Resource resource, final long count) {
if (response.getContentType() == null) { if (response.getContentType() == null) {
final String extensionmime; final String extensionmime;
if ((extensionmime = _mimeTypes.getMimeByExtension(resource.getName())) != null) { if ((extensionmime = this._mimeTypes.getMimeByExtension(resource.getName())) != null) {
response.setContentType(extensionmime); response.setContentType(extensionmime);
} }
} }
@ -649,7 +654,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} }
if (_acceptRanges) { if (this._acceptRanges) {
response.setHeader(HeaderFramework.ACCEPT_RANGES, "bytes"); response.setHeader(HeaderFramework.ACCEPT_RANGES, "bytes");
} }
} }
@ -659,6 +664,10 @@ public class YaCyDefaultServlet extends HttpServlet {
return rewriteMethod(targetClass).invoke(null, new Object[]{request, args, Switchboard.getSwitchboard()}); // add switchboard return rewriteMethod(targetClass).invoke(null, new Object[]{request, args, Switchboard.getSwitchboard()}); // add switchboard
} }
protected Object invokeServlet(final Class<?> targetClass, final RequestHeader request, final serverObjects args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
return rewriteMethod(targetClass).invoke(null, new Object[]{request, args, Switchboard.getSwitchboard()}); // add switchboard
}
/** /**
* Returns the URL base for this peer, determined from request HTTP header "Host" when present. Use this when absolute URL rendering is required, * Returns the URL base for this peer, determined from request HTTP header "Host" when present. Use this when absolute URL rendering is required,
* otherwise relative URLs should be preferred.<br/> * otherwise relative URLs should be preferred.<br/>
@ -713,8 +722,8 @@ public class YaCyDefaultServlet extends HttpServlet {
return protocol + "://" + hostAndPort; return protocol + "://" + hostAndPort;
} }
private RequestHeader generateLegacyRequestHeader(HttpServletRequest request, String target, String targetExt) { private RequestHeader generateLegacyRequestHeader(final HttpServletRequest request, final String target, final String targetExt) {
RequestHeader legacyRequestHeader = new RequestHeader(request); final RequestHeader legacyRequestHeader = new RequestHeader(request);
legacyRequestHeader.put(HeaderFramework.CONNECTION_PROP_PATH, target); // target may contain a server side include (SSI) legacyRequestHeader.put(HeaderFramework.CONNECTION_PROP_PATH, target); // target may contain a server side include (SSI)
legacyRequestHeader.put(HeaderFramework.CONNECTION_PROP_EXT, targetExt); legacyRequestHeader.put(HeaderFramework.CONNECTION_PROP_EXT, targetExt);
@ -731,22 +740,22 @@ public class YaCyDefaultServlet extends HttpServlet {
*/ */
public File getLocalizedFile(final String path, final String localeSelection) throws IOException { public File getLocalizedFile(final String path, final String localeSelection) throws IOException {
if (!(localeSelection.equals("default"))) { if (!(localeSelection.equals("default"))) {
final File localePath = new File(_htLocalePath, localeSelection + '/' + path); final File localePath = new File(this._htLocalePath, localeSelection + '/' + path);
if (localePath.exists()) { if (localePath.exists()) {
return localePath; // avoid "NoSuchFile" troubles if the "localeSelection" is misspelled return localePath; // avoid "NoSuchFile" troubles if the "localeSelection" is misspelled
} }
} }
File docsPath = new File(_htDocsPath, path); final File docsPath = new File(this._htDocsPath, path);
if (docsPath.exists()) { if (docsPath.exists()) {
return docsPath; return docsPath;
} }
return _resourceBase.addPath(path).getFile(); return this._resourceBase.addPath(path).getFile();
} }
protected File rewriteClassFile(final File template) { protected File rewriteClassFile(final File servletFile) {
try { try {
String f = template.getCanonicalPath(); String f = servletFile.getCanonicalPath();
final int p = f.lastIndexOf('.'); final int p = f.lastIndexOf('.');
if (p < 0) { if (p < 0) {
return null; return null;
@ -762,15 +771,32 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} }
protected Class<?> rewriteClass(String target) {
assert target.charAt(0) == '/';
try {
final int p = target.lastIndexOf('.');
if (p < 0) {
return null;
}
target = target.substring(1, p);
final Class<?> servletClass = Class.forName("net.yacy.htroot." + target);
return servletClass;
} catch (final ClassNotFoundException e) {
return null;
}
}
protected Method rewriteMethod(final File classFile) throws InvocationTargetException { protected Method rewriteMethod(final File classFile) throws InvocationTargetException {
Method m = null; Method m = null;
// now make a class out of the stream // now make a class out of the stream
try { try {
final SoftReference<Method> ref = templateMethodCache.get(classFile); final SoftReference<Method> ref = this.templateMethodCache.get(classFile);
if (ref != null) { if (ref != null) {
m = ref.get(); m = ref.get();
if (m == null) { if (m == null) {
templateMethodCache.remove(classFile); this.templateMethodCache.remove(classFile);
} else { } else {
return m; return m;
} }
@ -785,10 +811,10 @@ public class YaCyDefaultServlet extends HttpServlet {
m = c.getMethod("respond", params); m = c.getMethod("respond", params);
if (MemoryControl.shortStatus()) { if (MemoryControl.shortStatus()) {
templateMethodCache.clear(); this.templateMethodCache.clear();
} else { } else {
// store the method into the cache // store the method into the cache
templateMethodCache.put(classFile, new SoftReference<Method>(m)); this.templateMethodCache.put(classFile, new SoftReference<Method>(m));
} }
} catch (final ClassNotFoundException e) { } catch (final ClassNotFoundException e) {
ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: class " + classFile + " is missing:" + e.getMessage()); ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: class " + classFile + " is missing:" + e.getMessage());
@ -800,6 +826,21 @@ public class YaCyDefaultServlet extends HttpServlet {
return m; return m;
} }
protected Method rewriteMethod(final Class<?> rewriteClass) throws InvocationTargetException {
Method m = null;
try {
final Class<?>[] params = (Class<?>[]) Array.newInstance(Class.class, 3);
params[0]= RequestHeader.class;
params[1] = serverObjects.class;
params[2] = serverSwitch.class;
m = rewriteClass.getMethod("respond", params);
} catch (final NoSuchMethodException e) {
ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: method 'respond' not found in class " + rewriteClass.getName() + ": " + e.getMessage());
throw new InvocationTargetException(e, "method 'respond' not found in class " + rewriteClass.getName() + ": " + e.getMessage());
}
return m;
}
/** /**
* Handles a YaCy servlet template, reads the template and replaces the template * Handles a YaCy servlet template, reads the template and replaces the template
* items with actual values. Because of supported server side includes target * items with actual values. Because of supported server side includes target
@ -811,23 +852,24 @@ public class YaCyDefaultServlet extends HttpServlet {
* @throws IOException * @throws IOException
* @throws ServletException * @throws ServletException
*/ */
protected void handleTemplate(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { protected void handleTemplate(final String target, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
Switchboard sb = Switchboard.getSwitchboard(); final Switchboard sb = Switchboard.getSwitchboard();
String localeSelection = sb.getConfig("locale.language", "browser"); String localeSelection = sb.getConfig("locale.language", "browser");
if (localeSelection.endsWith("browser")) { if (localeSelection.endsWith("browser")) {
String lng = request.getLocale().getLanguage(); final String lng = request.getLocale().getLanguage();
if (lng.equalsIgnoreCase("en")) { // because en is handled as "default" in localizer if (lng.equalsIgnoreCase("en")) { // because en is handled as "default" in localizer
localeSelection = "default"; localeSelection = "default";
} else { } else {
localeSelection = lng; localeSelection = lng;
} }
} }
File targetFile = getLocalizedFile(target, localeSelection); final File targetLocalizedFile = getLocalizedFile(target, localeSelection);
File targetClass = rewriteClassFile(_resourceBase.addPath(target).getFile()); final File targetClassFile = rewriteClassFile(this._resourceBase.addPath(target).getFile());
String targetExt = target.substring(target.lastIndexOf('.') + 1); final Class<?> targetClass = rewriteClass(target);
final String targetExt = target.substring(target.lastIndexOf('.') + 1);
long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
if (target.endsWith(".css")) { if (target.endsWith(".css")) {
response.setDateHeader(HeaderFramework.LAST_MODIFIED, now); response.setDateHeader(HeaderFramework.LAST_MODIFIED, now);
response.setDateHeader(HeaderFramework.EXPIRES, now + 3600000); // expires in 1 hour (which is still often, others use 1 week, month or year) response.setDateHeader(HeaderFramework.EXPIRES, now + 3600000); // expires in 1 hour (which is still often, others use 1 week, month or year)
@ -846,15 +888,15 @@ public class YaCyDefaultServlet extends HttpServlet {
response.setHeader(HeaderFramework.CORS_ALLOW_ORIGIN, "*"); response.setHeader(HeaderFramework.CORS_ALLOW_ORIGIN, "*");
} }
if ((targetClass != null)) { if ((targetClassFile != null || targetClass != null)) {
serverObjects args = new serverObjects(); final serverObjects args = new serverObjects();
Enumeration<String> argNames = request.getParameterNames(); // on ssi jetty dispatcher merged local ssi query parameters final Enumeration<String> argNames = request.getParameterNames(); // on ssi jetty dispatcher merged local ssi query parameters
while (argNames.hasMoreElements()) { while (argNames.hasMoreElements()) {
String argName = argNames.nextElement(); final String argName = argNames.nextElement();
// standard attributes are just pushed as string // standard attributes are just pushed as string
args.put(argName, request.getParameter(argName)); args.put(argName, request.getParameter(argName));
} }
RequestHeader legacyRequestHeader = generateLegacyRequestHeader(request, target, targetExt); final RequestHeader legacyRequestHeader = generateLegacyRequestHeader(request, target, targetExt);
// add multipart-form fields to parameter // add multipart-form fields to parameter
if (ServletFileUpload.isMultipartContent(request)) { if (ServletFileUpload.isMultipartContent(request)) {
parseMultipart(request, args); parseMultipart(request, args);
@ -864,11 +906,19 @@ public class YaCyDefaultServlet extends HttpServlet {
try { try {
if (args.isEmpty()) { if (args.isEmpty()) {
// yacy servlets typically test for args != null (but not for args .isEmpty()) // yacy servlets typically test for args != null (but not for args .isEmpty())
if (targetClass == null) {
tmp = invokeServlet(targetClassFile, legacyRequestHeader, null);
} else {
tmp = invokeServlet(targetClass, legacyRequestHeader, null); tmp = invokeServlet(targetClass, legacyRequestHeader, null);
}
} else {
if (targetClass == null) {
tmp = invokeServlet(targetClassFile, legacyRequestHeader, args);
} else { } else {
tmp = invokeServlet(targetClass, legacyRequestHeader, args); tmp = invokeServlet(targetClass, legacyRequestHeader, args);
} }
} catch(InvocationTargetException e) { }
} catch(final InvocationTargetException e) {
if(e.getCause() instanceof InvalidURLLicenceException) { if(e.getCause() instanceof InvalidURLLicenceException) {
/* A non authorized user is trying to fetch a image with a bad or already released license code */ /* A non authorized user is trying to fetch a image with a bad or already released license code */
response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getCause().getMessage()); response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getCause().getMessage());
@ -893,10 +943,10 @@ public class YaCyDefaultServlet extends HttpServlet {
return; return;
} }
ConcurrentLog.logException(e); ConcurrentLog.logException(e);
throw new ServletException(targetFile.getAbsolutePath()); throw new ServletException(targetLocalizedFile.getAbsolutePath());
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
ConcurrentLog.logException(e); ConcurrentLog.logException(e);
throw new ServletException(targetFile.getAbsolutePath()); throw new ServletException(targetLocalizedFile.getAbsolutePath());
} }
if (tmp instanceof RasterPlotter || tmp instanceof EncodedImage || tmp instanceof Image) { if (tmp instanceof RasterPlotter || tmp instanceof EncodedImage || tmp instanceof Image) {
@ -967,10 +1017,10 @@ public class YaCyDefaultServlet extends HttpServlet {
if (templatePatterns.getOutgoingHeader() != null) { if (templatePatterns.getOutgoingHeader() != null) {
// handle responseHeader entries set by servlet // handle responseHeader entries set by servlet
ResponseHeader tmpouthdr = templatePatterns.getOutgoingHeader(); final ResponseHeader tmpouthdr = templatePatterns.getOutgoingHeader();
for (String hdrkey : tmpouthdr.keySet()) { for (final String hdrkey : tmpouthdr.keySet()) {
if (!HeaderFramework.STATUS_CODE.equals(hdrkey)) { // skip default init response status value (not std. ) if (!HeaderFramework.STATUS_CODE.equals(hdrkey)) { // skip default init response status value (not std. )
String val = tmpouthdr.get(hdrkey); final String val = tmpouthdr.get(hdrkey);
if (!response.containsHeader(hdrkey) && val != null) { // to be on the safe side, add only new hdr (mainly used for CORS_ALLOW_ORIGIN) if (!response.containsHeader(hdrkey) && val != null) { // to be on the safe side, add only new hdr (mainly used for CORS_ALLOW_ORIGIN)
response.setHeader(hdrkey, tmpouthdr.get(hdrkey)); response.setHeader(hdrkey, tmpouthdr.get(hdrkey));
} }
@ -978,7 +1028,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
// handle login cookie // handle login cookie
if (tmpouthdr.getCookiesEntries() != null) { if (tmpouthdr.getCookiesEntries() != null) {
for (Cookie c : tmpouthdr.getCookiesEntries()) { for (final Cookie c : tmpouthdr.getCookiesEntries()) {
response.addCookie(c); response.addCookie(c);
} }
} }
@ -1015,7 +1065,7 @@ public class YaCyDefaultServlet extends HttpServlet {
return; return;
} }
if (targetFile.exists() && targetFile.isFile() && targetFile.canRead()) { if (targetLocalizedFile.exists() && targetLocalizedFile.isFile() && targetLocalizedFile.canRead()) {
sb.setConfig(SwitchboardConstants.SERVER_SERVLETS_CALLED, appendPath(sb.getConfig(SwitchboardConstants.SERVER_SERVLETS_CALLED, ""), target)); sb.setConfig(SwitchboardConstants.SERVER_SERVLETS_CALLED, appendPath(sb.getConfig(SwitchboardConstants.SERVER_SERVLETS_CALLED, ""), target));
if (args != null && !args.isEmpty()) { if (args != null && !args.isEmpty()) {
@ -1030,10 +1080,10 @@ public class YaCyDefaultServlet extends HttpServlet {
templatePatterns.put(servletProperties.PEER_STAT_MYTIME, GenericFormatter.SHORT_SECOND_FORMATTER.format()); templatePatterns.put(servletProperties.PEER_STAT_MYTIME, GenericFormatter.SHORT_SECOND_FORMATTER.format());
templatePatterns.put(servletProperties.RELATIVE_BASE, YaCyDefaultServlet.getRelativeBase(target)); templatePatterns.put(servletProperties.RELATIVE_BASE, YaCyDefaultServlet.getRelativeBase(target));
templatePatterns.put(SwitchboardConstants.REFERRER_META_POLICY, sb.getConfig(SwitchboardConstants.REFERRER_META_POLICY, SwitchboardConstants.REFERRER_META_POLICY_DEFAULT)); templatePatterns.put(SwitchboardConstants.REFERRER_META_POLICY, sb.getConfig(SwitchboardConstants.REFERRER_META_POLICY, SwitchboardConstants.REFERRER_META_POLICY_DEFAULT));
Seed myPeer = sb.peers.mySeed(); final Seed myPeer = sb.peers.mySeed();
templatePatterns.put("newpeer", myPeer.getAge() >= 1 ? 0 : 1); templatePatterns.put("newpeer", myPeer.getAge() >= 1 ? 0 : 1);
templatePatterns.putHTML("newpeer_peerhash", myPeer.hash); templatePatterns.putHTML("newpeer_peerhash", myPeer.hash);
boolean authorized = sb.adminAuthenticated(legacyRequestHeader) >= 2; final boolean authorized = sb.adminAuthenticated(legacyRequestHeader) >= 2;
templatePatterns.put("authorized", authorized ? 1 : 0); // used in templates and other html (e.g. to display lock/unlock symbol) templatePatterns.put("authorized", authorized ? 1 : 0); // used in templates and other html (e.g. to display lock/unlock symbol)
templatePatterns.put("simpleheadernavbar", sb.getConfig("decoration.simpleheadernavbar", "navbar-default")); templatePatterns.put("simpleheadernavbar", sb.getConfig("decoration.simpleheadernavbar", "navbar-default"));
@ -1041,12 +1091,12 @@ public class YaCyDefaultServlet extends HttpServlet {
// add navigation keys to enable or disable menu items // add navigation keys to enable or disable menu items
templatePatterns.put("navigation-p2p", sb.getConfigBool(SwitchboardConstants.NETWORK_UNIT_DHT, true) || !sb.isRobinsonMode() ? 1 : 0); templatePatterns.put("navigation-p2p", sb.getConfigBool(SwitchboardConstants.NETWORK_UNIT_DHT, true) || !sb.isRobinsonMode() ? 1 : 0);
templatePatterns.put("navigation-p2p_authorized", authorized ? 1 : 0); templatePatterns.put("navigation-p2p_authorized", authorized ? 1 : 0);
String submitted = sb.getConfig("server.servlets.submitted", ""); final String submitted = sb.getConfig("server.servlets.submitted", "");
boolean crawler_enabled = true; /* final boolean crawler_enabled = true; /*
submitted.contains("Crawler_p") || submitted.contains("Crawler_p") ||
submitted.contains("ConfigBasic") || submitted.contains("ConfigBasic") ||
submitted.contains("Load_RSS_p");*/ submitted.contains("Load_RSS_p");*/
boolean advanced_enabled = final boolean advanced_enabled =
crawler_enabled || crawler_enabled ||
submitted.contains("IndexImportMediawiki_p") || submitted.contains("IndexImportMediawiki_p") ||
submitted.contains("CrawlStart"); submitted.contains("CrawlStart");
@ -1059,38 +1109,38 @@ public class YaCyDefaultServlet extends HttpServlet {
templatePatterns.put(SwitchboardConstants.GREETING_IMAGE_ALT, sb.getConfig(SwitchboardConstants.GREETING_IMAGE_ALT, "")); templatePatterns.put(SwitchboardConstants.GREETING_IMAGE_ALT, sb.getConfig(SwitchboardConstants.GREETING_IMAGE_ALT, ""));
templatePatterns.put("clientlanguage", localeSelection); templatePatterns.put("clientlanguage", localeSelection);
String mimeType = Classification.ext2mime(targetExt, MimeTypes.Type.TEXT_HTML.asString()); final String mimeType = Classification.ext2mime(targetExt, MimeTypes.Type.TEXT_HTML.asString());
InputStream fis; InputStream fis;
long fileSize = targetFile.length(); final long fileSize = targetLocalizedFile.length();
if (fileSize <= Math.min(4 * 1024 * 1204, MemoryControl.available() / 100)) { if (fileSize <= Math.min(4 * 1024 * 1204, MemoryControl.available() / 100)) {
// read file completely into ram, avoid that too many files are open at the same time // read file completely into ram, avoid that too many files are open at the same time
fis = new ByteArrayInputStream(FileUtils.read(targetFile)); fis = new ByteArrayInputStream(FileUtils.read(targetLocalizedFile));
} else { } else {
fis = new BufferedInputStream(new FileInputStream(targetFile)); fis = new BufferedInputStream(new FileInputStream(targetLocalizedFile));
} }
// set response header // set response header
response.setContentType(mimeType); response.setContentType(mimeType);
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
ByteArrayOutputStream bas = new ByteArrayOutputStream(4096); final ByteArrayOutputStream bas = new ByteArrayOutputStream(4096);
try { try {
// apply templates // apply templates
TemplateEngine.writeTemplate(targetFile.getName(), fis, bas, templatePatterns); TemplateEngine.writeTemplate(targetLocalizedFile.getName(), fis, bas, templatePatterns);
// handle SSI // handle SSI
parseSSI (bas.toByteArray(),request,response); parseSSI (bas.toByteArray(),request,response);
} finally { } finally {
try { try {
fis.close(); fis.close();
} catch(IOException ignored) { } catch(final IOException ignored) {
ConcurrentLog.warn("FILEHANDLER", "YaCyDefaultServlet: could not close target file " + targetFile.getName()); ConcurrentLog.warn("FILEHANDLER", "YaCyDefaultServlet: could not close target file " + targetLocalizedFile.getName());
} }
try { try {
bas.close(); bas.close();
} catch(IOException ignored) { } catch(final IOException ignored) {
/* Should never happen with a ByteArrayOutputStream */ /* Should never happen with a ByteArrayOutputStream */
} }
} }
@ -1106,7 +1156,7 @@ public class YaCyDefaultServlet extends HttpServlet {
* @return the relative path prefix, eventually empty * @return the relative path prefix, eventually empty
*/ */
protected static String getRelativeBase(String targetPath) { protected static String getRelativeBase(String targetPath) {
StringBuilder relativeBase = new StringBuilder(); final StringBuilder relativeBase = new StringBuilder();
if(targetPath != null) { if(targetPath != null) {
/* Normalize target path : it is relative to htroot, starting with a slash or not */ /* Normalize target path : it is relative to htroot, starting with a slash or not */
if(targetPath.startsWith("/")) { if(targetPath.startsWith("/")) {
@ -1127,7 +1177,7 @@ public class YaCyDefaultServlet extends HttpServlet {
* @param target the query target * @param target the query target
* @param response servlet response to eventually update * @param response servlet response to eventually update
*/ */
private void updateRespHeadersForImages(String target, HttpServletResponse response) { private void updateRespHeadersForImages(final String target, final HttpServletResponse response) {
if (target.equals("/ViewImage.png") || target.equals("/ViewFavicon.png")) { if (target.equals("/ViewImage.png") || target.equals("/ViewFavicon.png")) {
if (response.containsHeader(HeaderFramework.LAST_MODIFIED)) { if (response.containsHeader(HeaderFramework.LAST_MODIFIED)) {
response.getHeaders(HeaderFramework.LAST_MODIFIED).clear(); // if this field is present, the reload-time is a 10% fraction of ttl and other caching headers do not work response.getHeaders(HeaderFramework.LAST_MODIFIED).clear(); // if this field is present, the reload-time is a 10% fraction of ttl and other caching headers do not work
@ -1146,12 +1196,12 @@ public class YaCyDefaultServlet extends HttpServlet {
* @param inStream * @param inStream
* @throws IOException when a read/write error occured. * @throws IOException when a read/write error occured.
*/ */
private void writeInputStream(HttpServletResponse response, String targetExt, InputStream inStream) private void writeInputStream(final HttpServletResponse response, final String targetExt, final InputStream inStream)
throws IOException { throws IOException {
final String mimeType = Classification.ext2mime(targetExt, MimeTypes.Type.TEXT_HTML.asString()); final String mimeType = Classification.ext2mime(targetExt, MimeTypes.Type.TEXT_HTML.asString());
response.setContentType(mimeType); response.setContentType(mimeType);
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
byte[] buffer = new byte[4096]; final byte[] buffer = new byte[4096];
int l, size = 0; int l, size = 0;
try { try {
while ((l = inStream.read(buffer)) > 0) { while ((l = inStream.read(buffer)) > 0) {
@ -1159,7 +1209,7 @@ public class YaCyDefaultServlet extends HttpServlet {
size += l; size += l;
} }
response.setContentLength(size); response.setContentLength(size);
} catch(IOException e){ } catch(final IOException e){
/** No need to log full stack trace (in most cases resource is not available because of a network error) */ /** No need to log full stack trace (in most cases resource is not available because of a network error) */
ConcurrentLog.fine("FILEHANDLER", "YaCyDefaultServlet: resource content stream could not be written to response."); ConcurrentLog.fine("FILEHANDLER", "YaCyDefaultServlet: resource content stream could not be written to response.");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
@ -1167,7 +1217,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} finally { } finally {
try { try {
inStream.close(); inStream.close();
} catch(IOException ignored) { } catch(final IOException ignored) {
} }
} }
} }
@ -1179,7 +1229,7 @@ public class YaCyDefaultServlet extends HttpServlet {
* @param path path to be appended * @param path path to be appended
* @return comma separated string of pathes including param path * @return comma separated string of pathes including param path
*/ */
private String appendPath(String proplist, String path) { private String appendPath(final String proplist, final String path) {
if (proplist.length() == 0) return path; if (proplist.length() == 0) return path;
if (proplist.contains(path)) return proplist; if (proplist.contains(path)) return proplist;
return proplist + "," + path; return proplist + "," + path;
@ -1188,9 +1238,9 @@ public class YaCyDefaultServlet extends HttpServlet {
/** /**
* parse SSI line and include resource (<!--#include virtual="file.html" -->) * parse SSI line and include resource (<!--#include virtual="file.html" -->)
*/ */
protected void parseSSI(final byte[] in, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { protected void parseSSI(final byte[] in, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
ByteBuffer buffer = new ByteBuffer(in); final ByteBuffer buffer = new ByteBuffer(in);
OutputStream out = response.getOutputStream(); final OutputStream out = response.getOutputStream();
final byte[] inctxt ="<!--#include virtual=\"".getBytes(); final byte[] inctxt ="<!--#include virtual=\"".getBytes();
int offset = 0; int offset = 0;
int p = buffer.indexOf(inctxt, offset); int p = buffer.indexOf(inctxt, offset);
@ -1202,10 +1252,10 @@ public class YaCyDefaultServlet extends HttpServlet {
final int rightquote = buffer.indexOf("\"".getBytes(), p + 23); final int rightquote = buffer.indexOf("\"".getBytes(), p + 23);
if (rightquote > 0 && rightquote < end) { if (rightquote > 0 && rightquote < end) {
final String path = buffer.toString(p + 22, rightquote - p - 22); final String path = buffer.toString(p + 22, rightquote - p - 22);
RequestDispatcher dispatcher = request.getRequestDispatcher(path); final RequestDispatcher dispatcher = request.getRequestDispatcher(path);
try { try {
dispatcher.include(request, response); dispatcher.include(request, response);
} catch (IOException ex) { } catch (final IOException ex) {
if (path.indexOf("yacysearch") < 0) ConcurrentLog.warn("FILEHANDLER", "YaCyDefaultServlet: parseSSI dispatcher problem - " + ex.getMessage() + ": " + path); if (path.indexOf("yacysearch") < 0) ConcurrentLog.warn("FILEHANDLER", "YaCyDefaultServlet: parseSSI dispatcher problem - " + ex.getMessage() + ": " + path);
// this is probably a time-out; it may occur during search requests; for search requests we consider that normal // this is probably a time-out; it may occur during search requests; for search requests we consider that normal
} }
@ -1242,16 +1292,16 @@ public class YaCyDefaultServlet extends HttpServlet {
if (!MemoryControl.request(request.getContentLength() * 3, false)) { if (!MemoryControl.request(request.getContentLength() * 3, false)) {
throw new IOException("not enough memory available for request. request.getContentLength() = " + request.getContentLength() + ", MemoryControl.available() = " + MemoryControl.available()); throw new IOException("not enough memory available for request. request.getContentLength() = " + request.getContentLength() + ", MemoryControl.available() = " + MemoryControl.available());
} }
ServletFileUpload upload = new ServletFileUpload(DISK_FILE_ITEM_FACTORY); final ServletFileUpload upload = new ServletFileUpload(DISK_FILE_ITEM_FACTORY);
upload.setFileSizeMax(SIZE_FILE_THRESHOLD); upload.setFileSizeMax(SIZE_FILE_THRESHOLD);
try { try {
// Parse the request to get form field items // Parse the request to get form field items
List<FileItem> fileItems = upload.parseRequest(request); final List<FileItem> fileItems = upload.parseRequest(request);
// Process the uploaded file items // Process the uploaded file items
Iterator<FileItem> i = fileItems.iterator(); final Iterator<FileItem> i = fileItems.iterator();
final BlockingQueue<Map.Entry<String, byte[]>> files = new LinkedBlockingQueue<>(); final BlockingQueue<Map.Entry<String, byte[]>> files = new LinkedBlockingQueue<>();
while (i.hasNext()) { while (i.hasNext()) {
FileItem item = i.next(); final FileItem item = i.next();
if (item.isFormField()) { if (item.isFormField()) {
// simple text // simple text
if (item.getContentType() == null || !item.getContentType().contains("charset")) { if (item.getContentType() == null || !item.getContentType().contains("charset")) {
@ -1268,21 +1318,21 @@ public class YaCyDefaultServlet extends HttpServlet {
try { try {
filecontent = item.getInputStream(); filecontent = item.getInputStream();
files.put(new AbstractMap.SimpleEntry<String, byte[]>(item.getFieldName(), FileUtils.read(filecontent))); files.put(new AbstractMap.SimpleEntry<String, byte[]>(item.getFieldName(), FileUtils.read(filecontent)));
} catch (IOException e) { } catch (final IOException e) {
ConcurrentLog.info("FILEHANDLER", e.getMessage()); ConcurrentLog.info("FILEHANDLER", e.getMessage());
} finally { } finally {
if (filecontent != null) try {filecontent.close();} catch (IOException e) {ConcurrentLog.info("FILEHANDLER", e.getMessage());} if (filecontent != null) try {filecontent.close();} catch (final IOException e) {ConcurrentLog.info("FILEHANDLER", e.getMessage());}
} }
} }
} }
if (files.size() <= 1) { // TODO: should include additonal checks to limit parameter.size below rel. large SIZE_FILE_THRESHOLD if (files.size() <= 1) { // TODO: should include additonal checks to limit parameter.size below rel. large SIZE_FILE_THRESHOLD
for (Map.Entry<String, byte[]> job: files) { // add the file content to parameter fieldname$file for (final Map.Entry<String, byte[]> job: files) { // add the file content to parameter fieldname$file
String n = job.getKey(); final String n = job.getKey();
byte[] v = job.getValue(); final byte[] v = job.getValue();
String filename = args.get(n); final String filename = args.get(n);
if (filename != null && filename.endsWith(".gz")) { if (filename != null && filename.endsWith(".gz")) {
// transform this value into base64 // transform this value into base64
String b64 = Base64Order.standardCoder.encode(v); final String b64 = Base64Order.standardCoder.encode(v);
args.put(n + "$file", b64); args.put(n + "$file", b64);
args.remove(n); args.remove(n);
args.put(n, filename + ".base64"); args.put(n, filename + ".base64");
@ -1292,9 +1342,9 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} else { } else {
// do this concurrently (this would all be superfluous if serverObjects could store byte[] instead only String) // do this concurrently (this would all be superfluous if serverObjects could store byte[] instead only String)
int t = Math.min(files.size(), Runtime.getRuntime().availableProcessors()); final int t = Math.min(files.size(), Runtime.getRuntime().availableProcessors());
final Map.Entry<String, byte[]> POISON = new AbstractMap.SimpleEntry<>(null, null); final Map.Entry<String, byte[]> POISON = new AbstractMap.SimpleEntry<>(null, null);
Thread[] p = new Thread[t]; final Thread[] p = new Thread[t];
for (int j = 0; j < t; j++) { for (int j = 0; j < t; j++) {
files.put(POISON); files.put(POISON);
p[j] = new Thread("YaCyDefaultServlet.parseMultipart-" + j) { p[j] = new Thread("YaCyDefaultServlet.parseMultipart-" + j) {
@ -1302,23 +1352,23 @@ public class YaCyDefaultServlet extends HttpServlet {
public void run() { public void run() {
Map.Entry<String, byte[]> job; Map.Entry<String, byte[]> job;
try {while ((job = files.take()) != POISON) { try {while ((job = files.take()) != POISON) {
String n = job.getKey(); final String n = job.getKey();
byte[] v = job.getValue(); final byte[] v = job.getValue();
String filename = args.get(n); final String filename = args.get(n);
String b64 = Base64Order.standardCoder.encode(v); final String b64 = Base64Order.standardCoder.encode(v);
synchronized (args) { synchronized (args) {
args.put(n + "$file", b64); args.put(n + "$file", b64);
args.remove(n); args.remove(n);
args.put(n, filename + ".base64"); args.put(n, filename + ".base64");
} }
}} catch (InterruptedException e) {} }} catch (final InterruptedException e) {}
} }
}; };
p[j].start(); p[j].start();
} }
for (int j = 0; j < t; j++) p[j].join(); for (int j = 0; j < t; j++) p[j].join();
} }
} catch (Exception ex) { } catch (final Exception ex) {
ConcurrentLog.info("FILEHANDLER", ex.getMessage()); ConcurrentLog.info("FILEHANDLER", ex.getMessage());
} }
} }

Loading…
Cancel
Save