workspace-tree-widget/src/main/java/org/gcube/portlets/user/workspace/server/ImageServlet.java

292 lines
10 KiB
Java

/**
*
*/
package org.gcube.portlets.user.workspace.server;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.activation.MimetypesFileTypeMap;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.storagehubwrapper.server.StorageHubWrapper;
import org.gcube.common.storagehubwrapper.server.tohl.Workspace;
import org.gcube.common.storagehubwrapper.shared.tohl.WorkspaceItem;
import org.gcube.common.storagehubwrapper.shared.tohl.exceptions.InternalErrorException;
import org.gcube.common.storagehubwrapper.shared.tohl.exceptions.ItemNotFoundException;
import org.gcube.common.storagehubwrapper.shared.tohl.impl.StreamDescriptor;
import org.gcube.common.storagehubwrapper.shared.tohl.items.FileItem;
import org.gcube.common.storagehubwrapper.shared.tohl.items.FileItemType;
import org.gcube.common.storagehubwrapper.shared.tohl.items.ImageFileItem;
import org.gcube.common.storagehubwrapper.shared.tohl.items.ItemStreamDescriptor;
import org.gcube.portlets.user.workspace.client.ConstantsExplorer;
import org.gcube.portlets.user.workspace.client.util.ImageRequestType;
import org.gcube.portlets.user.workspace.server.util.ThumbnailGenerator;
import org.gcube.portlets.user.workspace.server.util.WsUtil;
import org.gcube.portlets.user.workspace.shared.SessionExpiredException;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class ImageServlet.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa{@literal @}isti.cnr.it
* Oct 18, 2018
*/
public class ImageServlet extends HttpServlet{
/**
*
*/
private static final int THUMB_MAX_SIZE = 300;
private static final long serialVersionUID = -8423345575690165644L;
protected static Logger logger = LoggerFactory.getLogger(ImageServlet.class);
/**
* {@inheritDoc}
*/
@Override
public void init() throws ServletException {
super.init();
logger.trace("Workspace ImageServlet ready.");
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String imageId = req.getParameter("id");
String imageType = req.getParameter("type");
String contextID = req.getParameter(ConstantsExplorer.CURRENT_CONTEXT_ID);
boolean viewContent = req.getParameter("viewContent")==null?false:req.getParameter("viewContent").equals("true");
//String currUserId = req.getParameter(ConstantsExplorer.CURRENT_USER_ID);
ImageRequestType requestType = getRequestType(imageType);
logger.info("request image id: "+imageId+", type: "+requestType +", "+ConstantsExplorer.CURRENT_CONTEXT_ID+ ": "+contextID+", viewContent: "+viewContent);
Workspace wa = null;
try {
if(WsUtil.isSessionExpired(req))
throw new SessionExpiredException();
GCubeUser gcubeUser = PortalContext.getConfiguration().getCurrentUser(req);
StorageHubWrapper storageHubWrapper = WsUtil.getStorageHubWrapper(req, contextID, gcubeUser);
wa = storageHubWrapper.getWorkspace();
//wa = WsUtil.getWorkspace(req, contextID, gcubeUser);
} catch (Exception e) {
if (e instanceof SessionExpiredException){
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error the user session is expired");
return;
}
logger.error("Error during workspace retrieving", e);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Error during workspace retrieving");
return;
}
if (wa == null) {
logger.error("Error, no workspace in session");
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Error, no workspace in session");
return;
}
WorkspaceItem item;
try {
item = wa.getItem(imageId);
} catch (ItemNotFoundException e) {
logger.error("Error, no images found", e);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Error, no images found");
return;
} catch (Exception e) {
logger.error("Error on getting image: ", e);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Error on getting image");
return;
}
if (item instanceof FileItem == false) {
logger.error("Error wrong item type, expected a file, found "+item.getType());
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Error wrong item type, expected a file, found "+item.getType());
return;
}
FileItem folderItem = (FileItem) item;
FileItemType itemType = folderItem.getFileItemType();
if (itemType != FileItemType.IMAGE_DOCUMENT) {
logger.error("Error is wrong the file type, expected an "+FileItemType.IMAGE_DOCUMENT+", found "+itemType);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error wrong file item type, expected EXTERNAL_IMAGE or IMAGE_DOCUMENT, found "+itemType);
return;
}
ImageFileItem image = (ImageFileItem) folderItem;
try {
long size = 0;
ItemStreamDescriptor streamDescr = null;
String mimeType = null;
switch (requestType) {
case THUMBNAIL:
try{
streamDescr = wa.getThumbnailData(image.getId());
logger.debug("Thumbnail data has size: "+streamDescr.getSize());
//CHECKING IF THE STREAM IS A VALID IMAGE
/* TODO
* ReusableInputStream ris = new ReusableInputStream(streamDescr.getStream());
boolean isAvalidImage = isAnImage(ris, image.getName());
if(!isAvalidImage) {
//CREATING THE THUMBNAIL
logger.debug("the stream seems not be a valid image, creating the thumbnail");
streamDescr = createThumbnailForImage(wa, image);
}else {
//ASSIGNING THE REUSABLE STREAM
logger.debug("using reusable stream");
size = streamDescr.getSize()==null?0:streamDescr.getSize();
logger.debug("ReusableInputStream has size: "+size);
streamDescr = new org.gcube.common.storagehubwrapper.shared.tohl.impl.StreamDescriptor(ris, image.getName(), size, streamDescr.getMimeType());
}*/
}catch (Exception e) {
//silent
streamDescr = createThumbnailForImage(wa, image);
}
mimeType = streamDescr.getMimeType()!=null?streamDescr.getMimeType():image.getMimeType();
size = streamDescr.getSize()==null?0:streamDescr.getSize(); //reading size from byte.lenght
logger.info("THUMBNAIL size: "+size);
break;
case IMAGE:
default:
//reading mimeType from source image
mimeType = image.getMimeType();
size = image.getSize()==null?0:image.getSize(); //reading size from image source
streamDescr = wa.downloadFile(image.getId(), image.getName(), null, null);
logger.info("IMAGE size is: "+size);
break;
}
String fileName = image.getName();
String contentDisposition = viewContent?"inline":"attachment";
resp.setHeader("Content-Disposition", contentDisposition+"; filename=\"" + fileName + "\"" );
logger.info("mimeType is: "+mimeType);
resp.setContentType(mimeType);
//if image/thumbnail size is 0, skipping setContentLength
//AVOIDING TO SET IT, SOME CASES THE SIZE MISMATCH
// if(size!=0)
// resp.setContentLength((int)size);
InputStream in = streamDescr.getStream();
if(in==null)
throw new InternalErrorException("Image/Thumbnail data is null for image: "+image.getName());
OutputStream out = resp.getOutputStream();
// Send the content
IOUtils.copy(in, out);
in.close();
out.close();
logger.info("stream copied correctly");
} catch (Exception e) {
logger.error("Error: ",e);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Error on gettimg the image/thumbnail data");
return;
}
}
/**
* Creates the thumbnail for image.
*
* @param wa the wa
* @param image the image
* @return the stream descriptor
* @throws Exception the exception
*/
public static StreamDescriptor createThumbnailForImage(Workspace wa, ImageFileItem image) throws Exception {
logger.warn("Thumbnail data not available from StorageHub, creating it by the "+ThumbnailGenerator.class.getSimpleName() +" provided by the "+ImageServlet.class.getSimpleName());
ItemStreamDescriptor streamDescr = wa.downloadFile(image.getId(), image.getName(), null, null);
InputStream thumbIs = ThumbnailGenerator.generateThumbnail(streamDescr.getStream(), image.getName(), THUMB_MAX_SIZE, THUMB_MAX_SIZE);
return new org.gcube.common.storagehubwrapper.shared.tohl.impl.StreamDescriptor(thumbIs, image.getName(), null, image.getMimeType());
}
/**
* Checks if is an image.
*
* @param image the image
* @param fileName the file name
* @return true, if is an image
*/
private boolean isAnImage(InputStream image, String fileName) {
try {
logger.debug("Recognizing image type by "+ImageIO.class.getName());
// It's an image
//Only BMP, GIF, JPG and PNG are recognized).
ImageIO.read(image);
logger.debug(ImageIO.class.getName()+ " recognized the image: "+fileName+" as an Image");
return true;
} catch (Exception e) {
//Silent. It's not an image.
}
try {
logger.debug("Recognizing image type by "+MimetypesFileTypeMap.class.getName());
File f = ThumbnailGenerator.stream2file(image, fileName, ".tmp");
String mimetype = new MimetypesFileTypeMap().getContentType(f);
String type = mimetype.split("/")[0];
boolean isAnImage = type.equals("image")?true:false;
logger.debug(MimetypesFileTypeMap.class.getName()+ " is recognized the filename: "+fileName+" as an Image? "+isAnImage);
return isAnImage;
}catch (Exception e) {
//Silent. It's not an image.
}
logger.debug("The filename "+fileName+" seems not to be an Image");
return false;
}
/**
* Gets the request type.
*
* @param imageType the image type
* @return the request type
*/
private ImageRequestType getRequestType(String imageType){
if (imageType == null){
logger.warn("No request type specified, return the complete image");
return ImageRequestType.IMAGE;
} else
try{
return ImageRequestType.valueOf(imageType);
}catch (Exception e) {
return ImageRequestType.IMAGE;
}
}
}