diff --git a/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java b/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java index 6e9562a20..ecc61b49d 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java +++ b/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java @@ -68,7 +68,6 @@ import static org.librecms.CmsConstants.*; + "FROM BinaryAsset a " + "LEFT JOIN a.permissions p " + "WHERE a.objectId = :assetId " - + "LEFT JOIN a.permissions p " + "AND (" + " (" + " p.grantee IN :roles " diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java index 3b1d87df1..d00893b84 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java @@ -337,7 +337,8 @@ public class Assets { final ProvidesPropertiesForAssetTypeLiteral literal = new ProvidesPropertiesForAssetTypeLiteral( - asset.getClass()); + asset.getClass() + ); final Instance instance = assetPropertiesProviders diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java new file mode 100644 index 000000000..ad2d28f47 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection.rs; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.librecms.assets.BinaryAssetDataService; +import org.librecms.assets.AudioAsset; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path("/{content-section}/audiomedia") +public class AudioMedia { + + private static final Logger LOGGER = LogManager.getLogger(Images.class); + + @Inject + private ContentSectionRepository sectionRepo; + + @Inject + private AssetRepository assetRepo; + + @Inject + private BinaryAssetDataService dataService; + + @GET + @Path("/uuid-{uuid}") + public Response getAudioByUuid( + @PathParam("content-section") final String sectionName, + @PathParam("uuid") final String uuid + ) { + final Optional video = assetRepo + .findByUuidAndType(uuid, AudioAsset.class); + + if (video.isPresent()) { + return loadAudio(video.get()); + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The requested video \"%s\" does not exist.", + uuid + ) + ) + .build(); + } + } + + @GET + @Path("/{path:^(?!uuid).+$}") + public Response getAudio( + @PathParam("content-section") final String sectionName, + @PathParam("path") final String path + ) { + final Optional section = sectionRepo + .findByLabel(sectionName); + if (!section.isPresent()) { + return Response + .status(Response.Status.NOT_FOUND) + .entity(String.format("No content section \"%s\" available.", + sectionName)) + .build(); + } + + final Optional asset = assetRepo.findByPath( + section.get(), path + ); + + if (asset.isPresent()) { + if (asset.get() instanceof AudioAsset) { + return loadAudio((AudioAsset) asset.get()); + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The asset found at the requested path \"%s\" " + + "is not an video.", + path + ) + ) + .build(); + } + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The requested video \"%s\" does not exist.", + path + ) + ) + .build(); + } + } + + private Response loadAudio(final AudioAsset video) { + final String mimeType = video.getMimeType().toString(); + + return Response + .ok() + .entity( + new StreamingOutput() { + + @Override + public void write(final OutputStream outputStream) + throws IOException, WebApplicationException { + dataService.copyDataToOutputStream( + video, outputStream + ); + } + + }) + .header("Content-Type", mimeType) + .build(); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/BookmarkPropertiesProvider.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/BookmarkPropertiesProvider.java new file mode 100644 index 000000000..b62ff0915 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/BookmarkPropertiesProvider.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection.rs; + +import org.librecms.assets.Bookmark; +import org.librecms.contentsection.Asset; + +import java.util.Objects; + +import javax.enterprise.context.Dependent; +import javax.json.JsonObjectBuilder; + +/** + * + * @author Jens Pelzetter + */ +@Dependent +@ProvidesPropertiesForAssetType(Bookmark.class) +public class BookmarkPropertiesProvider implements AssetPropertiesProvider { + + @Override + public void addProperties( + final Asset asset, final JsonObjectBuilder builder + ) { + Objects.requireNonNull(asset); + Objects.requireNonNull(builder); + + if (!(asset instanceof Bookmark)) { + throw new IllegalArgumentException( + String.format( + "\"%s\" only supports assets of type \"%s\". Check " + + "the qualifier annotation on \"%s\".", + getClass().getName(), + Bookmark.class.getName(), + getClass().getName() + ) + ); + } + + final Bookmark bookmark = (Bookmark) asset; + builder.add("targetUrl", bookmark.getUrl()); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java index bff1be942..a5717c5bb 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java @@ -37,10 +37,12 @@ public class ContentSectionsApplication extends Application{ final Set> classes = new HashSet<>(); classes.add(Assets.class); + classes.add(AudioMedia.class); classes.add(ContentItems.class); classes.add(ContentSections.class); classes.add(Files.class); classes.add(Images.class); + classes.add(Videos.class); return classes; } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ExternalAudioAssetPropertiesProvider.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ExternalAudioAssetPropertiesProvider.java new file mode 100644 index 000000000..6922966d1 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ExternalAudioAssetPropertiesProvider.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection.rs; + +import org.librecms.assets.ExternalAudioAsset; +import org.librecms.contentsection.Asset; + +import java.util.Objects; + +import javax.enterprise.context.Dependent; +import javax.json.JsonObjectBuilder; + +/** + * + * @author Jens Pelzetter + */ +@Dependent +@ProvidesPropertiesForAssetType(ExternalAudioAsset.class) +public class ExternalAudioAssetPropertiesProvider extends BookmarkPropertiesProvider { + + @Override + public void addProperties( + final Asset asset, final JsonObjectBuilder builder + ) { + Objects.requireNonNull(asset); + Objects.requireNonNull(builder); + + if (!(asset instanceof ExternalAudioAsset)) { + throw new IllegalArgumentException( + String.format( + "\"%s\" only supports assets of type \"%s\". Check " + + "the qualifier annotation on \"%s\".", + getClass().getName(), + ExternalAudioAsset.class.getName(), + getClass().getName() + ) + ); + } + + super.addProperties(asset, builder); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ExternalVideoAssetPropertiesProvider.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ExternalVideoAssetPropertiesProvider.java new file mode 100644 index 000000000..e2d15d1df --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ExternalVideoAssetPropertiesProvider.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection.rs; + +import org.librecms.assets.ExternalVideoAsset; +import org.librecms.contentsection.Asset; + +import java.util.Objects; + +import javax.enterprise.context.Dependent; +import javax.json.JsonObjectBuilder; + +/** + * + * @author Jens Pelzetter + */ +@Dependent +@ProvidesPropertiesForAssetType(ExternalVideoAsset.class) +public class ExternalVideoAssetPropertiesProvider extends BookmarkPropertiesProvider { + + @Override + public void addProperties( + final Asset asset, final JsonObjectBuilder builder + ) { + Objects.requireNonNull(asset); + Objects.requireNonNull(builder); + + if (!(asset instanceof ExternalVideoAsset)) { + throw new IllegalArgumentException( + String.format( + "\"%s\" only supports assets of type \"%s\". Check " + + "the qualifier annotation on \"%s\".", + getClass().getName(), + ExternalVideoAsset.class.getName(), + getClass().getName() + ) + ); + } + + super.addProperties(asset, builder); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java index fb22f47e0..14135e8b0 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java @@ -23,8 +23,6 @@ import org.apache.logging.log4j.Logger; import org.librecms.assets.BinaryAsset; import org.librecms.assets.BinaryAssetDataService; import org.librecms.assets.BinaryAssetRepository; -import org.librecms.contentsection.Asset; -import org.librecms.contentsection.AssetRepository; import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSectionRepository; @@ -51,8 +49,6 @@ public class Files { private static final Logger LOGGER = LogManager.getLogger(Files.class); -// @Inject -// private AssetRepository assetRepo; @Inject private BinaryAssetRepository binaryAssetRepo; @@ -135,7 +131,7 @@ public class Files { } }) - .header("ContentType", asset.getMimeType()) + .header("Content-Type", asset.getMimeType()) .header( "Content-Disposition", String.format( diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ImagesPropertiesProvider.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ImagesPropertiesProvider.java index 72126fbe1..746f74bdf 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ImagesPropertiesProvider.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ImagesPropertiesProvider.java @@ -23,11 +23,11 @@ import org.librecms.assets.Image; import org.librecms.contentsection.Asset; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Objects; +import javax.enterprise.context.Dependent; import javax.imageio.ImageIO; import javax.json.JsonObjectBuilder; @@ -35,25 +35,29 @@ import javax.json.JsonObjectBuilder; * * @author Jens Pelzetter */ +@Dependent @ProvidesPropertiesForAssetType(Image.class) public class ImagesPropertiesProvider implements AssetPropertiesProvider { @Override - public void addProperties(final Asset asset, - final JsonObjectBuilder builder) { - + public void addProperties( + final Asset asset, final JsonObjectBuilder builder + ) { Objects.requireNonNull(asset); Objects.requireNonNull(builder); - + if (!(asset instanceof Image)) { - throw new IllegalArgumentException(String - .format("\"%s\" only supports assets of type \"%s\". Check " - + "the qualifier annotation on \"%s\".", - getClass().getName(), - Image.class.getName(), - getClass().getName())); + throw new IllegalArgumentException( + String.format( + "\"%s\" only supports assets of type \"%s\". Check " + + "the qualifier annotation on \"%s\".", + getClass().getName(), + Image.class.getName(), + getClass().getName() + ) + ); } - + final Image image = (Image) asset; // final byte[] data = image.getData(); // final InputStream inputStream = new ByteArrayInputStream(data); @@ -61,10 +65,10 @@ public class ImagesPropertiesProvider implements AssetPropertiesProvider { final BufferedImage bufferedImage; try { bufferedImage = ImageIO.read(inputStream); - } catch(IOException ex) { + } catch (IOException ex) { throw new UnexpectedErrorException(ex); } - + builder .add("name", image.getDisplayName()) .add("filename", image.getFileName()) @@ -74,5 +78,5 @@ public class ImagesPropertiesProvider implements AssetPropertiesProvider { .add("size", image.getDataSize()); // .add("size", data.length); } - + } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java new file mode 100644 index 000000000..cecd277ac --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection.rs; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.librecms.assets.BinaryAssetDataService; +import org.librecms.assets.VideoAsset; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path("/{content-section}/videos") +public class Videos { + + private static final Logger LOGGER = LogManager.getLogger(Images.class); + + @Inject + private ContentSectionRepository sectionRepo; + + @Inject + private AssetRepository assetRepo; + + @Inject + private BinaryAssetDataService dataService; + + @GET + @Path("/uuid-{uuid}") + public Response getVideoByUuid( + @PathParam("content-section") final String sectionName, + @PathParam("uuid") final String uuid + ) { + final Optional video = assetRepo + .findByUuidAndType(uuid, VideoAsset.class); + + if (video.isPresent()) { + return loadVideo(video.get()); + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The requested video \"%s\" does not exist.", + uuid + ) + ) + .build(); + } + } + + @GET + @Path("/{path:^(?!uuid).+$}") + public Response getVideo( + @PathParam("content-section") final String sectionName, + @PathParam("path") final String path + ) { + final Optional section = sectionRepo + .findByLabel(sectionName); + if (!section.isPresent()) { + return Response + .status(Response.Status.NOT_FOUND) + .entity(String.format("No content section \"%s\" available.", + sectionName)) + .build(); + } + + final Optional asset = assetRepo.findByPath( + section.get(), path + ); + + if (asset.isPresent()) { + if (asset.get() instanceof VideoAsset) { + return loadVideo((VideoAsset) asset.get()); + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The asset found at the requested path \"%s\" " + + "is not an video.", + path + ) + ) + .build(); + } + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The requested video \"%s\" does not exist.", + path + ) + ) + .build(); + } + } + + private Response loadVideo(final VideoAsset video) { + final String mimeType = video.getMimeType().toString(); + + return Response + .ok() + .entity( + new StreamingOutput() { + + @Override + public void write(final OutputStream outputStream) + throws IOException, WebApplicationException { + dataService.copyDataToOutputStream( + video, outputStream + ); + } + + }) + .header("Content-Type", mimeType) + .build(); + } + +} diff --git a/ccm-cms/src/main/typescript/content-sections/cms-editor/audio-node/audio-node.ts b/ccm-cms/src/main/typescript/content-sections/cms-editor/audio-node/audio-node.ts index 43fe42024..90adbe4ed 100644 --- a/ccm-cms/src/main/typescript/content-sections/cms-editor/audio-node/audio-node.ts +++ b/ccm-cms/src/main/typescript/content-sections/cms-editor/audio-node/audio-node.ts @@ -414,7 +414,7 @@ function loadAudioAssets( selectButton.addEventListener( "click", (event) => { - const audioUrl = `/content-sections/info/audio/uuid-${audioAsset["uuid"]}`; + const audioUrl = buildAudioMediaUrl(audioAsset); node.attrs.audioSrc = audioUrl; if (audioElem) { audioElem.src = audioUrl; @@ -443,3 +443,16 @@ function loadAudioAssets( console.error(error); }); } + +function buildAudioMediaUrl(audioAsset: any) { + switch (audioAsset["type"]) { + case "org.librecms.assets.ExternalAudioAsset": + return audioAsset["properties"]["targetUrl"]; + case "org.librecms.assets.AudioAsset": + return `/content-sections/info/audiomedia/uuid-${audioAsset["uuid"]}`; + default: + console.error(`Unknown audio asset type.`); + return ""; + } +} + diff --git a/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts b/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts index 879357b8a..158473e09 100644 --- a/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts +++ b/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts @@ -462,7 +462,7 @@ function loadVideos( selectButton.addEventListener( "click", (event) => { - const videoUrl = `/@contentsections/info/videos/uuid-${video["uuid"]}`; + const videoUrl = buildVideoUrl(video); node.attrs.videoSrc = videoUrl; if (videoElem) { videoElem.src = videoUrl; @@ -491,3 +491,15 @@ function loadVideos( console.error(error); }); } + +function buildVideoUrl(video: any) { + switch (video["type"]) { + case "org.librecms.assets.ExternalVideoAsset": + return video["properties"]["targetUrl"]; + case "org.librecms.assets.VideoAsset": + return `/content-sections/info/videos/uuid-${video["uuid"]}`; + default: + console.error(`Unknown video asset type.`); + return ""; + } +}