GalleryInWysiwygRouter.java
/*
* Copyright (C) 2000 - 2024 Silverpeas
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* As a special exception to the terms and conditions of version 3.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* Open Source Software ("FLOSS") applications as described in Silverpeas's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* "http://www.silverpeas.org/docs/core/legal/floss_exception.html"
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.silverpeas.components.gallery.servlets;
import org.silverpeas.components.gallery.constant.MediaResolution;
import org.silverpeas.components.gallery.model.AlbumDetail;
import org.silverpeas.components.gallery.model.GalleryRuntimeException;
import org.silverpeas.components.gallery.model.MediaPK;
import org.silverpeas.components.gallery.model.Photo;
import org.silverpeas.components.gallery.service.GalleryService;
import org.silverpeas.core.admin.service.OrganizationController;
import org.silverpeas.core.contribution.content.LinkUrlDataSource;
import org.silverpeas.core.contribution.content.LinkUrlDataSourceScanner;
import org.silverpeas.core.contribution.content.wysiwyg.service.directive.ImageUrlAccordingToHtmlSizeDirective;
import org.silverpeas.core.io.file.SilverpeasFile;
import org.silverpeas.core.node.model.NodePK;
import org.silverpeas.core.util.ServiceProvider;
import org.silverpeas.kernel.util.StringUtil;
import org.silverpeas.kernel.logging.SilverLogger;
import javax.activation.FileDataSource;
import javax.inject.Singleton;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static java.util.Collections.singletonList;
import static org.silverpeas.core.contribution.content.LinkUrlDataSourceScanner.extractUrlParameters;
import static org.silverpeas.core.util.StringDataExtractor.RegexpPatternDirective.regexp;
import static org.silverpeas.core.util.StringDataExtractor.from;
import static org.silverpeas.kernel.util.StringUtil.defaultStringIfNotDefined;
/**
* This servlet is used in order to list image media for other components which handle WYSIWYG
* editing.
*/
public class GalleryInWysiwygRouter extends HttpServlet {
private static final long serialVersionUID = 1L;
private static SilverpeasFile getSilverpeasFile(final Photo image, final String size,
final boolean useOriginal) {
final MediaResolution mediaResolution = useOriginal
? MediaResolution.ORIGINAL
: MediaResolution.PREVIEW;
return image.getFile(mediaResolution, size);
}
private static boolean isViewInWysiwyg(final String componentId) {
return "yes".equalsIgnoreCase(OrganizationController.get()
.getComponentParameterValue(componentId, "viewInWysiwyg"));
}
private static GalleryService getGalleryService() {
return ServiceProvider.getService(GalleryService.class);
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doPost(req, res);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String componentId = request.getParameter("ComponentId");
String albumId = request.getParameter("AlbumId");
String imageId = request.getParameter("ImageId");
String language = request.getParameter("Language");
String size = request.getParameter("Size");
boolean useOriginal = Boolean.parseBoolean(request.getParameter("UseOriginal"));
// Check component instance application parameter viewInWysiwyg (shared picture) is activated
boolean isViewInWysiwyg = isViewInWysiwyg(componentId);
if (isViewInWysiwyg) {
String rootDest = "/gallery/jsp/";
String destination = "";
// regarder si on demande l'affichage de l'arborescence ou l'affichage du
// contenu d'un album
if (StringUtil.isDefined(imageId)) {
// Display image
Photo image = getGalleryService().getPhoto(new MediaPK(imageId, componentId));
displayImage(response, image, size, useOriginal);
} else if (!StringUtil.isDefined(albumId)) {
// Display albums content
request.setAttribute("Albums", viewAllAlbums(componentId));
destination = rootDest + "wysiwygAlbums.jsp";
} else {
// Display album content
request.setAttribute("MediaList", viewPhotosOfAlbum(componentId, albumId));
destination = rootDest + "wysiwygImages.jsp";
}
if (StringUtil.isDefined(destination)) {
request.setAttribute("Language", language);
RequestDispatcher requestDispatcher =
getServletConfig().getServletContext().getRequestDispatcher(destination);
if (requestDispatcher != null) {
requestDispatcher.forward(request, response);
}
}
}
}
/**
* Retrieve all albums from a multimedia application
* @param componentId the component instance identifier
* @return a collection of AlbumDetail
*/
private Collection<AlbumDetail> viewAllAlbums(String componentId) {
try {
return getGalleryService().getAllAlbums(componentId);
} catch (Exception e) {
throw new GalleryRuntimeException(e);
}
}
/**
* Retrieve all photos from an album
* @param componentId the component identifier
* @param albumId the album identifier
* @return a collection of Photo
*/
private Collection<Photo> viewPhotosOfAlbum(String componentId, String albumId) {
try {
NodePK nodePK = new NodePK(albumId, componentId);
return getGalleryService().getAllPhotos(nodePK);
} catch (Exception e) {
throw new GalleryRuntimeException(e);
}
}
private void displayImage(HttpServletResponse res, Photo image, String size, boolean useOriginal)
throws IOException {
res.setContentType(image.getFileMimeType().getMimeType());
res.setHeader("Cache-Control", "no-store"); //HTTP 1.1
res.setHeader("Pragma", "no-cache");
res.setDateHeader("Expires", -1);
OutputStream out2 = res.getOutputStream();
int read;
final SilverpeasFile imageFile = getSilverpeasFile(image, size, useOriginal);
try (BufferedInputStream input = new BufferedInputStream(new FileInputStream(imageFile))) {
read = input.read();
while (read != -1) {
// writes bytes into the response
out2.write(read);
read = input.read();
}
} catch (Exception e) {
SilverLogger.getLogger(this).warn(e);
} finally {
// we must close the in and out streams
try {
out2.close();
} catch (Exception e) {
SilverLogger.getLogger(this).warn(e);
}
}
}
@Singleton
public static class ImageUrlToDataSourceScanner implements LinkUrlDataSourceScanner {
private static final Pattern GALLERY_CONTENT_LINK_PATTERN =
Pattern.compile("(?i)=\"([^\"]*/GalleryInWysiwyg/[^\"]+)");
@Override
public List<LinkUrlDataSource> scanHtml(final String htmlContent) {
final List<LinkUrlDataSource> result = new ArrayList<>();
from(htmlContent).withDirectives(singletonList(regexp(GALLERY_CONTENT_LINK_PATTERN, 1))).extract().forEach(l -> {
final Map<String, String> params = extractUrlParameters(l);
final String componentId = params.get("ComponentId");
// Check component instance application parameter viewInWysiwyg (shared picture) is activated
boolean isViewInWysiwyg = isViewInWysiwyg(componentId);
if (isViewInWysiwyg) {
final String imageId = params.get("ImageId");
final String size = params.get("Size");
final boolean useOriginal = Boolean.parseBoolean(params.get("UseOriginal"));
final Photo image = getGalleryService().getPhoto(new MediaPK(imageId, componentId));
final SilverpeasFile imageFile = getSilverpeasFile(image, size, useOriginal);
if (imageFile.exists()) {
result.add(new LinkUrlDataSource(l, () -> new FileDataSource(imageFile)));
}
}
});
return result;
}
}
@Singleton
public static class ImageUrlAccordingToHtmlSizeDirectiveTranslator extends
ImageUrlAccordingToHtmlSizeDirective.SrcWithSizeParametersTranslator {
@Override
public boolean isCompliantUrl(final String url) {
return defaultStringIfNotDefined(url).contains("/GalleryInWysiwyg/");
}
}
}