Future-proofing of final-seminar file paths
Change-Id: Ib2c46c6015c7f42454bb04129309ad96e214aefe
This commit is contained in:
parent
1f8425dce7
commit
9f59204df8
src/main/java/se/su/dsv/scipro
data
repository
@ -84,13 +84,15 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr
|
|||||||
|
|
||||||
public void deleteSeminarFilesRecursive(final FinalSeminar seminar) throws FileStorageException {
|
public void deleteSeminarFilesRecursive(final FinalSeminar seminar) throws FileStorageException {
|
||||||
if (seminar.getDocument() != null) {
|
if (seminar.getDocument() != null) {
|
||||||
delete(getRepositorySeminarPath(seminar));
|
//delete(getRepositorySeminarPath(seminar)); Use of deprecated path/method
|
||||||
|
delete(seminar.getDocument().getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteOpponentFiles(final FinalSeminarOpposition opp) throws FileStorageException {
|
public void deleteOpponentFiles(final FinalSeminarOpposition opp) throws FileStorageException {
|
||||||
if (opp.getOpponentReport() != null) {
|
if (opp.getOpponentReport() != null) {
|
||||||
delete(getRepositoryOppositionPath(opp));
|
//delete(getRepositoryOppositionPath(opp)); Use of deprecated path/method
|
||||||
|
delete(opp.getOpponentReport().getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +141,8 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr
|
|||||||
throw new RuntimeException("The file must be a PDF");
|
throw new RuntimeException("The file must be a PDF");
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = getRepositorySeminarPath(seminar);
|
//String path = getRepositorySeminarPath(seminar); Deprecated method call
|
||||||
|
String path = fileRepository.getFinalSeminarPath(seminar.getId());
|
||||||
FileDescription fd = null;
|
FileDescription fd = null;
|
||||||
try {
|
try {
|
||||||
fd = store(upload, path);
|
fd = store(upload, path);
|
||||||
@ -200,8 +203,9 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr
|
|||||||
throw new IllegalStateException("Non other than the opponent can upload an opposition");
|
throw new IllegalStateException("Non other than the opponent can upload an opposition");
|
||||||
}
|
}
|
||||||
FileDescription fd = null;
|
FileDescription fd = null;
|
||||||
String path = getRepositoryOppositionPath(opposition);
|
//String path = getRepositoryOppositionPath(opposition); Deprecated method call
|
||||||
|
String path = fileRepository.getFinalSeminarOppositionPath(opposition.getId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fd = store(upload, path);
|
fd = store(upload, path);
|
||||||
fd = fileDescriptionDao.save(fd);
|
fd = fileDescriptionDao.save(fd);
|
||||||
@ -239,7 +243,11 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr
|
|||||||
throw new Exception(e);
|
throw new Exception(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following two methods are deprecated and should not be used, they are left here because the
|
||||||
|
* production system has data generated using these old path-methods. //MP
|
||||||
|
*
|
||||||
private String getRepositorySeminarPath(FinalSeminar seminar) {
|
private String getRepositorySeminarPath(FinalSeminar seminar) {
|
||||||
return fileRepository.getRepositoryRootPath() + FINAL_SEMINAR_DIRECTORY
|
return fileRepository.getRepositoryRootPath() + FINAL_SEMINAR_DIRECTORY
|
||||||
+ String.valueOf(seminar.getId()) + "/";
|
+ String.valueOf(seminar.getId()) + "/";
|
||||||
@ -249,11 +257,8 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr
|
|||||||
return getRepositorySeminarPath(o.getFinalSeminar()) + FINAL_SEMINAR_OPPOSITION_DIRECTORY
|
return getRepositorySeminarPath(o.getFinalSeminar()) + FINAL_SEMINAR_OPPOSITION_DIRECTORY
|
||||||
+ String.valueOf(o.getId()) + "/";
|
+ String.valueOf(o.getId()) + "/";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@ package se.su.dsv.scipro.data.dataobjects;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
import javax.persistence.Cacheable;
|
import javax.persistence.Cacheable;
|
||||||
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
@ -24,6 +26,7 @@ import org.hibernate.annotations.Index;
|
|||||||
public class FileDescription extends DomainObject implements Comparable<FileDescription>{
|
public class FileDescription extends DomainObject implements Comparable<FileDescription>{
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
public static final int PATH_MAX_LENGTH = 255;
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
@ -35,6 +38,7 @@ public class FileDescription extends DomainObject implements Comparable<FileDesc
|
|||||||
@Index(name="file_description_identifier_index") //Hibernate specific, just for performance
|
@Index(name="file_description_identifier_index") //Hibernate specific, just for performance
|
||||||
private String identifier;
|
private String identifier;
|
||||||
@Index(name="file_description_path_index") //Hibernate specific, just for performance
|
@Index(name="file_description_path_index") //Hibernate specific, just for performance
|
||||||
|
@Column(length=PATH_MAX_LENGTH)
|
||||||
private String path;
|
private String path;
|
||||||
private Long userId = null;
|
private Long userId = null;
|
||||||
private Long size;
|
private Long size;
|
||||||
|
@ -161,6 +161,18 @@ public interface FileRepository {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
String getResourcePath(Long fileResourceId);
|
String getResourcePath(Long fileResourceId);
|
||||||
|
/**
|
||||||
|
* Get the repository path associated with a certain FinalSeminar
|
||||||
|
* @param finalSeminarId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String getFinalSeminarPath(Long finalSeminarId);
|
||||||
|
/**
|
||||||
|
* Get the repository path associated with a certain FinalSeminarOpposition
|
||||||
|
* @param finalSeminarOppositionId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String getFinalSeminarOppositionPath(Long finalSeminarOppositionId);
|
||||||
/**
|
/**
|
||||||
* Convenience method to sort folders according to the input parameters
|
* Convenience method to sort folders according to the input parameters
|
||||||
* @param list
|
* @param list
|
||||||
|
@ -62,14 +62,19 @@ import eu.medsea.mimeutil.detector.ExtensionMimeDetector;
|
|||||||
@Repository
|
@Repository
|
||||||
public class FileRepositoryImpl implements FileRepository {
|
public class FileRepositoryImpl implements FileRepository {
|
||||||
|
|
||||||
|
protected static final int STANDARD_INTERVAL_LENGTH = 100;
|
||||||
protected static final String ROOT_PATH = "root/";
|
protected static final String ROOT_PATH = "root/";
|
||||||
protected static final String PROJECTS_PATH = "projects/";
|
protected static final String PROJECTS_PATH = "projects/";
|
||||||
protected static final String RESOURCES_PATH = "resources/";
|
protected static final String RESOURCES_PATH = "resources/";
|
||||||
|
protected static final String FINAL_SEMINAR_ROOT_PATH = "final_seminars/";
|
||||||
|
protected static final String FINAL_SEMINARS_PATH = "final_seminar_reports/";
|
||||||
|
protected static final String FINAL_SEMINAR_OPPOSITION_REPORT_PATH = "opposition_reports/";
|
||||||
|
|
||||||
@Autowired(required=false)
|
@Autowired(required=false)
|
||||||
private RepositoryManager repositoryManager;
|
private RepositoryManager repositoryManager;
|
||||||
|
|
||||||
public String storeFile(String name, String mimeType, InputStream fileStream) {
|
public String storeFile(String name, String mimeType, InputStream fileStream) {
|
||||||
|
|
||||||
if (StringUtils.isEmpty(name)) {
|
if (StringUtils.isEmpty(name)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -89,6 +94,9 @@ public class FileRepositoryImpl implements FileRepository {
|
|||||||
Node folder = RepositoryHelper.findOrCreateFolder(session, splitWithoutFile, rootNode);
|
Node folder = RepositoryHelper.findOrCreateFolder(session, splitWithoutFile, rootNode);
|
||||||
|
|
||||||
Node file = folder.addNode(itemName, "nt:file");
|
Node file = folder.addNode(itemName, "nt:file");
|
||||||
|
if( file.getPath().length() > FileDescription.PATH_MAX_LENGTH ){
|
||||||
|
throw new IllegalStateException("Trying to store a node with a path length that is too long");
|
||||||
|
}
|
||||||
file.addMixin("sp:fileMixin");
|
file.addMixin("sp:fileMixin");
|
||||||
Node fileContent = file.addNode ("jcr:content", "nt:resource");
|
Node fileContent = file.addNode ("jcr:content", "nt:resource");
|
||||||
fileContent.addMixin("mix:referenceable");
|
fileContent.addMixin("mix:referenceable");
|
||||||
@ -384,35 +392,37 @@ public class FileRepositoryImpl implements FileRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getProjectRootPath(Long projectId){
|
public String getProjectRootPath(Long projectId){
|
||||||
return ROOT_PATH+PROJECTS_PATH+getProjectSubFolder(projectId);
|
return ROOT_PATH+PROJECTS_PATH+getIntervalSubFolder(projectId, STANDARD_INTERVAL_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFinalSeminarPath(Long finalSeminarId){
|
||||||
|
return ROOT_PATH+FINAL_SEMINAR_ROOT_PATH+FINAL_SEMINARS_PATH+getIntervalSubFolder(finalSeminarId, STANDARD_INTERVAL_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFinalSeminarOppositionPath(Long finalSeminarOppositionId){
|
||||||
|
return ROOT_PATH+FINAL_SEMINAR_ROOT_PATH+FINAL_SEMINAR_OPPOSITION_REPORT_PATH+getIntervalSubFolder(finalSeminarOppositionId, STANDARD_INTERVAL_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to split the projects folder into subfolders containing projects. Precaution because jackrabbit can
|
* Method used to split the folders into subfolders containing for example projects. Precaution because jackrabbit can
|
||||||
* get slow when faced with huge number of subnodes in one node (10.000+).
|
* get slow when faced with huge number of subnodes in one node (10.000+).
|
||||||
* @param projectId id of the project, for example 54
|
* @param id id of the domain object used as key, for example projectId, for example 54
|
||||||
|
* @param intervalLength, should be a CONSTANT for any given uses
|
||||||
* @return result looking like for example: "0-99/54
|
* @return result looking like for example: "0-99/54
|
||||||
*/
|
*/
|
||||||
protected String getProjectSubFolder(Long projectId){
|
protected String getIntervalSubFolder(final Long id, final int intervalLength){
|
||||||
int intervalLength = 100;
|
if(id == null)
|
||||||
Long startId = ( projectId / intervalLength ) * intervalLength;
|
throw new IllegalStateException("Attempting to calculate a repository path using a null-id, that's not allowed!");
|
||||||
|
Long startId = ( id / intervalLength ) * intervalLength;
|
||||||
Long endId = startId + intervalLength - 1;
|
Long endId = startId + intervalLength - 1;
|
||||||
String result = startId.toString() + "-" + endId.toString() + "/" + projectId.toString() +"/";
|
String result = startId.toString() + "-" + endId.toString() + "/" + id.toString() +"/";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getResourcePath(Long fileResourceId){
|
public String getResourcePath(Long fileResourceId){
|
||||||
if(fileResourceId == null)
|
if(fileResourceId == null)
|
||||||
throw new NullPointerException("Null value for FileResource-id cannot generate a valid path to store a file resource!");
|
throw new NullPointerException("Null value for FileResource-id cannot generate a valid path to store a file resource!");
|
||||||
return ROOT_PATH+RESOURCES_PATH+getResourceSubFolder(fileResourceId);
|
return ROOT_PATH+RESOURCES_PATH+getIntervalSubFolder(fileResourceId, 1000); //TODO If resources are ever used with files, make this a static constant
|
||||||
}
|
|
||||||
|
|
||||||
protected String getResourceSubFolder(Long fileResourceId){
|
|
||||||
int intervalLength = 1000;
|
|
||||||
Long startId = ( fileResourceId / intervalLength ) * intervalLength;
|
|
||||||
Long endId = startId + intervalLength - 1;
|
|
||||||
String result = startId.toString() + "-" + endId.toString() + "/" + fileResourceId.toString() +"/";
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -416,13 +416,21 @@ public abstract class AbstractFilePanel extends Panel {
|
|||||||
protected void onSubmit() {
|
protected void onSubmit() {
|
||||||
final FileUpload upload = fileUploadField.getFileUpload();
|
final FileUpload upload = fileUploadField.getFileUpload();
|
||||||
|
|
||||||
fileRepository.storeFile(upload, absolutePath);
|
try{
|
||||||
|
fileRepository.storeFile(upload, absolutePath);
|
||||||
setRedirect(true);
|
|
||||||
|
setRedirect(true);
|
||||||
pp.put("i", relativePath.replaceAll("/", "."));
|
pp.put("i", relativePath.replaceAll("/", "."));
|
||||||
|
setResponsePage(fpc.getSurroundingPageClass(), pp);
|
||||||
setResponsePage(fpc.getSurroundingPageClass(), pp);
|
|
||||||
|
} catch (FileStorageException fse){
|
||||||
|
if(fse.getCause().getClass().equals(IllegalStateException.class)){
|
||||||
|
error("Cannot save file into this directory, the resulting path is to long/deep. Try a shorter name or a different directory.");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
error(fse.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user