diff --git a/ccm-cms/pom.xml b/ccm-cms/pom.xml index c89a0d3de..b506844a3 100644 --- a/ccm-cms/pom.xml +++ b/ccm-cms/pom.xml @@ -71,6 +71,12 @@ provided + + org.jboss.resteasy + resteasy-multipart-provider + provided + + javax.mvc javax.mvc-api diff --git a/ccm-cms/src/main/java/org/librecms/assets/FileAsset.java b/ccm-cms/src/main/java/org/librecms/assets/FileAsset.java index 903931be9..c7103c2a0 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/FileAsset.java +++ b/ccm-cms/src/main/java/org/librecms/assets/FileAsset.java @@ -18,10 +18,16 @@ */package org.librecms.assets; import com.arsdigita.cms.ui.assets.forms.FileAssetForm; + import java.io.Serializable; + import javax.persistence.Entity; import javax.persistence.Table; + import org.hibernate.envers.Audited; +import org.librecms.ui.contentsections.assets.FileAssetCreateStep; +import org.librecms.ui.contentsections.assets.FileAssetEditStep; +import org.librecms.ui.contentsections.assets.MvcAssetEditKit; import static org.librecms.CmsConstants.*; import static org.librecms.assets.AssetConstants.*; @@ -39,6 +45,10 @@ import static org.librecms.assets.AssetConstants.*; labelBundle = ASSETS_BUNDLE, descriptionKey = "fileasset.description", descriptionBundle = ASSETS_BUNDLE) +@MvcAssetEditKit( + createStep = FileAssetCreateStep.class, + editStep = FileAssetEditStep.class +) public class FileAsset extends BinaryAsset implements Serializable { private static final long serialVersionUID = -8195062456502964401L; diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/AssetFolderController.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/AssetFolderController.java index dc7684ea7..9e06de158 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/AssetFolderController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/AssetFolderController.java @@ -39,6 +39,7 @@ import org.librecms.ui.contentsections.assets.MvcAssetCreateStep; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -274,15 +275,21 @@ public class AssetFolderController { assetFolderTree.buildFolderTree(section, folder) ); - contentSectionModel.setAvailableAssetTypes( - assetCreateSteps - .stream() - .collect( - Collectors.toMap( - step -> step.getAssetType(), - step -> step.getLabel() - ) + contentSectionModel.setAvailableAssetTypes(assetCreateSteps + .stream() + .sorted( + (step1, step2) -> step1.getLabel().compareTo( + step2.getLabel() ) + ) + .collect( + Collectors.toMap( + step -> step.getAssetType(), + step -> step.getLabel(), + (value1, value2) -> value1, + () -> new LinkedHashMap<>() + ) + ) ); assetFolderModel.setRows( @@ -665,11 +672,11 @@ public class AssetFolderController { row.setFolderPath( folderManager .getFolderPath(folder) -// .substring( -// folderManager -// .getFolderPath(section.getRootAssetsFolder()) -// .length() -// ) + // .substring( + // folderManager + // .getFolderPath(section.getRootAssetsFolder()) + // .length() + // ) ); row.setName(entry.getDisplayName()); row.setTitle( diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AssetUi.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AssetUi.java index b33430572..d1e8b94e2 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AssetUi.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AssetUi.java @@ -66,7 +66,7 @@ public class AssetUi { ) { models.put("section", section.getLabel()); models.put("assetPath", assetPath); - return "/org/librecms/ui/contentsection/assets/asset-not-found.xhtml"; + return "org/librecms/ui/contentsection/assets/asset-not-found.xhtml"; } } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java index 1c5c674ab..f3432a721 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java @@ -32,6 +32,7 @@ public class CmsAssetEditSteps implements MvcAssetEditSteps { final Set> classes = new HashSet<>(); classes.add(BookmarkEditStep.class); + classes.add(FileAssetEditStep.class); classes.add(LegalMetadataEditStep.class); classes.add(PostalAddressEditStep.class); classes.add(SideNoteEditStep.class); diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStep.java index 355ec3a62..766038b51 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStep.java @@ -20,6 +20,8 @@ package org.librecms.ui.contentsections.assets; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jboss.resteasy.plugins.providers.multipart.InputPart; +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.AuthorizationRequired; import org.librecms.assets.FileAsset; @@ -33,9 +35,12 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLConnection; -import java.util.Arrays; +import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.logging.Level; import java.util.stream.Collectors; import javax.activation.MimeType; @@ -44,8 +49,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.mvc.Controller; import javax.mvc.Models; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.Part; import javax.transaction.Transactional; import javax.ws.rs.Consumes; @@ -54,8 +57,8 @@ import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; /** * @@ -135,17 +138,22 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep { ); editStepModel.setFileName(getFileAsset().getFileName()); - editStepModel.setMimeType(getFileAsset().getMimeType().toString()); + editStepModel.setMimeType( + Optional + .ofNullable(getFileAsset().getMimeType()) + .map(MimeType::toString) + .orElse("") + ); editStepModel.setSize(getFileAsset().getSize()); - + final long size = getFileAsset().getSize(); if (size < 2048) { editStepModel.setSizeLabel(String.format("%d Bytes", size)); - } else if(size < 1024 * 1024) { + } else if (size < 1024 * 1024) { editStepModel.setSizeLabel( String.format("%d kB", size / 1024) ); - } else if (size < 1024 * 1024 * 1024){ + } else if (size < 1024 * 1024 * 1024) { editStepModel.setSizeLabel( String.format("%d MB", size / (1024 * 1024)) ); @@ -313,12 +321,12 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep { @Consumes(MediaType.MULTIPART_FORM_DATA) @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) - public String removeDescription( + public String uploadFile( @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) final String sectionIdentifier, @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) final String assetPath, - @Context final HttpServletRequest request + final MultipartFormDataInput input ) { try { init(); @@ -331,61 +339,54 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep { if (assetPermissionsChecker.canEditAsset(getAsset())) { final FileAsset fileAsset = getFileAsset(); + final Map> uploadForm = input + .getFormDataMap(); + final List inputParts = uploadForm.get("fileData"); + final Part part; - final String fileName; - try { - part = request.getPart("file"); - final String contentDisposition = part.getHeader( - "content-disposition" - ); - fileName = Arrays - .stream(contentDisposition.split(";")) - .filter(field -> field.startsWith("filename")) - .findAny() - .map( - field -> field - .substring(field.indexOf('=') + 1) - .trim().replace("\"", "") - ).orElse(""); - } catch (IOException | ServletException ex) { - LOGGER.error( - "Failed to upload file for FileAsset {}:", assetPath - ); - LOGGER.error(ex); - models.put("uploadFailed", true); - return buildRedirectPathForStep(); - } + String fileName = ""; + String contentType = ""; + for (final InputPart inputPart : inputParts) { + try { + final MultivaluedMap headers = inputPart + .getHeaders(); + fileName = getFileName(headers); + contentType = getContentType(headers); + final byte[] bytes = new byte[1024]; + try (InputStream inputStream = inputPart.getBody( + InputStream.class, null + ); + ByteArrayOutputStream fileDataOutputStream + = new ByteArrayOutputStream()) { + while (inputStream.read(bytes) != -1) { + fileDataOutputStream.writeBytes(bytes); + } - final byte[] bytes = new byte[1024]; - try (InputStream fileInputStream = part.getInputStream(); - ByteArrayOutputStream fileDataOutputStream - = new ByteArrayOutputStream()) { - while (fileInputStream.read(bytes) != -1) { - fileDataOutputStream.writeBytes(bytes); + fileAsset.setData(fileDataOutputStream.toByteArray()); + } + + } catch (IOException ex) { + LOGGER.error( + "Failed to upload file for FileAsset {}:", assetPath + ); + LOGGER.error(ex); + + models.put("uploadFailed", true); + return buildRedirectPathForStep(); } - - fileAsset.setData(fileDataOutputStream.toByteArray()); - } catch (IOException ex) { - LOGGER.error( - "Failed to upload file for FileAsset {}:", assetPath - ); - LOGGER.error(ex); - - models.put("uploadFailed", true); - return buildRedirectPathForStep(); } fileAsset.setFileName(fileName); fileAsset.setSize(fileAsset.getData().length); - try (BufferedInputStream stream = new BufferedInputStream( - new ByteArrayInputStream(fileAsset.getData()))) { - fileAsset.setMimeType( - new MimeType(URLConnection - .guessContentTypeFromStream(stream)) + try { + fileAsset.setMimeType(new MimeType(contentType)); + } catch (MimeTypeParseException ex) { + LOGGER.error( + "Failed to upload file for FileAsset {}:", assetPath ); - } catch (IOException | MimeTypeParseException ex) { - LOGGER.error("Failed to get file type.", ex); - models.put("failedToGetType", true); + LOGGER.error(ex); + + models.put("uploadFailed", true); return buildRedirectPathForStep(); } @@ -400,4 +401,26 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep { } } + private String getFileName(final MultivaluedMap headers) { + final String[] contentDisposition = headers + .getFirst("Content-Disposition") + .split(";"); + + for (final String fileName : contentDisposition) { + if (fileName.trim().startsWith("filename")) { + final String[] name = fileName.split("="); + + return name[1].trim().replaceAll("\"", ""); + } + } + + return ""; + } + + private String getContentType( + final MultivaluedMap headers + ) { + return headers.getFirst("Content-Type"); + } + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepModel.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepModel.java index cec18da9e..163b1ba9a 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepModel.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepModel.java @@ -37,7 +37,7 @@ public class FileAssetEditStepModel { private Map descriptionValues; - private List descriptionLocales; + private List unusedDescriptionLocales; private String fileName; @@ -57,14 +57,14 @@ public class FileAssetEditStepModel { this.descriptionValues = new HashMap<>(descriptionValues); } - public List getDescriptionLocales() { - return Collections.unmodifiableList(descriptionLocales); + public List getUnusedDescriptionLocales() { + return Collections.unmodifiableList(unusedDescriptionLocales); } protected void setUnusedDescriptionLocales( final List descriptionLocales ) { - this.descriptionLocales = new ArrayList<>(descriptionLocales); + this.unusedDescriptionLocales = new ArrayList<>(descriptionLocales); } public String getFileName() { diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/fileasset/edit-fileasset.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/fileasset/edit-fileasset.xhtml index acc1efc4f..1d1bab73f 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/fileasset/edit-fileasset.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/fileasset/edit-fileasset.xhtml @@ -34,7 +34,7 @@ editDialogValueLabel="#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.description.edit.value.label']}" editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@fileasset-edit/description/edit" editorId="description-editor" - hasUnusedLocales="#{!CmsFileAssetEditStep.unusedDescriptionLocales.isEmpty()}" + hasUnusedLocales="#{!CmsFileAssetEditStepModel.unusedDescriptionLocales.isEmpty()}" headingLevel="3" objectIdentifier="#{CmsSelectedAssetModel.assetPath}" readOnly="#{!MvcAssetEditStepModel.canEdit}" @@ -45,83 +45,85 @@ removeDialogTitle="#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.description.remove.title']}" removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@fileasset-edit/description/remove" title="#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.description.title']}" - unusedLocales="#{CmsFileAssetEditStep.unusedDescriptionLocales}" + unusedLocales="#{CmsFileAssetEditStepModel.unusedDescriptionLocales}" useTextarea="true" - values="#{CmsFileAssetEditStep.descriptionValues}" + values="#{CmsFileAssetEditStepModel.descriptionValues}" /> - - -

#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.title']}

- -
- -
- -
-
-
-
#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.name']}
-
#{CmsFileAssetEditStepModel.fileName}
-
-
-
#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.type']}
-
#{CmsFileAssetEditStepModel.mimeType}
-
-
-
#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.size']}
-
#{CmsFileAssetEditStepModel.sizeLabel}
-
-
+ +
+
+
#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.name']}
+
#{CmsFileAssetEditStepModel.fileName}
+
+
+
#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.type']}
+
#{CmsFileAssetEditStepModel.mimeType}
+
+
+
#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.size']}
+
#{CmsFileAssetEditStepModel.sizeLabel}
+
+
+ + diff --git a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties index 562566e5a..70b879e1b 100644 --- a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties +++ b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties @@ -207,3 +207,4 @@ fileasset.editstep.file.name=File name fileasset.editstep.file.type=File Type fileasset.editstep.file.size=File size editstep.legalmetadata.rights.remove.submit=Remove +fileasset.editstep.file.upload.label=Upload file diff --git a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties index f8f9a573d..4b1552dba 100644 --- a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties @@ -207,3 +207,4 @@ fileasset.editstep.file.name=Dateiname fileasset.editstep.file.type=Dateityp fileasset.editstep.file.size=Gr\u00f6\u00dfe der Datei editstep.legalmetadata.rights.remove.submit=Entfernen +fileasset.editstep.file.upload.label=Datei hochladen diff --git a/pom.xml b/pom.xml index 2f3a60d42..8fe73eb6c 100644 --- a/pom.xml +++ b/pom.xml @@ -534,6 +534,23 @@ 2.4.0-b180830.0438
+ + + org.jboss.resteasy + resteasy-core + 4.6.0.Final + + + org.jboss.resteasy + resteasy-multipart-provider + 3.14.0.Final + +