diff --git a/src/main/java/se/su/dsv/scipro/data/controllers/impl/FinalSeminarUploadControllerImpl.java b/src/main/java/se/su/dsv/scipro/data/controllers/impl/FinalSeminarUploadControllerImpl.java index ab1d88b066..c010bb8378 100644 --- a/src/main/java/se/su/dsv/scipro/data/controllers/impl/FinalSeminarUploadControllerImpl.java +++ b/src/main/java/se/su/dsv/scipro/data/controllers/impl/FinalSeminarUploadControllerImpl.java @@ -84,13 +84,15 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr public void deleteSeminarFilesRecursive(final FinalSeminar seminar) throws FileStorageException { 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 { 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"); } - String path = getRepositorySeminarPath(seminar); + //String path = getRepositorySeminarPath(seminar); Deprecated method call + String path = fileRepository.getFinalSeminarPath(seminar.getId()); FileDescription fd = null; try { 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"); } FileDescription fd = null; - String path = getRepositoryOppositionPath(opposition); - + //String path = getRepositoryOppositionPath(opposition); Deprecated method call + String path = fileRepository.getFinalSeminarOppositionPath(opposition.getId()); + try { fd = store(upload, path); fd = fileDescriptionDao.save(fd); @@ -239,7 +243,11 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr 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) { return fileRepository.getRepositoryRootPath() + FINAL_SEMINAR_DIRECTORY + String.valueOf(seminar.getId()) + "/"; @@ -249,11 +257,8 @@ public class FinalSeminarUploadControllerImpl implements FinalSeminarUploadContr return getRepositorySeminarPath(o.getFinalSeminar()) + FINAL_SEMINAR_OPPOSITION_DIRECTORY + String.valueOf(o.getId()) + "/"; } - - - - - +*/ + } diff --git a/src/main/java/se/su/dsv/scipro/data/dataobjects/FileDescription.java b/src/main/java/se/su/dsv/scipro/data/dataobjects/FileDescription.java index 95487ca2f7..78229a9600 100644 --- a/src/main/java/se/su/dsv/scipro/data/dataobjects/FileDescription.java +++ b/src/main/java/se/su/dsv/scipro/data/dataobjects/FileDescription.java @@ -2,7 +2,9 @@ package se.su.dsv.scipro.data.dataobjects; import java.util.Date; +import javax.persistence.Basic; import javax.persistence.Cacheable; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @@ -24,6 +26,7 @@ import org.hibernate.annotations.Index; public class FileDescription extends DomainObject implements Comparable<FileDescription>{ private static final long serialVersionUID = 1L; + public static final int PATH_MAX_LENGTH = 255; @Id @GeneratedValue @@ -35,6 +38,7 @@ public class FileDescription extends DomainObject implements Comparable<FileDesc @Index(name="file_description_identifier_index") //Hibernate specific, just for performance private String identifier; @Index(name="file_description_path_index") //Hibernate specific, just for performance + @Column(length=PATH_MAX_LENGTH) private String path; private Long userId = null; private Long size; diff --git a/src/main/java/se/su/dsv/scipro/repository/FileRepository.java b/src/main/java/se/su/dsv/scipro/repository/FileRepository.java index 074f609cab..daa5bc191f 100644 --- a/src/main/java/se/su/dsv/scipro/repository/FileRepository.java +++ b/src/main/java/se/su/dsv/scipro/repository/FileRepository.java @@ -161,6 +161,18 @@ public interface FileRepository { * @return */ 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 * @param list diff --git a/src/main/java/se/su/dsv/scipro/repository/FileRepositoryImpl.java b/src/main/java/se/su/dsv/scipro/repository/FileRepositoryImpl.java index 430c635031..ba01f48d6a 100644 --- a/src/main/java/se/su/dsv/scipro/repository/FileRepositoryImpl.java +++ b/src/main/java/se/su/dsv/scipro/repository/FileRepositoryImpl.java @@ -62,14 +62,19 @@ import eu.medsea.mimeutil.detector.ExtensionMimeDetector; @Repository public class FileRepositoryImpl implements FileRepository { + protected static final int STANDARD_INTERVAL_LENGTH = 100; protected static final String ROOT_PATH = "root/"; protected static final String PROJECTS_PATH = "projects/"; 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) private RepositoryManager repositoryManager; public String storeFile(String name, String mimeType, InputStream fileStream) { + if (StringUtils.isEmpty(name)) { return null; } @@ -89,6 +94,9 @@ public class FileRepositoryImpl implements FileRepository { Node folder = RepositoryHelper.findOrCreateFolder(session, splitWithoutFile, rootNode); 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"); Node fileContent = file.addNode ("jcr:content", "nt:resource"); fileContent.addMixin("mix:referenceable"); @@ -384,35 +392,37 @@ public class FileRepositoryImpl implements FileRepository { } 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+). - * @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 */ - protected String getProjectSubFolder(Long projectId){ - int intervalLength = 100; - Long startId = ( projectId / intervalLength ) * intervalLength; + protected String getIntervalSubFolder(final Long id, final int intervalLength){ + if(id == null) + 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; - String result = startId.toString() + "-" + endId.toString() + "/" + projectId.toString() +"/"; + String result = startId.toString() + "-" + endId.toString() + "/" + id.toString() +"/"; return result; } public String getResourcePath(Long fileResourceId){ if(fileResourceId == null) 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); - } - - 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; + return ROOT_PATH+RESOURCES_PATH+getIntervalSubFolder(fileResourceId, 1000); //TODO If resources are ever used with files, make this a static constant } @Override diff --git a/src/main/java/se/su/dsv/scipro/repository/panels/AbstractFilePanel.java b/src/main/java/se/su/dsv/scipro/repository/panels/AbstractFilePanel.java index 038c32e308..1b511bd941 100644 --- a/src/main/java/se/su/dsv/scipro/repository/panels/AbstractFilePanel.java +++ b/src/main/java/se/su/dsv/scipro/repository/panels/AbstractFilePanel.java @@ -416,13 +416,21 @@ public abstract class AbstractFilePanel extends Panel { protected void onSubmit() { final FileUpload upload = fileUploadField.getFileUpload(); - fileRepository.storeFile(upload, absolutePath); - - setRedirect(true); - - pp.put("i", relativePath.replaceAll("/", ".")); - - setResponsePage(fpc.getSurroundingPageClass(), pp); + try{ + fileRepository.storeFile(upload, absolutePath); + + setRedirect(true); + pp.put("i", relativePath.replaceAll("/", ".")); + 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()); + } + } } } }