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

First running version

parents
Branches
Tags
No related merge requests found
Showing
with 1576 additions and 0 deletions
File added
File added
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_j2eeVersion>1.7-web</org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_j2eeVersion>
<org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>Tomcat</org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>
</properties>
</project-shared-configuration>
pom.xml 0 → 100644
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>it.inaf.oats</groupId>
<artifactId>VOSpaceBackend</artifactId>
<version>0.0</version>
<packaging>war</packaging>
<name>VOSpaceBackend</name>
<repositories>
<repository>
<id>maven-restlet</id>
<name>Restlet repository</name>
<url>https://maven.restlet.com</url>
</repository>
</repositories>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<restlet-version>2.3.6</restlet-version>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
</dependency>
<dependency>
<groupId>restletfileupload</groupId>
<artifactId>fileupload</artifactId>
<version>0.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>ca.nrc.cadc.</groupId>
<artifactId>cadcUtil</artifactId>
<version>0.0</version>
</dependency>
<dependency>
<groupId>com.mysql.jdbc</groupId>
<artifactId>mysql-connector</artifactId>
<version>0.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet</artifactId>
<version>${restlet-version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.jackson</artifactId>
<version>2.3.6</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.json</artifactId>
<version>2.3.4</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.servlet</artifactId>
<version>2.3.4</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.fileupload</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<excludes><exclude>**/*.java</exclude></excludes>
</resource>
</resources>
</build>
</project>
/**
*
* @author bertocco
*/
package it.inaf.oats.vospacebackend;
import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;
public class VOSpaceBackendApplication extends Application {
@Override
public synchronized Restlet createInboundRoot() {
// Create a router Restlet that defines routes.
Router router = new Router(getContext());
// Defines a route for the resource "list of items"
router.attach("/vospaceBackendSet", VOSpaceBackendResource.class );
router.attach("/vospaceBackendSet/{fileToManage}", VOSpaceBackendResource.class );
//router.attach("/vospaceBackendGet", VOSpaceBackendResourceGet.class );
return router;
}
}
package it.inaf.oats.vospacebackend;
import it.inaf.oats.vospacebackend.implementation.VOSpaceBackPosix;
import it.inaf.oats.vospacebackend.implementation.VOSpaceBackMetadata;
import ca.nrc.cadc.util.PropertiesReader;
import it.inaf.oats.vospacebackend.implementation.VOSpaceBackend;
import it.inaf.oats.vospacebackend.implementation.VOSpaceBackImplFactory;
import it.inaf.oats.vospacebackend.exceptions.ExceptionMessage;
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.text.MessageFormat;
import java.util.UUID;
import java.util.HashMap;
import org.apache.log4j.Logger;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.Delete;
import org.restlet.resource.ServerResource;
import org.restlet.representation.Representation;
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.Status;
/**
*
* @author bertocco
*/
public class VOSpaceBackendResource extends ServerResource {
protected Logger log = Logger.getLogger(VOSpaceBackendResource.class);
@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());
}
} else {
// POST request with unexpected type.
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("POST request with unexpected type.");
}
} else {
// POST request with no entity.
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
result = this.printMessage("POST request with no entity.");
}
return result;
}
@Get
public Representation doGet(){
Representation result = null;
log.info("Entering in GET operation");
String fileName = (String)getRequestAttributes().get("fileToManage");
log.debug("File to download is: " + fileName);
try {
result = this.downloadFile(fileName);
} catch (Exception e) {
//setStatus(Status.CLIENT_ERROR_NOT_FOUND);
result = this.printMessage("GET request: failed to download file.");
}
return result;
}
@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");
// 3/ Request is parsed by the handler which generates a
// list of FileItems
FileItemIterator fileIterator = null;
try {
fileIterator = upload.getItemIterator(entity);
} catch (Exception e) {
log.info(e.toString());
}
log.info("Iterator created");
// Process only the uploaded item called "fileToUpload"
// and return back
boolean found = false;
while (fileIterator.hasNext() && !found) {
FileItemStream fi = fileIterator.next();
if (fi.getFieldName().equals("fileToUpload")) {
found = true;
// Read the original file name
String origFileName = fi.getName();
// Check if fileName is present in metadata DB
VOSpaceBackMetadata metadataDB = new VOSpaceBackMetadata();
HashMap myMetadata;
myMetadata = metadataDB.getFile(origFileName);
if ((boolean)myMetadata.get("ifSuccessful")) {
log.debug("File Name already present in the database");
result = this.printMessage("File Name already present in the database.");
} else {
// Read the file content
InputStream is = fi.openStream();
byte[] data = IOUtils.toByteArray(is);
// Calculate the file MD5 checksum (so will not need to re-read
// the file a new time later
String md5sum = new String(DigestUtils.md5Hex(data));
log.debug("MD5Sum del file: " + md5sum);
// Calculate a unique file name to store the file
String unique_file_id_str = UUID.randomUUID().toString();
log.debug("Unique file identifyer " + unique_file_id_str);
log.debug("FieldName = " + fi.getFieldName());
log.debug("Field " + fi.getFieldName() + " found");
// 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);
outStream.write(data);
outStream.close();
if (this.storeUploadedFile(unique_file_id_str, origFileName, md5sum)) {
setStatus(Status.SUCCESS_OK);
result = this.printMessage("File successfully uploaded");
} else {
result = this.printMessage("File NOT Uploaded! Something went wrong.");
}
}
}
}
return result;
}
private boolean storeUploadedFile(String tmp_file_name, String orig_f_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(orig_f_name, 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);
}
return result;
}
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);
} else {
log.debug("DELETE request: failed to remove file " + fileName);
result = this.printMessage("DELETE request: failed to remove file " + fileName);
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 Representation printMessage(String error) {
StringBuilder sb = new StringBuilder("");
sb.append(error);
sb.append("\n");
return new StringRepresentation(sb.toString(), MediaType.TEXT_PLAIN);
}
}
/**
*
* @author bertocco
*/
package it.inaf.oats.vospacebackend.exceptions;
import java.util.ResourceBundle;
import java.util.HashMap;
import java.util.Enumeration;
import org.apache.log4j.Logger;
public class ExceptionMessage {
private static HashMap myMessagesProperties = new HashMap<String, String>();
protected static Logger log = Logger.getLogger(ExceptionMessage.class);
public ExceptionMessage() {
ResourceBundle rb = null;
try {
ResourceBundle.getBundle("it.inaf.oats.vospacebackend.exceptions.exceptionMessages");
} catch (Exception e) {
log.debug("Super unluky! Unable to read exception messages");
log.debug(e);
}
Enumeration <String> keys = rb.getKeys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
String value = rb.getString(key);
myMessagesProperties.put(key, value);
log.debug("Reading VOSpaceBackend exception messages:");
log.debug(key + " = " + value);
}
}
public static String getMessage(String msgKey) {
String excMsg = (String)myMessagesProperties.get(msgKey);
log.debug("Getting message:");
log.debug(excMsg);
return excMsg;
}
}
/**
*
* @author bertocco
*/
package it.inaf.oats.vospacebackend.exceptions;
import java.util.ResourceBundle;
import org.apache.log4j.Logger;
import java.util.ResourceBundle;
public class VOSpaceBackendException extends Exception {
private static final Logger log = Logger.getLogger(VOSpaceBackendException.class);
public VOSpaceBackendException() {
log.debug("VOSpaceBackendException created");
}
public VOSpaceBackendException(String message) {
super(message);
log.debug(message);
}
public VOSpaceBackendException(Throwable cause) {
super(cause);
cause.printStackTrace();
log.debug(cause.toString());
}
public VOSpaceBackendException(String message, Throwable cause) {
super(message, cause);
cause.printStackTrace();
log.debug(message);
log.debug(cause.toString());
}
}
# his properties file contains the messages related to error
# cases specific to the vospace backend application.
NO_VOSPACE_BACKEND_IMPLEMENTATION_SPECIFIED="VOSpace Backend Implementation NOT configured"
CLASS_NOT_FOUND="Required class {0} not found"
UNABLE_TO_INSTANTIATE="Unable to create an instance of class {0}"
UNABLE_TO_ACCESS="Unable to access class {0}"
DATABASE_DRIVER_NOT_FOUND="Unable to get Database data source. Check context.xml"
UNABLE_TO_GET_DB_CONNECTION="Unable to get the database connection"
ERROR_DISABLING_DB_AUTOCOMMIT="There was an error disabling the database autocommit"
DB_OPERATION_NOT_RECOGNIZED="File metadata database operation not recognized. Admitted only SET, GET, DELETE"
UNABLE_TO_READ_PROPERTIES="Unable to read properties file {0}"
PROPERTY_NOT_FOUND="Property {0} not found in file {1}"
\ No newline at end of file
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package it.inaf.oats.vospacebackend.implementation;
import java.util.HashMap;
public class FileRecord {
private static final String original_file_name = "original_file_name";
private static final String stored_file_name = "stored_file_name";
private static final String md5_checksum = "md5_checksum";
private static final String relative_path = "relative_path";
private HashMap content = new HashMap<String, String>();
public FileRecord() {
content.put(original_file_name, "");
content.put(stored_file_name, "");
content.put(md5_checksum, "");
content.put(relative_path, "");
}
public FileRecord(String fileName, String stored_f_name, String md5Checksum, String relativePath) {
content.put(original_file_name, fileName);
content.put(stored_file_name, stored_f_name);
content.put(md5_checksum, md5Checksum);
content.put(relative_path, relativePath);
}
public HashMap getFileRecord() {
return content;
}
public void setFileRecord(String fileName, String stored_f_name, String md5Checksum, String relativePath) {
content.put(original_file_name, fileName);
content.put(stored_file_name, stored_f_name);
content.put(md5_checksum, md5Checksum);
content.put(relative_path, relativePath);
}
}
/*
*
* @author bertocco
*/
package it.inaf.oats.vospacebackend.implementation;
import java.util.List;
import org.apache.log4j.Logger;
import ca.nrc.cadc.util.PropertiesReader;
import it.inaf.oats.vospacebackend.exceptions.ExceptionMessage;
import it.inaf.oats.vospacebackend.exceptions.VOSpaceBackendException;
import it.inaf.oats.vospacebackend.utils.ConfigReader;
import java.text.MessageFormat;
public class VOSpaceBackImplFactory {
private static final String CONFIG_FILE_NAME = "VOSpace.properties";
private static final Logger log = Logger.getLogger(VOSpaceBackImplFactory.class);
private static String VOSpaceBackImplName = new String();
public VOSpaceBackImplFactory() throws VOSpaceBackendException {
ConfigReader myConf = null;
try {
myConf = new ConfigReader(CONFIG_FILE_NAME);
} catch (Exception e) {
ExceptionMessage exMsg = new ExceptionMessage();
log.debug(MessageFormat.format(exMsg.getMessage("UNABLE_TO_READ_PROPERTIES"), CONFIG_FILE_NAME));
throw new VOSpaceBackendException(
MessageFormat.format(exMsg.getMessage("UNABLE_TO_READ_PROPERTIES"), CONFIG_FILE_NAME));
}
try {
this.VOSpaceBackImplName = myConf.getProperty("it.inaf.oats.vospacebackendimplementation.VOSpaceBackendImpl");
} catch (Exception e) {
ExceptionMessage exMsg = new ExceptionMessage();
log.debug(MessageFormat.format(
exMsg.getMessage("PROPERTY_NOT_FOUND"),
"it.inaf.oats.vospacebackendimplementation.VOSpaceBackendImpl",
CONFIG_FILE_NAME));
throw new VOSpaceBackendException(
MessageFormat.format(
exMsg.getMessage("PROPERTY_NOT_FOUND"),
"it.inaf.oats.vospacebackendimplementation.VOSpaceBackendImpl",
CONFIG_FILE_NAME));
}
}
public VOSpaceBackend getVOSpaceBackImpl() throws VOSpaceBackendException {
log.debug("Try to get object: " + this.VOSpaceBackImplName);
return (VOSpaceBackend)this.buildObject(this.VOSpaceBackImplName);
}
private Object buildObject(String myBackendImpl) throws VOSpaceBackendException {
Object result = null;
try {
//note that, with this style, the implementation needs to have a
//no-argument constructor!
Class implClass = Class.forName(myBackendImpl);
result = implClass.newInstance();
} catch (ClassNotFoundException ex) {
log.debug("CLASS_NOT_FOUND");
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(MessageFormat.format(exMsg.getMessage("CLASS_NOT_FOUND"), myBackendImpl));
} catch (InstantiationException ex) {
log.debug("UNABLE_TO_INSTANTIATE");
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(MessageFormat.format(exMsg.getMessage("UNABLE_TO_INSTANTIATE"), myBackendImpl));
} catch (IllegalAccessException ex) {
log.debug("UNABLE_TO_ACCESS");
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(MessageFormat.format(exMsg.getMessage("UNABLE_TO_ACCESS"), myBackendImpl));
}
return result;
}
}
package it.inaf.oats.vospacebackend.implementation;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.util.HashMap;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import it.inaf.oats.vospacebackend.exceptions.ExceptionMessage;
import it.inaf.oats.vospacebackend.exceptions.VOSpaceBackendException;
/*
* FileRecord myParams is used as input record
* HashMap myResult is used as output record
* @author bertocco
*/
public class VOSpaceBackMetadata {
/**
* This class has two attributes:
* <p>
* Logger to perform logging operations
* <p>
* HashMap which will contain the metadata set identifying a stored/to store file
* This hashmap fields will are:
* boolean ifSuccessfull if db query is successful or not
* String "original_file_name"
* String "stored_file_name"
* String "md5_checksum"
* String "relative_path"
*/
protected Logger log;
protected HashMap myResult;
/**
* Create the log and the HashMap that will be used to store the database
* query result to return. The field "ifSuccessful" will contain a boolean
* value true if operation successfully executed and false if not.
* Other fields will be added containing the query result set fields,
* depending on the executed query.
*/
public VOSpaceBackMetadata() {
log = Logger.getLogger(VOSpaceBackMetadata.class);
myResult = new <String, Object>HashMap();
myResult.put("ifSuccessful", false);
}
/**
*
* @param fileName Original file name (provided by the client) of the file to store
* @param stored_f_name name used to store the file in the file system
* @param md5Checksum MD5 checksum of the file to store
* @param relativePath relative path (after the root) of the file to store
* @return boolean true if operation successful false if not
* @throws VOSpaceBackendException
*/
public HashMap setFile(String fileName, String stored_f_name, String md5Checksum,
String relativePath)
throws VOSpaceBackendException, SQLException {
String myOp = "SET";
String myQuery = "INSERT INTO vosbackend.StoredFiles " +
"(original_file_name, stored_file_name, md5_checksum, relative_path)" +
" VALUES (?, ?, ?, ?);";
FileRecord myParams = new FileRecord(fileName, stored_f_name,
md5Checksum, relativePath);
myResult = excuteQuery(myOp, myQuery, myParams);
return myResult;
}
public HashMap getFile(String orig_f_name)
throws VOSpaceBackendException, SQLException {
String myOp = "GET";
String myQuery = "SELECT * FROM vosbackend.StoredFiles " +
"WHERE original_file_name=?";
FileRecord myParams = new FileRecord(orig_f_name, "", "", "");
myResult = excuteQuery(myOp, myQuery, myParams);
return myResult;
}
public boolean deleteFile(String orig_f_name)
throws VOSpaceBackendException, SQLException {
String myOp = "DELETE";
String myQuery = "DELETE FROM vosbackend.StoredFiles WHERE original_file_name=?";
FileRecord myParams = new FileRecord(orig_f_name, "", "", "");
myResult = excuteQuery(myOp, myQuery, myParams);
return (boolean)myResult.get("ifSuccessful");
}
private HashMap excuteQuery(String operation, String query, FileRecord fileToStore)
throws VOSpaceBackendException, SQLException {
PreparedStatement preparedStatementInsert = null;
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
log.debug("Database connection get");
} catch (SQLException e) {
log.fatal(e);
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(ExceptionMessage.getMessage("UNABLE_TO_GET_DB_CONNECTION"));
}
try {
dbConnection.setAutoCommit(false);
log.debug("Autocommit set false");
} catch (SQLException e) {
log.fatal(e);
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(ExceptionMessage.getMessage("ERROR_DISABLING_DB_AUTOCOMMIT"));
}
// Starts JDBC Transaction
PreparedStatement preparedQuery = null;
try {
HashMap fileToStoreFields = fileToStore.getFileRecord();
switch (operation) {
case "SET":
log.debug("Going to prepare query for SET operation");
preparedQuery = dbConnection.prepareStatement(query);
preparedQuery.setString(1, (String)fileToStoreFields.get("original_file_name"));
preparedQuery.setString(2, (String)fileToStoreFields.get("stored_file_name"));
preparedQuery.setString(3, (String)fileToStoreFields.get("md5_checksum"));
preparedQuery.setString(4, (String)fileToStoreFields.get("relative_path"));
log.debug("Going to execute query");
preparedQuery.executeUpdate();
log.debug("Query executed");
dbConnection.commit();
log.debug("Query committed");
myResult.put("ifSuccessful", true);
break;
case "GET":
preparedQuery = dbConnection.prepareStatement(query);
preparedQuery.setString(1, (String)fileToStoreFields.get("original_file_name"));
ResultSet rs = preparedQuery.executeQuery();
int rowCounter = 0;
while (rs.next()) {
rowCounter = rowCounter +1;
myResult.put("original_file_name", rs.getString("original_file_name"));
myResult.put("stored_file_name", rs.getString("stored_file_name"));
myResult.put("md5_checksum", rs.getString("md5_checksum"));
myResult.put("relative_path", rs.getString("relative_path"));
}
if (rowCounter == 0) {
log.debug("GET: query successfully executed. File not found");
myResult.put("ifSuccessful", false);
} else {
log.debug("GET: query successfully executed. File found");
myResult.put("ifSuccessful", true);
}
break;
case "DELETE":
preparedQuery = dbConnection.prepareStatement(query);
preparedQuery.setString(1, (String)fileToStoreFields.get("original_file_name"));
preparedQuery.executeUpdate();
dbConnection.commit();
myResult.put("ifSuccessful", true);
break;
default:
myResult.put("ifSuccessful", false);
ExceptionMessage exMsg = new ExceptionMessage();
log.fatal(ExceptionMessage.getMessage("DB_OPERATION_NOT_RECOGNIZED"));
throw new VOSpaceBackendException(ExceptionMessage.getMessage("DB_OPERATION_NOT_RECOGNIZED"));
}
dbConnection.setAutoCommit(true);
dbConnection.close();
} catch (SQLException e) {
log.error("SQLException exception executing SET file" + e.getMessage());
dbConnection.rollback();
} finally {
if (preparedQuery != null) {
preparedQuery.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
return myResult;
}
private Connection getDBConnection() throws SQLException, VOSpaceBackendException {
DataSource ds = this.getDataSource();
Connection dbConnection = ds.getConnection();
return dbConnection;
}
protected DataSource getDataSource() throws VOSpaceBackendException {
DataSource ds = null;
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
String vosNodesDataSourceName = "jdbc/vosbackend";
ds = (DataSource) envContext.lookup(vosNodesDataSourceName);
} catch (NamingException ex) {
log.fatal(ex);
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(ExceptionMessage.getMessage("DATABASE_DRIVER_NOT_FOUND"));
}
return ds;
}
}
package it.inaf.oats.vospacebackend.implementation;
import it.inaf.oats.vospacebackend.exceptions.ExceptionMessage;
import it.inaf.oats.vospacebackend.exceptions.VOSpaceBackendException;
import it.inaf.oats.vospacebackend.utils.ConfigReader;
import java.sql.SQLException;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.UUID;
import org.apache.log4j.Logger;
import org.apache.commons.io.FileUtils;
/**
*
* @author bertocco
*/
public class VOSpaceBackPosix implements VOSpaceBackend {
private static String documentRoot;
private static String tmpStorageRoot;
private static final String CONFIG_FILE_NAME = "VOSpace.properties";
private static final Logger log = Logger.getLogger(VOSpaceBackImplFactory.class);
public VOSpaceBackPosix() throws VOSpaceBackendException {
try {
ConfigReader myConf = new ConfigReader(CONFIG_FILE_NAME);
this.documentRoot = myConf.getProperty("fs.posix.document.root");
this.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"), CONFIG_FILE_NAME));
throw new VOSpaceBackendException(
MessageFormat.format(exMsg.getMessage("UNABLE_TO_READ_PROPERTIES"), CONFIG_FILE_NAME));
}
log.debug("VOSpace Backend Document Root = " + this.documentRoot);
log.debug("VOSpace Backend Temporary Document Root = " + this.tmpStorageRoot);
}
public boolean createFile(String orig_f_name, String tmp_file, String md5_sum)
throws VOSpaceBackendException, SQLException, IOException {
VOSpaceBackMetadata metadata = new VOSpaceBackMetadata();
String relativePath = this.createPathFromString(md5_sum);
// Needs syncronisation BEGIN
HashMap fileMetadata = metadata.setFile(orig_f_name, tmp_file, md5_sum, relativePath);
boolean result = (boolean)fileMetadata.get("ifSuccessful");
if (result) {
log.debug("File metadata successfully saved. I'm going to store the file content");
this.fileFromTmpToFinalStorageArea(tmp_file, relativePath, "MOVE");
} else
log.debug("File metadata NOT saved. Need to abort the operation");
// Needs syncronisation END
return result;
}
/* Retrieve the file, copy it in the temporary location, return the File */
public File returnFile(String orig_f_name)
throws VOSpaceBackendException, SQLException, IOException {
// Check if fileName is present in metadata DB
VOSpaceBackMetadata metadataDB = new VOSpaceBackMetadata();
HashMap myMetadata;
File outFile = null;
myMetadata = metadataDB.getFile(orig_f_name);
if ((boolean)myMetadata.get("ifSuccessful")) {
log.debug("Metadata record found for file " + orig_f_name);
log.debug("storedFileName = " + (String)myMetadata.get("stored_file_name"));
log.debug("relative_path = " + (String)myMetadata.get("relative_path"));
log.debug("md5_checksum = " + (String)myMetadata.get("md5_checksum"));
log.debug("original_file_name = " + (String)myMetadata.get("original_file_name"));
String storedFileName = (String)myMetadata.get("stored_file_name");
String relativePath = (String)myMetadata.get("relative_path");
String unique_file_id_str = UUID.randomUUID().toString();
// Needs syncronisation START
this.fileFromStorageAreaToTmp(storedFileName, unique_file_id_str, relativePath, "COPY");
outFile = new File(this.getTmpPath() + storedFileName);
return outFile;
// Needs syncronisation END
} else {
log.debug("Metadata record NOT found for file " + orig_f_name);
outFile = null;
return outFile;
}
}
public boolean deleteFile(String orig_f_name)
throws VOSpaceBackendException, SQLException {
boolean deleted = false;
// Check if fileName is present in metadata DB
VOSpaceBackMetadata metadataDB = new VOSpaceBackMetadata();
HashMap myMetadata;
File outFile = null;
myMetadata = metadataDB.getFile(orig_f_name);
log.debug("Value of ifSuccessful = " +(boolean)myMetadata.get("ifSuccessful"));
if ((boolean)myMetadata.get("ifSuccessful")) {
String storedFileName = (String)myMetadata.get("stored_file_name");
String relativePath = (String)myMetadata.get("relative_path");
File fileToDelete = new File(this.getStoragePath(relativePath) + storedFileName);
log.debug("I'm going to delete from DB the metadata set of file " + orig_f_name);
// Needs syncronisation START
metadataDB.deleteFile(orig_f_name);
log.debug("Metadata set of file " + orig_f_name + " successfully deleted from DB");
log.debug("I'm going to delete from file system " + fileToDelete);
deleted = fileToDelete.delete();
// Needs syncronisation END
if (deleted)
log.debug("File successfully deleted");
else
log.debug("Failed to delete the file");
} else {
log.debug("Failed to delete the file");
deleted = false;
}
return deleted;
}
public String createPathFromString(String initialStr) throws VOSpaceBackendException{
log.debug("initialStr = " + initialStr);
log.debug("initialStr.substring(initialStr.length()-2, initialStr.length())" + initialStr.substring(initialStr.length()-2));
log.debug("initialStr.length()-4, initialStr.length()-2)" + initialStr.substring(initialStr.length()-4, initialStr.length()-2));
String relativePath = null;
try{
relativePath = new String(File.separator +
initialStr.substring(initialStr.length()-4, initialStr.length()-2) +
File.separator +
initialStr.substring(initialStr.length()-2, initialStr.length()));
} catch (Exception e) {
log.debug("Exception creating partial path from string " + initialStr);
throw new VOSpaceBackendException(e);
}
log.debug("relative path = " + relativePath);
return relativePath;
}
public void fileFromTmpToFinalStorageArea(String tmpfile, String relPath, String operation)
throws VOSpaceBackendException {
File tmpFile = new File(this.getTmpPath() + tmpfile);
File finalStoredFile = new File(this.getStoragePath(relPath) + tmpfile);
log.debug("tmpStoredFile is: " + tmpFile);
log.debug("finalStoredFile is: " + finalStoredFile);
this.operateOnFiles(tmpFile, finalStoredFile, operation);
}
public void fileFromStorageAreaToTmp(String stored, String tmp, String relativePath, String operation)
throws VOSpaceBackendException {
File storedFile = new File(this.getStoragePath(relativePath) + stored);
File tmpFile = new File(this.getTmpPath() + tmp);
log.debug("storedFile is: " + storedFile);
log.debug("tmpFile is: " + tmpFile);
this.operateOnFiles(storedFile, tmpFile, operation);
}
public void operateOnFiles (File A, File B, String operation) throws VOSpaceBackendException {
log.debug("File A is: " + A);
log.debug("File B is: " + B);
log.debug("Operation required is " + operation);
switch (operation) {
case "MOVE":
this.moveFileAToFileB(A, B);
break;
case "COPY":
this.copyFileAToFileB(A, B);
break;
default:
log.debug("Error in operation required");
throw new VOSpaceBackendException("Error in operation required");
}
}
public boolean checksBeforeCopyOrMove(File A, File B)
throws VOSpaceBackendException {
boolean checkOK = false;
if (!A.exists()) {
log.debug("Move operation impossible: source file" + A.getAbsolutePath()
+ "does not exists.");
throw new VOSpaceBackendException("Operation impossible: source file"
+ A.getAbsolutePath() + "does not exists.");
}
String absolutePathB = B.getAbsolutePath();
String pathB = absolutePathB.substring(0,absolutePathB.lastIndexOf(File.separator));
File pathBFile = new File(pathB);
if (!pathBFile.exists()) {
try {
checkOK = pathBFile.mkdirs();
} catch (Exception e) {
log.debug("Exception creating the final destination directory of file "
+ B.getAbsolutePath());
throw new VOSpaceBackendException(e);
}
} else if (pathBFile.isDirectory()){
checkOK = true;
} else {
log.debug("File " + pathB + " already exsists, but is not a directory.");
checkOK = false;
}
return checkOK;
}
public void moveFileAToFileB (File A, File B) throws VOSpaceBackendException {
if (this.checksBeforeCopyOrMove(A, B)) {
try {
FileUtils.moveFile(A, B);
} catch (Exception e) {
log.debug("Exception moving temporary copy of uploaded file in its final destination directory");
throw new VOSpaceBackendException(e);
}
}
}
public void copyFileAToFileB (File A, File B) throws VOSpaceBackendException {
if (this.checksBeforeCopyOrMove(A, B)) {
try {
FileUtils.copyFile(A, B);
} catch (Exception e) {
log.debug("Exception moving temporary copy of uploaded file in its final destination directory");
throw new VOSpaceBackendException(e);
}
}
}
private String getStoragePath(String relativePath) {
String storagePath = this.documentRoot + relativePath + File.separator;
return storagePath;
}
private String getTmpPath() {
String tmpFilePath = this.tmpStorageRoot + File.separator;
return tmpFilePath;
}
}
package it.inaf.oats.vospacebackend.implementation;
import it.inaf.oats.vospacebackend.exceptions.VOSpaceBackendException;
import java.io.IOException;
import java.io.File;
import java.sql.SQLException;
/**
*
* @author bertocco
*/
public interface VOSpaceBackend {
public boolean createFile(String orig_f_name, String tmp_file, String md5_sum)
throws VOSpaceBackendException, SQLException, IOException;
public File returnFile(String orig_f_name)
throws VOSpaceBackendException, SQLException, IOException;
public boolean deleteFile(String orig_f_name)
throws VOSpaceBackendException, SQLException;
}
package it.inaf.oats.vospacebackend.utils;
import it.inaf.oats.vospacebackend.exceptions.VOSpaceBackendException;
import it.inaf.oats.vospacebackend.exceptions.ExceptionMessage;
import java.util.HashMap;
import java.util.Properties;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.text.MessageFormat;
import org.apache.log4j.Logger;
public class ConfigReader {
private static final String DEFAULT_CONFIG_DIR = System.getProperty("user.home")
+ File.separator + "config"
+ File.separator;
private String fullPropFileName = new String();
private static HashMap readProperties = new HashMap<String, String>();
protected static Logger log = Logger.getLogger(ConfigReader.class);
public ConfigReader(String propertiesFile) throws VOSpaceBackendException {
fullPropFileName = DEFAULT_CONFIG_DIR + propertiesFile;
try (InputStream in = new FileInputStream(fullPropFileName)) {
Properties prop = new Properties();
prop.load(in);
for (String key : prop.stringPropertyNames()) {
String value = prop.getProperty(key);
readProperties.put(key, value);
log.debug("Reading properties from " + fullPropFileName);
log.debug(key + " = " + value);
}
} catch (IOException e) {
ExceptionMessage exMsg = new ExceptionMessage();
log.fatal(org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(e));
throw new VOSpaceBackendException(
MessageFormat.format(exMsg.getMessage("UNABLE_TO_READ_PROPERTIES"), fullPropFileName));
}
}
public String getProperty(String key) throws VOSpaceBackendException {
String property = "";
try {
property = (String)readProperties.get(key);
log.debug("Getting property:");
log.debug(property);
} catch (Exception e) {
log.fatal(org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(e));
ExceptionMessage exMsg = new ExceptionMessage();
throw new VOSpaceBackendException(
MessageFormat.format(exMsg.getMessage("PROPERTY_NOT_FOUND"), key, fullPropFileName));
}
return property;
}
}
package it.inaf.oats.vospacebackend.utils;
import java.util.HashMap;
import org.apache.log4j.Logger;
import ca.nrc.cadc.vos.VOSURI;
/**
*
* @author bertocco
*/
public class VOSURIParser {
private String scheme;
private String namingAuthority;
private String query;
private String path;
private HashMap content;
protected Logger log;
public VOSURIParser() {
log = Logger.getLogger(VOSURIParser.class);
scheme = new String("");
namingAuthority = new String("");
query = new String("");
path = new String("");
content = new <String, String>HashMap();
content.put("scheme", "");
content.put("namingAuthority", "");
content.put("query", "");
content.put("path", "");
}
public VOSURIParser(VOSURI vosuri) throws Exception {
log = Logger.getLogger(VOSURIParser.class);
content = this.parse(vosuri);
scheme = (String)content.get("scheme");
namingAuthority = (String)content.get("namingAuthority");
query = (String)content.get("query");
path = (String)content.get("path");
}
public HashMap parse(VOSURI vosuri) throws Exception {
String myScheme = new String("");
String myNamingAuthority = new String("");
String myQuery = new String("");
String myPath = new String("");
String vosuriStr = vosuri.toString();
String mainSeparator = "://";
String exclamationMark = "!";
String tilde = "~";
boolean useExclamationMark = false;
boolean useTilde = false;
if(vosuriStr != null && vosuriStr.length() > 0 ) {
if (vosuriStr.contains(mainSeparator) &&
vosuriStr.contains(exclamationMark) || vosuriStr.contains(tilde)) {
log.debug("VOSURI " + vosuriStr + "well formed");
if (vosuriStr.contains(exclamationMark))
useExclamationMark = true;
if (vosuriStr.contains(tilde))
useTilde = true;
} else {
throw new Exception("Malformed URI received: " + vosuriStr);
}
myScheme = vosuriStr.substring(0, vosuriStr.indexOf(mainSeparator));
if(useExclamationMark)
myNamingAuthority =
vosuriStr.substring(vosuriStr.indexOf(mainSeparator)+3, vosuriStr.indexOf(exclamationMark));
if(useTilde)
myNamingAuthority =
vosuriStr.substring(vosuriStr.indexOf(mainSeparator)+3, vosuriStr.indexOf(tilde));
// Remove fragment if present
String vosuriWithoutFragment;
int endIndex = vosuriStr.lastIndexOf("#");
if (endIndex != -1) {
vosuriWithoutFragment = vosuriStr.substring(0, endIndex);
} else {
log.debug("URI without fragment received: " + vosuriStr);
vosuriWithoutFragment = vosuriStr;
}
// get path as the part of the string after the last occurrence of "/"
if (vosuriWithoutFragment != null && vosuriWithoutFragment.length() > 0 ) {
endIndex = vosuriWithoutFragment.lastIndexOf("/");
if (endIndex != -1) {
myPath = vosuriWithoutFragment.substring(endIndex+1, vosuriWithoutFragment.length());
}
} else {
throw new Exception("Malformed URI received: " + vosuriStr);
}
} else {
throw new Exception("Malformed URI received: " + vosuriStr);
}
content.put("scheme", myScheme);
content.put("namingAuthority", myNamingAuthority);
content.put("query", "");
content.put("path", myPath);
return content;
}
}
# VOSpace Backend Implementation to be used
it.inaf.oats.vospacebackendimplementation.VOSpaceBackendImpl = it.inaf.oats.vospacebackend.implementation.VOSpaceBackPosix
# VOSpace with posix backend Document Root
fs.posix.document.root = /home/bertocco/vospace
# VOSpace with posix backend Temporary storage area
fs.posix.tmp.storage.root = /tmp/vospace
CREATE DATABASE vosbackend;
use vosbackend;
grant all on vosbackend.* to 'vosbackadmin' identified by 'Peper0ne';
CREATE TABLE StoredFiles
(
fileID int NOT NULL AUTO_INCREMENT,
original_file_name varchar(255) NOT NULL,
stored_file_name varchar(36) NOT NULL,
md5_checksum varchar(36) NOT NULL,
relative_path varchar(8),
PRIMARY KEY (fileID)
) ENGINE=InnoDB;
ALTER TABLE StoredFiles ADD INDEX f_name (original_file_name);
package test;
import java.util.HashMap;
import ca.nrc.cadc.vos.VOSURI;
import it.inaf.oats.vospacebackend.utils.VOSURIParser;
/**
*
* @author bertocco
*/
public class VOSURIParserTest {
public VOSURIParserTest() {
}
public static void main(String[] args) {
String uriStr = "vos://nvo.caltech!vospace/myresults/siap-out-1.vot";
try {
VOSURI myvosuri = new VOSURI(uriStr);
VOSURIParser parser = new VOSURIParser();
HashMap parsingRes = parser.parse(myvosuri);
System.out.println("scheme = " + (String)parsingRes.get("scheme"));
System.out.println("namingAuthority = " + (String)parsingRes.get("namingAuthority"));
System.out.println("query = " + (String)parsingRes.get("query"));
System.out.println("path = " + (String)parsingRes.get("path"));
} catch (Exception e) {
System.out.println("Exception in VOSURIParserTest main");
e.printStackTrace();
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/vospaceBackend" docBase="vospace"
crossContext="true" reloadable="true" debug="1">
<Resource name="jdbc/vosbackend"
auth="Container"
type="javax.sql.DataSource"
username="vosbackadmin" password="Peper0ne"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/vosbackend"
maxActive="10"
maxWait="-1"
maxIdle="4" />
</Context>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment