Skip to content
Snippets Groups Projects
Commit fea5ccf9 authored by Grégory Mantelet's avatar Grégory Mantelet
Browse files

[UWS,TAP] Fix HTTPServletResponse.setContentLenght for LONG values.

_This commit completes the GitHub issue #106 ._
parent b981e429
No related branches found
No related tags found
No related merge requests found
......@@ -2,21 +2,22 @@ package tap.resource;
/*
* This file is part of TAPLibrary.
*
*
* TAPLibrary 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.
*
*
* TAPLibrary 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 TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2015-2017 - Astronomisches Rechen Institut (ARI)
*
* Copyright 2015-2019 - Astronomisches Rechen Institut (ARI),
* UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.io.BufferedReader;
......@@ -39,7 +40,7 @@ import uws.service.log.UWSLog.LogLevel;
/**
* <p>A {@link TAPResource} which is able to "forward" an HTTP request toward a specified URI.</p>
*
*
* <p>
* In function of the URI shape (i.e. what is the scheme? none/file:/other) and the servlet path,
* the HTTP request will be internally forwarded to the Web Application file (using
......@@ -47,11 +48,11 @@ import uws.service.log.UWSLog.LogLevel;
* the content of the specified file will be copied in the HTTP response or a redirection toward
* the given URL will be performed.
* </p>
*
*
* <p><i>See {@link #forward(String, String, HttpServletRequest, HttpServletResponse)} for more details</i></p>
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 2.1 (03/2017)
*
* @author Gr&eacute;gory Mantelet (ARI;CDS)
* @version 2.2 (03/2019)
* @since 2.1
*/
public abstract class ForwardResource implements TAPResource {
......@@ -62,7 +63,7 @@ public abstract class ForwardResource implements TAPResource {
/**
* Builds a {@link ForwardResource} with a logger to use in case of "small" errors.
*
*
* @param logger A TAP logger.
*/
protected ForwardResource(final TAPLog logger){
......@@ -71,7 +72,7 @@ public abstract class ForwardResource implements TAPResource {
/**
* <p>Write the content of the specified file in the given HTTP response.</p>
*
*
* <p>Three cases are taken into account in this function, in function of the given URI:</p>
* <ol>
* <li><b>a file inside WebContent</b> if the given URI has no scheme (e.g. "tapIndex.jsp" or "/myFiles/tapIndex.html").
......@@ -83,7 +84,7 @@ public abstract class ForwardResource implements TAPResource {
* <li><b>a distance document</b> in all other cases. Indeed, if there is a scheme different from "file:" the given URI will be considered as a URL.
* In this case, any request to the TAP home page is redirected to this URL.</li>
* </ol>
*
*
* <p><b>Important note:</b>
* The 1st option is applied ONLY IF the path of the TAP servlet is NOT the root path of the web application:
* that's to say <code>/*</code>. In the case where a URI without scheme is provided though the servlet path
......@@ -92,14 +93,14 @@ public abstract class ForwardResource implements TAPResource {
* specified file is not a JSP or does not need any kind of interpretation by the function
* {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}.
* </p>
*
*
* @param file URI/URL/path of the file to write/forward/redirect in the given HTTP response.
* @param mimeType MIME type of the specified file.
* @param request HTTP request which require the specified file.
* @param response HTTP response in which the specified file must be written/forwarded/redirected.
*
*
* @return <code>true</code> if the forward/redirection was successful, <code>false</code> otherwise.
*
*
* @throws IOException When an error occur while forwarding toward the specified Web application resource,
* or while writing the specified local file
* or while redirection toward the specified URL
......@@ -154,7 +155,7 @@ public abstract class ForwardResource implements TAPResource {
File f = new File(uri.getPath());
if (f.exists() && !f.isDirectory() && f.canRead()){
// set the content length:
response.setContentLength((int)f.length());
UWSToolBox.setContentLength(response, f.length());
// get the input stream:
input = new BufferedReader(new FileReader(f));
......@@ -231,12 +232,12 @@ public abstract class ForwardResource implements TAPResource {
/**
* <p>Log the given error as a TAP log message with the {@link LogLevel} ERROR, and the event corresponding to the resource name.</p>
*
*
* <p>
* The logged message starts with: <code>Can not write the specified content ({file})</code>.
* After the specified error message, the following is appended: <code>! => A default content may be displayed.</code>.
* </p>
*
*
* <p>
* If the message parameter is missing, the {@link Throwable} message will be taken instead.
* And if this latter is also missing, none will be written.
......
package uws;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* This file is part of UWSLibrary.
*
......@@ -31,25 +51,11 @@ import uws.service.log.UWSLog;
import uws.service.request.RequestParser;
import uws.service.request.UploadFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
* Some useful functions for the managing of a UWS service.
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 4.3 (01/2019)
* @version 4.4 (03/2019)
*/
public class UWSToolBox {
......@@ -525,9 +531,8 @@ public class UWSToolBox {
response.setCharacterEncoding(UWSToolBox.DEFAULT_CHAR_ENCODING);
// Set the HTTP content length:
if (contentSize > 0)
response.setHeader("Content-Length", String.valueOf(contentSize));
setContentLength(response, contentSize);
// Write the file into the HTTP response:
output = response.getOutputStream();
byte[] buffer = new byte[1024];
......@@ -688,4 +693,31 @@ public class UWSToolBox {
return null;
}
/**
* Set the content length in the given {@link HttpServletResponse}.
*
* <p><i><b>Implementation note:</b>
* This could perfectly be done using
* {@link HttpServletResponse#setContentLength(int)}, <b>but only if the
* content size is encoded or fit in an integer value</b>. Otherwise, that
* function will set no content length.
* On the contrary, this current function takes a long value and set
* manually the content type header.
* </i></p>
*
* <p><i><b>Note:</b>
* This function has no effect if the given {@link HttpServletResponse} is
* NULL or if the given content size is &le; 0.
* </i></p>
*
* @param response HTTP response.
* @param contentSize The content size to set.
*
* @since 4.4
*/
public static final void setContentLength(final HttpServletResponse response, final long contentSize){
if (response != null && contentSize > 0)
response.setHeader("Content-Length", String.valueOf(contentSize));
}
}
......@@ -2,21 +2,22 @@ package uws.job.jobInfo;
/*
* This file is part of UWSLibrary.
*
*
* UWSLibrary 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.
*
*
* UWSLibrary 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 UWSLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2017 - Astronomisches Rechen Institut (ARI)
*
* Copyright 2017-2019 - Astronomisches Rechen Institut (ARI),
* UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.io.IOException;
......@@ -25,20 +26,21 @@ import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import uws.UWSException;
import uws.UWSToolBox;
import uws.job.UWSJob;
import uws.job.serializer.XMLSerializer;
/**
* Very simple implementation of {@link JobInfo}. It aims to represent a
* key-value pair.
*
*
* <p>
* Both functions {@link #getXML(String)} and
* {@link #write(HttpServletResponse)} will return the following XML document:
* </p>
*
*
* <pre>&lt;KEY&gt;VALUE&lt;/KEY&gt;</pre>
*
*
* <p>, where:</p>
* <ul>
* <li><i><code>KEY</code></i> can be get with {@link #getName()} and can be
......@@ -46,16 +48,16 @@ import uws.job.serializer.XMLSerializer;
* <li><i><code>VALUE</code></i> can be get with {@link #getValue()} and set
* with {@link #setValue(String)}.</li>
* </ul>
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 4.2 (06/2017)
*
* @author Gr&eacute;gory Mantelet (ARI;CDS)
* @version 4.4 (03/2019)
* @since 4.2
*/
public class SingleValueJobInfo implements JobInfo {
private static final long serialVersionUID = 1L;
/** Name of the value stored inside this {@link JobInfo}.
*
*
* <p><i><b>Warning:</b> By default, this name is not supposed to be
* changed after initialization of this class. That's why only a public
* getter function is provided.</i></p> */
......@@ -66,7 +68,7 @@ public class SingleValueJobInfo implements JobInfo {
/** XML representation of this {@link JobInfo}, returned by
* {@link #getXML(String)} and {@link #write(HttpServletResponse)}.
*
*
* <p><i>Note:
* It has to be updated each time the {@link #value} is changed. So by
* default, it is rebuilt by {@link #setValue(String)}.
......@@ -76,11 +78,11 @@ public class SingleValueJobInfo implements JobInfo {
/**
* Build a {@link JobInfo} representing a single value having the given
* name.
*
*
* <p><i>Note 1:
* The name can not be changed after creation.
* </i></p>
*
*
* <p><i>Note 2:
* With this constructor, the represented value is NULL. To set a value,
* you have to use the function {@link #setValue(String)}. An alternative
......@@ -88,9 +90,9 @@ public class SingleValueJobInfo implements JobInfo {
* {@link #SingleValueJobInfo(String, String)} so that setting immediately
* the name and value.
* </i></p>
*
*
* @param name Name of the value to represent.
*
*
* @throws NullPointerException If the given name is NULL or an empty
* string.
* @throws IllegalArgumentException If the given name is not a valid XML
......@@ -105,20 +107,20 @@ public class SingleValueJobInfo implements JobInfo {
/**
* Build a {@link JobInfo} representing a single value having the given
* name and initial value.
*
*
* <p><i>Note 1:
* The name can not be changed after creation.
* </i></p>
*
*
* <p><i>Note 2:
* The value can change after object creation with the function
* {@link #setValue(String)}.
* </i></p>
*
*
* @param name Name of the value to represent. <i>Can not be NULL or an
* empty string, and must be a valid XML node name.</i>
* @param value Value to represent. <i>May be NULL.</i>
*
*
* @throws NullPointerException If the given name is NULL or an empty
* string.
* @throws IllegalArgumentException If the given name is not a valid XML
......@@ -138,7 +140,7 @@ public class SingleValueJobInfo implements JobInfo {
/**
* Get the name of the represented value.
*
*
* @return Value name. <i>Can NEVER be NULL.</i>
*/
public String getName(){
......@@ -147,7 +149,7 @@ public class SingleValueJobInfo implements JobInfo {
/**
* Get the represented value.
*
*
* @return The represented value. <i>Can be NULL.</i>
*/
public String getValue(){
......@@ -156,7 +158,7 @@ public class SingleValueJobInfo implements JobInfo {
/**
* Set the value represented by this {@link JobInfo}.
*
*
* @param value The new value to represent. <i>Can be NULL.</i>
*/
public void setValue(final String value){
......@@ -174,7 +176,7 @@ public class SingleValueJobInfo implements JobInfo {
public void write(HttpServletResponse response) throws IOException, UWSException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/xml");
response.setContentLength(xmlRepresentation.getBytes("UTF-8").length);
UWSToolBox.setContentLength(response, xmlRepresentation.getBytes("UTF-8").length);
PrintWriter writer = response.getWriter();
writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
......
......@@ -2,21 +2,22 @@ package uws.job.jobInfo;
/*
* This file is part of UWSLibrary.
*
*
* UWSLibrary 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.
*
*
* UWSLibrary 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 UWSLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2017 - Astronomisches Rechen Institut (ARI)
*
* Copyright 2017-2019 - Astronomisches Rechen Institut (ARI),
* UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.io.BufferedReader;
......@@ -38,20 +39,20 @@ import uws.service.request.UploadFile;
/**
* A full XML document attached to a {@link UWSJob job}.
*
*
* <p><b>XML representation</b></p>
*
*
* <p>
* The document stored inside this {@link JobInfo} is considered formatted
* in XML. So the functions {@link #getXML(String)} and
* {@link #write(HttpServletResponse)} will return them as such.
* </p>
*
*
* <p><i>Note 1:
* The represented document is supposed to be XML, but absolutely no
* verification is performed by {@link XMLJobInfo}.
* </i></p>
*
*
* <p><i>Note 2:
* {@link #getXML(String)} will skip the XML declaration
* (e.g. <code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code>)
......@@ -59,7 +60,7 @@ import uws.service.request.UploadFile;
* will write an exact copy of the stored XML document.
* Both functions can be overwritten if a different behavior is needed.
* </i></p>
*
*
* <p><i>Note 3:
* The stored XML document can refer to the following
* XML schemas:
......@@ -77,9 +78,9 @@ import uws.service.request.UploadFile;
* {@link XMLSerializer} in order to append the needed namespaces to the root
* XML node of any formatted XML documents.
* </i></p>
*
*
* <p><b>Internal representation and Creation</b></p>
*
*
* <p>
* This class proposes the two following constructors, each for a different
* internal representation:
......@@ -94,17 +95,17 @@ import uws.service.request.UploadFile;
* XML document.This constructor should be used <b>for large XML
* document.</b></li>
* </ul>
*
*
* <p><b>Modification</b></p>
*
*
* <p>
* By default, this implementation of {@link JobInfo} does not allow the
* modification of its XML document. If needed, this class should be
* extended with the adequate functions.
* </p>
*
*
* <p><b>Backup/Restoration</b></p>
*
*
* <p>
* An {@link UploadFile} can not be serialized using the Java Class
* Serialization mechanism because it does not implement the
......@@ -112,43 +113,43 @@ import uws.service.request.UploadFile;
* will be marked as <i>transient</i> and will have to be rebuilt when needed
* after a restoration process.
* </p>
*
*
* <p>However, it can be rebuilt only if:</p>
* <ol>
* <li>an access to a {@link UWSFileManager} is
* possible.</li>
* <li>the location of the file is known.</li>
* </ol>
*
*
* <p>
* The first point (1) is fortunately possible through a {@link UWSJob} object.
* This object is known after attachment to a job thanks to the function
* {@link #setJob(UWSJob)}. So, a link toward the parent job should be kept ;
* also marked as <i>transient</i>: see the attribute {@link #job}.
* </p>
*
*
* <p>For the second point (2), the location of the file must be kept as a
* non-transient attribute (see {@link #location}) so that being backuped with the
* other non-transient attributes of this class. In order to backup this
* location up-to-date, the function
* {@link #writeObject(java.io.ObjectOutputStream)} updates {@link #location}
* before the normal Java Class Serialization.
*
*
* <p>
* So finally, the restoration of the {@link UploadFile} will be done by
* {@link #getXML(String)} and {@link #write(HttpServletResponse)} with the
* function {@link #restoreFile()}.
* </p>
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 4.2 (06/2017)
*
* @author Gr&eacute;gory Mantelet (ARI;CDS)
* @version 4.4 (03/2019)
* @since 4.2
*/
public class XMLJobInfo implements JobInfo {
private static final long serialVersionUID = 1L;
/** XML file location.
*
*
* <p><b>Warning:</b>
* This field <b>ONLY</b> aims to contain the updated result of
* {@link UploadFile#getLocation() file.getLocation()}.
......@@ -156,12 +157,12 @@ public class XMLJobInfo implements JobInfo {
protected String location = null;
/** Link toward the XML file represented by this {@link JobInfo}.
*
*
* <p><b>Important:</b>
* This field must be used when a large XML document has to be represented
* by this {@link JobInfo}.
* </p>
*
*
* <p><i>Note:
* It can be set only by {@link #XMLJobInfo(UploadFile)}.
* If set, {@link #content} must be NULL.
......@@ -169,12 +170,12 @@ public class XMLJobInfo implements JobInfo {
protected transient UploadFile file = null;
/** XML document represented by this {@link JobInfo}.
*
*
* <p><b>Important:</b>
* This field MUST be used <b>ONLY</b> for small XML document in order to
* keep enough memory free for the normal UWS service operations.
* </p>
*
*
* <p><i>Note:
* It can be set only by {@link #XMLJobInfo(String)}.
* If set, {@link #file} must be NULL.
......@@ -185,7 +186,7 @@ public class XMLJobInfo implements JobInfo {
protected int length = -1;
/** The job owning this {@link JobInfo}.
*
*
* <p><i>Note:
* This field is set only by {@link #setJob(UWSJob)} and is used
* only by {@link #restoreFile()} in order to rebuild {@link #file}
......@@ -195,7 +196,7 @@ public class XMLJobInfo implements JobInfo {
/**
* Build a {@link JobInfo} representing a <b>small</b> XML document.
*
*
* <p><b>Important:</b>
* This constructor should be used only for <b>small</b> XML document
* because the given string will be kept as such in memory. If the given
......@@ -205,9 +206,9 @@ public class XMLJobInfo implements JobInfo {
* should save it in a file and use the constructor
* {@link #XMLJobInfo(UploadFile)}.</i>
* </p>
*
*
* @param smallXML The small XML document to represent.
*
*
* @throws NullPointerException If the given string is NULL or empty.
*/
public XMLJobInfo(final String smallXML) throws NullPointerException{
......@@ -223,9 +224,9 @@ public class XMLJobInfo implements JobInfo {
/**
* Build a {@link JobInfo} representing a <b>large</b> XML document stored
* inside a file.
*
*
* @param xmlFile Link toward the large XML document to represent.
*
*
* @throws NullPointerException If the given file is NULL or empty.
*/
public XMLJobInfo(final UploadFile xmlFile) throws NullPointerException{
......@@ -277,7 +278,8 @@ public class XMLJobInfo implements JobInfo {
if (input != null){
try{
input.close();
}catch(IOException ioe){}
}catch(IOException ioe){
}
}
}
return xml.toString();
......@@ -290,7 +292,7 @@ public class XMLJobInfo implements JobInfo {
if (content != null){
response.setCharacterEncoding("UTF-8");
response.setContentType("text/xml");
response.setContentLength(content.getBytes("UTF-8").length);
UWSToolBox.setContentLength(response, content.getBytes("UTF-8").length);
PrintWriter writer = response.getWriter();
writer.println(content);
......@@ -330,17 +332,17 @@ public class XMLJobInfo implements JobInfo {
/**
* Serialize this {@link XMLJobInfo}.
*
*
* <p><i>Note:</i>
* This function will be called by the Java Class Serialization mechanism.
* See the Javadoc of {@link Serializable} for more details.
* </i></p>
*
*
* <p>
* This function just updates the XML file (if any) location before the
* normal Java Class Serialization of this object.
* </p>
*
*
* @param out The stream used to contained the serialization of this
* {@link XMLJobInfo}.
*
......@@ -358,20 +360,20 @@ public class XMLJobInfo implements JobInfo {
/**
* Restore the link toward the XML file represented by this {@link JobInfo}.
*
*
* <p>
* This function has an effect only if {@link #file} is NULL but not
* {@link #location} ; indeed, such configuration can be encountered only
* if this {@link XMLJobInfo} has been de-serialized.
* </p>
*
*
* <p>
* Nothing can be done if the parent job is unknown. In other words,
* this {@link JobInfo} has to be attached to a job first
* (i.e. {@link #setJob(UWSJob)} has to be called first with a non-NULL
* parameter). If not, an exception will be thrown.
* </p>
*
*
* @throws UWSException If this {@link JobInfo} is not attached to a job.
*/
protected void restoreFile() throws UWSException{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment