Skip to content
Snippets Groups Projects
Commit f7c160f7 authored by Sara Bertocco's avatar Sara Bertocco
Browse files

New working version after Victoria trip

parent bda69128
Branches
Tags
No related merge requests found
/**_____________________________________________________________________________ /**
* _____________________________________________________________________________
* *
* OATS - INAF * OATS - INAF
* Osservatorio Astronomico di Tireste - Istituto Nazionale di Astrofisica * Osservatorio Astronomico di Tireste - Istituto Nazionale di Astrofisica
...@@ -21,69 +22,36 @@ ...@@ -21,69 +22,36 @@
* along with this program; if not, write to the Free Software Foundation, Inc., * along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* _____________________________________________________________________________ * _____________________________________________________________________________
**/ *
*/
package it.inaf.oats.vospacebackend; package it.inaf.oats.vospacebackend;
import it.inaf.oats.vospacebackend.implementation.VOSpaceBackend; import it.inaf.oats.vospacebackend.utils.ResourceManager;
import it.inaf.oats.vospacebackend.implementation.VOSpaceBackImplFactory; import ca.nrc.cadc.uws.ExecutionPhase;
import it.inaf.oats.vospacebackend.exceptions.ExceptionMessage; import ca.nrc.cadc.uws.Job;
import it.inaf.oats.vospacebackend.exceptions.VOSpaceBackendException;
import it.inaf.oats.vospacebackend.utils.ConfigReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.net.MalformedURLException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Iterator;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.codec.binary.Hex;
import org.restlet.resource.Get; import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.Put; import org.restlet.resource.Put;
import org.restlet.resource.Delete;
import org.restlet.Request; import org.restlet.Request;
import org.restlet.resource.ServerResource; import org.restlet.resource.ServerResource;
import org.restlet.representation.Variant; import org.restlet.representation.Variant;
import org.restlet.representation.Representation; import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation; import org.restlet.representation.StringRepresentation;
import org.restlet.representation.FileRepresentation;
import org.restlet.ext.fileupload.RestletFileUpload;
import org.restlet.data.MediaType; import org.restlet.data.MediaType;
import org.restlet.data.Status; import org.restlet.data.Status;
import java.security.InvalidKeyException; import org.apache.http.HttpStatus;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.io.OutputStream;
import java.util.UUID;
import javax.xml.bind.DatatypeConverter;
import ca.nrc.cadc.util.RsaSignatureGenerator;
import ca.nrc.cadc.util.RsaSignatureVerifier;
import java.security.MessageDigest;
/** /**
* *
* @author bertocco * @author bertocco
*/ */
public class VOSpaceBackendResource extends ServerResource { public class VOSpaceBackendResource extends ServerResource implements org.apache.http.HttpStatus {
protected Logger log = Logger.getLogger(VOSpaceBackendResource.class); protected Logger log = Logger.getLogger(VOSpaceBackendResource.class);
...@@ -91,459 +59,136 @@ public class VOSpaceBackendResource extends ServerResource { ...@@ -91,459 +59,136 @@ public class VOSpaceBackendResource extends ServerResource {
public Representation doPut(Representation entity, Variant variant) throws Exception { public Representation doPut(Representation entity, Variant variant) throws Exception {
Representation result = null; Representation result = null;
int opResult = 0;
log.info("Entering in PUT operation"); log.info("Entering in PUT operation");
String vosuri = null; String jobID = null;
String vosuri;
String encodedParameters; String encodedParameters;
InputStream is; InputStream is;
if (entity != null) { if (entity != null) {
log.info("Received good entity"); log.info("Received good entity");
try { try {
log.debug("Trying to read attributes");
Request request = getRequest(); vosuri = readParameters();
encodedParameters = (String)getRequest().getAttributes().get("parameters");
log.debug("Received encoded parameters : " + encodedParameters); jobID = (String) getRequest().getAttributes().get("jobid");
vosuri = manageParametersDecoding(encodedParameters); log.debug("Received jobid = " + jobID);
log.debug("Received parameters decoded = " + vosuri);
} catch (Exception e) { } catch (MalformedURLException e) {
log.debug("Exception reading string parameters");
log.debug(e); setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return this.printMessage("Malformed URL received. Unable to read parameters from URL");
} }
try { try {
is = entity.getStream(); is = entity.getStream();
log.debug("Input stream get"); log.debug("Input stream get");
result = readAndSaveFile(vosuri, is); opResult = ResourceManager.readAndSaveFile(vosuri, is);
} catch (Exception e) { } catch (Exception e) {
result = this.printMessage("File NOT Uploaded! Something went wrong.");
}
} log.debug("Exception in readAndSaveFile");
return this.printMessage("File NOT Uploaded! Something went wrong.");
return result;
} }
/*
@Post
public Representation doPost(Representation entity) throws Exception {
Representation result = null;
log.info("Entering in POST operation");
if (entity != null) {
if (MediaType.MULTIPART_FORM_DATA.equals(entity.getMediaType(), true)) {
log.info("Correctly Using MULTIPART_FORM_DATA");
try {
result = this.uploadFile(entity);
} catch (Exception e) {
result = this.printMessage(e.getMessage());
} }
if (opResult == HttpStatus.SC_OK) {
log.debug("File upload successful!");
log.debug("Going to set execution phase as completed ...");
ResourceManager.setJobPhase(jobID, ExecutionPhase.EXECUTING, ExecutionPhase.COMPLETED);
log.debug("Checkp 1");
ExecutionPhase expected = ExecutionPhase.COMPLETED;
ExecutionPhase current = ResourceManager.getJobPhase(jobID);
log.debug("Current phase = " + current.toString());
if (current == null) {
log.debug("Unable to correctly get job phase");
return this.printMessage("File SUCCESSFULLY Uploaded, but Unable to correctly set/get job phase");
} else { } else {
// POST request with unexpected type. if (current.toString().equals(expected.toString())) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST); log.debug("Job phase at the backend upload end: " + current.toString());
result = this.printMessage("POST request with unexpected type."); setStatus(Status.SUCCESS_OK);
return this.printMessage("File SUCCESSFULLY Uploaded!");
} else {
log.debug("Job phase at the backend upload end: " + current.toString());
return this.printMessage("File SUCCESSFULLY Uploaded, but internal operation trace not completed");
}
} }
} else { } else {
// POST request with no entity. log.debug("Internal server error. Operation result code: " + String.valueOf(opResult));
setStatus(Status.CLIENT_ERROR_BAD_REQUEST); setStatus(Status.SERVER_ERROR_INTERNAL);
result = this.printMessage("POST request with no entity."); return this.printMessage("File NOT Uploaded! Something went wrong.");
} }
return result;
} }
*/
@Get @Get
public Representation doGet() { public Representation doGet() {
Representation result = null; Representation result = null;
String vosuri;
log.info("Entering in GET operation"); log.info("Entering in GET operation");
String fileName = (String)getRequestAttributes().get("fileToManage");
log.debug("File to download is: " + fileName);
try { try {
result = this.downloadFile(fileName);
} catch (Exception e) {
//setStatus(Status.CLIENT_ERROR_NOT_FOUND);
result = this.printMessage("GET request: failed to download file.");
}
vosuri = readParameters();
return result; } catch (MalformedURLException e) {
}
@Delete
public Representation doDelete(){
Representation result;
log.info("Entering in DELETE operation");
String fileName = (String)getRequestAttributes().get("fileToManage");
log.debug("File to delete is: " + fileName);
try {
result = this.deleteFile(fileName);
} catch (Exception e) {
result = this.printMessage("DELETE request: failed to delete file " + fileName);
}
return result;
}
/*
private Representation uploadFile(Representation entity) throws Exception {
Representation result = null;
// 1/ Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1000240);
log.info("Factory created");
// 2/ Create a new file upload handler based on the Restlet
// FileUpload extension that will parse Restlet requests and
// generates FileItems.
RestletFileUpload upload = new RestletFileUpload(factory);
log.info("RestletFileUpload created");
List<FileItem> items;
boolean fileFound = false;
String origFileName = null;
FileItem fileItemToStore = null;
Map<String, String> parameters = new HashMap<String, String>();
try {
// 3/ Request is parsed by the handler which generates a list of FileItems
items = upload.parseRequest(getRequest());
for (final Iterator<FileItem> it = items.iterator(); it.hasNext(); ) {
FileItem fi = it.next();
String fileName = fi.getName();
if (fileName == null) {
parameters.put(fi.getFieldName(), new String(fi.get(), "UTF-8"));
} else {
fileItemToStore = fi;
origFileName = fileName;
fileFound = true;
}
}
} catch (Exception e) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("Unable to correctly parse request");
return result;
}
if (!fileFound) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("Unable to find a file to download");
return result;
}
String unique_file_id_str;
String security_token;
if (parameters.isEmpty()) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST); setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("Unable to find parameters in client request"); return this.printMessage("Malformed URL received. Unable to read parameters from URL");
return result;
}
if (origFileName == null) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("Unable to find original file name in client request");
return result;
}
if (parameters.get("unique_file_id_string") == null) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("No parameter unique_file_id_string found in request");
return result;
}
unique_file_id_str = parameters.get("unique_file_id_string");
if (parameters.get("security_token") == null) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("No parameter security_token found in request");
return result;
}
security_token = parameters.get("security_token");
log.debug("unique_file_id_string = " + unique_file_id_str);
log.debug("security_token = " + security_token);
log.debug("fileName = " + origFileName);
result = readAndSaveFile(vosuri, fileItemToStore);
return result;
}
*/
private Representation readAndSaveFile(String vosuri, FileItem fi)
throws IOException, VOSpaceBackendException {
Representation result;
log.debug("Entering in readAndSaveFile");
InputStream is = fi.getInputStream();
log.debug("Input stream get");
return readAndSaveFile(vosuri, is);
}
private Representation readAndSaveFile(String vosuri, InputStream is)
throws IOException, VOSpaceBackendException {
Representation result;
String md5sum = null;
// Generate the unique file identifier (storageFileID)
String unique_file_id_str = UUID.randomUUID().toString();
log.debug("Unique file identifyer " + unique_file_id_str);
// Get temporary document root from configuration file
String tmpStorageRoot = new String();
try {
ConfigReader myConf = new ConfigReader("VOSpace.properties");
tmpStorageRoot = myConf.getProperty("fs.posix.tmp.storage.root");
} catch (Exception e) {
ExceptionMessage exMsg = new ExceptionMessage();
log.debug(MessageFormat.format(
exMsg.getMessage("UNABLE_TO_READ_PROPERTIES"), "VOSpace.properties"));
throw new VOSpaceBackendException(MessageFormat.format(
exMsg.getMessage("PROPERTY_NOT_FOUND"), "fs.posix.tmp.storage.root", "VOSpace.properties"));
}
// Create the temporary directory, if needed
File path = new File(tmpStorageRoot);
if (!path.exists()) {
boolean status = path.mkdirs();
}
// Seve the temporary file in temporary location with the new unique name
File savedUploadedFile = new File(path + File.separator + unique_file_id_str);
FileOutputStream outStream = new FileOutputStream(savedUploadedFile);
try {
md5sum = readWriteAndGetChecksum(is, outStream);
} catch (Exception e) {
result = this.printMessage("File NOT Uploaded! Something went wrong." + e.getMessage());
} }
try { try {
if (this.storeUploadedFile(vosuri, unique_file_id_str, md5sum)) { result = ResourceManager.downloadFile(vosuri);
setStatus(Status.SUCCESS_OK);
result = this.printMessage("File successfully uploaded");
} else {
result = this.printMessage("File NOT Uploaded! Something went wrong.");
}
} catch (Exception e) { } catch (Exception e) {
result = this.printMessage("File NOT Uploaded! Something went wrong.");
}
return result;
}
private boolean storeUploadedFile(String vosuri, String tmp_file_name,
String md5_sum) throws Exception {
boolean stored = false;
log.debug("Entering in storeUploadedFile");
VOSpaceBackImplFactory myVOSpaceFactory = new VOSpaceBackImplFactory();
log.debug("myVOSpaceFactory created");
VOSpaceBackend myVOSpace = myVOSpaceFactory.getVOSpaceBackImpl();
log.debug("myVOSpace get");
stored = myVOSpace.createFile(vosuri, tmp_file_name, md5_sum);
log.debug("File stored: " + stored);
return stored;
}
private Representation downloadFile(String fileName) throws Exception {
Representation result;
log.debug("Entering in downloadFile");
VOSpaceBackImplFactory myVOSpaceFactory = new VOSpaceBackImplFactory();
log.debug("myVOSpaceFactory created");
VOSpaceBackend myVOSpace = myVOSpaceFactory.getVOSpaceBackImpl();
log.debug("myVOSpace get");
File fileToDownload = myVOSpace.returnFile(fileName);
if (fileToDownload != null ) {
log.debug("File found, fileToDownload is not null");
FileRepresentation fr = new FileRepresentation(fileToDownload.getAbsolutePath(),
MediaType.APPLICATION_OCTET_STREAM);
result = fr;
setStatus(Status.SUCCESS_OK);
} else {
log.debug("File NOT found, fileToDownload is null");
result = this.printMessage("Unable to download file. Something went wrong!");
setStatus(Status.SERVER_ERROR_INTERNAL); setStatus(Status.SERVER_ERROR_INTERNAL);
result = this.printMessage("GET request: failed to download file.");
} }
return result; if (result != null) {
}
private Representation deleteFile(String fileName) throws Exception {
Representation result = null;
log.debug("Entering in deleteFile");
VOSpaceBackImplFactory myVOSpaceFactory = new VOSpaceBackImplFactory();
log.debug("myVOSpaceFactory created");
VOSpaceBackend myVOSpace = myVOSpaceFactory.getVOSpaceBackImpl();
log.debug("myVOSpace delete");
try {
if(myVOSpace.deleteFile(fileName)) {
log.debug("DELETE request: file " + fileName + " removed.");
result = this.printMessage("DELETE request: file " + fileName + " removed.");
setStatus(Status.SUCCESS_OK); setStatus(Status.SUCCESS_OK);
return result;
} else { } else {
log.debug("DELETE request: failed to remove file " + fileName); setStatus(Status.CLIENT_ERROR_NOT_FOUND);
result = this.printMessage("DELETE request: failed to remove file " + fileName); return this.printMessage("GET request: failed to download file.");
setStatus(Status.SERVER_ERROR_INTERNAL);
}
} catch (Exception e) {
log.debug("DELETE request: failed to remove file " + fileName);
result = this.printMessage("DELETE request: failed to remove file " + fileName);
setStatus(Status.SERVER_ERROR_INTERNAL);
} }
return result;
} }
private String readParameters() throws MalformedURLException {
private String manageParametersDecoding(String toBeVerified) {
String vosuri; String vosuri;
int count = 0;
log.debug("manageParametersEncoding BEGIN");
String urlStr = new String(DatatypeConverter.parseBase64Binary(toBeVerified));
log.debug("urlStr = " + urlStr);
vosuri = urlStr.substring(0, urlStr.indexOf("|"));
log.debug("vosuri = " + vosuri);
String remaining = urlStr.substring(urlStr.indexOf("|")+1, urlStr.length());
log.debug("Remaining after get vosuri = " + remaining);
String signature = remaining.substring(remaining.indexOf("|")+1, remaining.length());
log.debug("signature = \n" + signature);
// Validation
log.debug("I am going to create RsaSignatureVerifier");
RsaSignatureVerifier su = new RsaSignatureVerifier();
log.debug("Created");
boolean valid = false;
try { try {
valid = su.verify(new ByteArrayInputStream(vosuri.getBytes()), log.debug("Trying to read attributes");
DatatypeConverter.parseBase64Binary(signature)); Request request = getRequest();
} catch (IOException ioe) { String encodedParameters = (String) getRequest().getAttributes().get("parameters");
log.debug("IOException"); log.debug("Received encoded parameters : " + encodedParameters);
log.debug(ioe.getMessage()); vosuri = ResourceManager.manageParametersDecoding(encodedParameters);
} catch (InvalidKeyException ike) { log.debug("Received parameters decoded = " + vosuri);
log.debug("InvalidKeyException"); } catch (Exception e) {
log.debug(ike.getMessage()); log.debug("Exception reading string parameters");
log.debug(e);
throw new MalformedURLException("Exception reading string parameters from URL");
} }
return vosuri; return vosuri;
} }
public String readWriteAndGetChecksum(InputStream istream, FileOutputStream ostream) throws Exception { public static Representation printMessage(String error) {
log.debug("Entering in readWriteAndGetChecksum(InputStream, FileOutputStream)");
int DEFAULT_BUFFER_SIZE = 1024 * 4;
String checksum = null;
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int bytesRead;
MessageDigest msgDigest = MessageDigest.getInstance("MD5");
// do an initial read to ensure there are bytes in the stream
try {
bytesRead = istream.read(buffer, 0, DEFAULT_BUFFER_SIZE);
if (bytesRead <= 0) {
// do not allow the creation of zero-length files
log.debug("Cannot write a zero-length file.");
throw new Exception("Cannot write a zero-length file.");
} else
log.debug("First bytes read OK");
} catch (IOException ex) {
String errorMsg = "Upstream exception while reading from "
+ istream.getClass().getName() + ": "
+ ex.getMessage();
log.debug("IOException in the first byte reading of the incoming file");
log.debug(errorMsg);
//throw new TransferAbortedException(errorMsg);
throw new Exception(errorMsg);
}
// Loop reading and writing data.
msgDigest.update(buffer, 0, bytesRead);
log.debug("First msgDigest.update OK");
try {
while (bytesRead >= 0) {
ostream.write(buffer, 0, bytesRead);
try {
bytesRead = istream.read(buffer, 0, DEFAULT_BUFFER_SIZE);
if(bytesRead > 0) {
msgDigest.update(buffer, 0, bytesRead);
}
} catch (IOException ex) {
String errorMsg = "Upstream exception while reading from "
+ istream.getClass().getName() + ": "
+ ex.getMessage();
//throw new TransferAbortedException(errorMsg);
log.debug(errorMsg);
log.debug("A Exception in reading/writing file" + ex.getMessage());
throw new Exception(errorMsg);
}
}
ostream.flush();
ostream.close();
} catch (IOException ex) {
log.debug("B Exception in reading/writing file" + ex.getMessage());
}
//Get the hash's bytes
byte[] bytes = null;
try {
bytes = msgDigest.digest();
} catch (Exception ex) {
log.debug("Exception doing msgDigest.digest()");
}
String md5_checksum = new String(Hex.encodeHex(bytes));
log.debug("************************ MD5 checksum calculated: " + md5_checksum);
return md5_checksum;
}
private Representation printMessage(String error) {
StringBuilder sb = new StringBuilder(""); StringBuilder sb = new StringBuilder("");
sb.append(error); sb.append(error);
sb.append("\n"); sb.append("\n");
return new StringRepresentation(sb.toString(), MediaType.TEXT_PLAIN); return new StringRepresentation(sb.toString(), MediaType.TEXT_PLAIN);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment