Java tutorial
package com.disney.opa.util; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.CopyOption; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.activation.MimetypesFileTypeMap; import javax.validation.ValidationException; import javax.ws.rs.container.ContainerRequestContext; import org.apache.commons.lang.StringEscapeUtils; import org.apache.log4j.Logger; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.disney.opa.bean.UserInfo; import com.disney.opa.dao.SearchEngineDao; import com.disney.opa.dom.image.OPAImage; import com.disney.opa.dom.module.Module; import com.disney.opa.dom.product.Attachment; import com.disney.opa.dom.product.Product; import com.disney.opa.dom.product.ProductState; import com.disney.opa.dom.user.UserSelectionTypes; import com.disney.opa.helper.user.UserPermission; import com.disney.opa.json.request.AddAttachmentRequest; import com.disney.opa.json.response.BaseJsonResponse; import com.disney.opa.search.PASearchResultSet; import com.disney.opa.service.ImageService; import com.disney.opa.service.ModuleService; import com.disney.opa.service.UtilityService; import com.disney.opa.template.ModuleTypes; import com.disney.opa.template.PageTypes; /** * This class is an utility class for attachment related functionality. * */ @Component public class AttachmentUtils { @Autowired private ImageService imageService; @Autowired private UtilityService utilityService; @Autowired private SearchEngineDao searchEngineDao; @Autowired private ModuleService moduleService; private static final Logger log = Logger.getLogger(AttachmentUtils.class); private static final int PRODUCT_DIR_DIVISOR = 10000; private static MimetypesFileTypeMap mimetypesFileTypeMap = null; /** * This method is to get the root path of attachments from OPAProperties. * * @return images directory * @throws Exception */ public String getRootAttachmentPath() throws Exception { return utilityService.getOPAPropertyValue("imagesDir"); } /** * Based on product id get the relative path of images directory. * * @param productId * @return images directory relative path */ public String getRelativeFilePath(int productId) { int productDirNumber = productId / PRODUCT_DIR_DIVISOR; return File.separator + productDirNumber + File.separator + productId + "_images"; } /** * This method is to get relative path of original files. * * @param productId * @return original files relative path */ public String getRelativeOriginalFilePath(int productId) { int productDirNumber = productId / PRODUCT_DIR_DIVISOR; return File.separator + productDirNumber + File.separator + productId + "_images" + File.separator + "original"; } /** * Get the attachments path using product id to store original files. * * @param productId * @return original attachments path * @throws Exception */ public String getOriginalAttachmentsPath(int productId) throws Exception { String pathname = getRootAttachmentPath() + getRelativeFilePath(productId) + File.separator + "original"; File dir = new File(pathname); if (!dir.exists() && !dir.mkdirs()) { throw new IOException("Could not create images directory: " + pathname); } return pathname; } /** * Based on file extension get the mime type. * * @param filename * @return mime type */ public static String getMimeType(String filename) { if (mimetypesFileTypeMap == null) { mimetypesFileTypeMap = new MimetypesFileTypeMap(); mimetypesFileTypeMap.addMimeTypes("image/bmp bmp"); mimetypesFileTypeMap.addMimeTypes("image/gif gif"); mimetypesFileTypeMap.addMimeTypes("image/jpeg jpg jpe jpeg"); mimetypesFileTypeMap.addMimeTypes("application/pdf pdf"); mimetypesFileTypeMap.addMimeTypes("application/postscript ps eps ai"); mimetypesFileTypeMap.addMimeTypes("image/targa tar targa"); mimetypesFileTypeMap.addMimeTypes("image/tiff tif tiff"); mimetypesFileTypeMap.addMimeTypes("image/png png"); mimetypesFileTypeMap.addMimeTypes("application/photoshop psd pdd"); mimetypesFileTypeMap.addMimeTypes("application/octet-stream img"); } return mimetypesFileTypeMap.getContentType(filename); } /** * This method is to get file extension using file name. * * @param filename * @return the file extension */ public String getFileExtension(String filename) { int index = filename.lastIndexOf("."); if (index >= 0) { return filename.substring(index + 1); } return null; } /** * This method is to get relative thumb nails path using product id. * * @param productId * @return relative thumb nails path */ public String getRelativeThumbnailsPath(int productId) { return getRelativeFilePath(productId) + File.separator + "thumbnails"; } /** * Create thumb nail file name using original file name. * * @param fileName * @return thumb nail file name */ public String getThumbnailFileName(String fileName) { String thumbnailFileName = new File(fileName).getName(); int index = thumbnailFileName.lastIndexOf("."); if (index < 0) { return thumbnailFileName + ".jpg"; } return thumbnailFileName.substring(0, index) + ".jpg"; } /** * This method is to create an attachment object and verifies the file existence on disk. * * @param fileName * @param fileLabel * @param productId * @param productStateID * @param userID * @return an attachment */ public Attachment getAttachment(String fileName, String fileLabel, int productId, int productStateID, int userID) { Attachment attachment = new Attachment(); try { attachment.setProductID(productId); attachment.setProductStateID(productStateID); attachment.setName(fileLabel); attachment.setFilename(fileName); attachment.setUserID(userID); attachment.setMimeType(AttachmentUtils.getMimeType(fileName)); String imageFile = getRelativeOriginalFilePath(productId) + File.separator + fileName; attachment.setFilePath(imageFile); attachment.setThumbnailFilePath(null); Path path = Paths.get(getRootAttachmentPath() + imageFile); if (Files.exists(path)) { attachment.setFileSize(Files.size(path)); } } catch (Exception e) { log.error("Error in getAttachment, fileName: " + fileName + ", fileLabel: " + fileLabel + ", productId: " + productId + ", userID: " + userID, e); } return attachment; } /** * This method handles the user save attachment request. * * @param addRequest * @param productStateID * @param fileNames * @param fileLabels * @param errors * @return list of attachments supplied by user * @throws Exception */ public List<Attachment> processRequest(AddAttachmentRequest addRequest, int productStateID, List<String> fileNames, List<String> fileLabels, List<String> errors) throws Exception { List<Attachment> attachments = new ArrayList<Attachment>(); for (AddAttachmentRequest.File file : addRequest.getFiles()) { String fileExt = getFileExtension(file.getImageFileName()); Attachment attachment = getAttachment(file.getImageFileName(), file.getFileLabel(), addRequest.getProductId(), productStateID, addRequest.getLogonUserId()); if (attachment.getFileSize() == 0L) { errors.add("File not found, file name: " + file.getImageFileName() + ", title: " + file.getFileLabel()); } else if ("zip".equalsIgnoreCase(fileExt)) { attachments.addAll(processZipFile(attachment, fileNames, fileLabels, errors)); attachment .setName(createUniqueFileLabel(attachment.getFilename(), attachment.getName(), fileLabels)); attachment.setName(attachment.getName() + ".PENDING"); attachments.add(attachment); } else { attachment .setName(createUniqueFileLabel(attachment.getFilename(), attachment.getName(), fileLabels)); attachments.add(attachment); } } return attachments; } /** * This method is to extract the zip files and creates attachment objects. * * @param attachment * @param fileNames * @param fileLabels * @param errors * @return list of attachments from the zip file */ public List<Attachment> processZipFile(Attachment attachment, List<String> fileNames, List<String> fileLabels, List<String> errors) { ZipFile zipFile = null; List<Attachment> attachments = new ArrayList<Attachment>(); try { String zipFilePath = getOriginalAttachmentsPath(attachment.getProductID()) + File.separator + attachment.getFilename(); zipFile = new ZipFile(zipFilePath); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if (entry.isDirectory()) { continue; } String fileName = entry.getName(); File destinationFile = new File( getOriginalAttachmentsPath(attachment.getProductID()) + File.separator + fileName); uploadFile(zipFile.getInputStream(entry), destinationFile); String label = createUniqueFileLabel(fileName, null, fileLabels); Attachment fileAttachment = getAttachment(fileName, label, attachment.getProductID(), attachment.getProductStateID(), attachment.getUserID()); if (fileAttachment.getFileSize() == 0L) { errors.add("File not found, file name: " + fileName + ", in zip file: " + attachment.getFilename()); } else { attachments.add(fileAttachment); } } } catch (Exception e) { errors.add( "Error while processing zip: " + attachment.getFilename() + ", title: " + attachment.getName()); log.error("Error while processing zip.", e); } finally { try { if (zipFile != null) { zipFile.close(); } } catch (IOException e) { } } return attachments; } /** * This method is to create unique file label. * * @param fileName * @param fileLabel * @param fileLabels * @return unique file label */ public String createUniqueFileLabel(String fileName, String fileLabel, List<String> fileLabels) { String newFileLabel = fileLabel; if (StringUtils.isEmpty(fileLabel)) { int index = fileName.lastIndexOf("."); newFileLabel = (index > 0) ? fileName.substring(0, index) : fileName; } for (int n = 1; fileLabels.contains(newFileLabel); n++) { newFileLabel = newFileLabel + "_" + n; } fileLabels.add(newFileLabel); return newFileLabel; } /** * This method is to create an unique isbn file name. * * @param fileName * @param isbn * @param fileNames * @return unique file name. */ public String createUniqueISBNFileName(String fileName, String isbn, List<String> fileNames) { String extension = getFileExtension(fileName); int index = fileName.lastIndexOf("."); String newFileNamePrefix = isbn + "_" + ((index > 0) ? fileName.substring(0, index) : fileName); String newFileName = newFileNamePrefix + "." + extension; for (int n = 1; fileNames.contains(newFileName); n++) { newFileName = newFileNamePrefix + "_" + n + "." + extension; } fileNames.add(newFileName); return newFileName; } /** * This method is to create a thumb nail to attachment. * * @param attachment * - Attachment */ public void createThumbnail(Attachment attachment) { try { String extension = getFileExtension(attachment.getFilename()); if (!LookupUtil.isThumbnailPossible(extension, attachment.getMimeType())) { return; } String thumbnailPath = getRelativeThumbnailsPath(attachment.getProductID()); File parentFile = new File(attachment.getFilePath()); String targetPassDirectory = getRelativeFilePath(attachment.getProductID()); String targetRejectDirectory = thumbnailPath + File.separator + "reject" + File.separator + "thumb_" + attachment.getFilename(); String thumbnailImagePath = createThumbnailImageMagick(parentFile, thumbnailPath, targetPassDirectory, targetRejectDirectory); if (StringUtils.isNotEmpty(thumbnailImagePath)) { attachment.setThumbnailFilePath( thumbnailPath + File.separator + getThumbnailFileName(attachment.getFilePath())); } } catch (Exception e) { log.error("Error while creating thumnail for file: " + attachment.getFilePath(), e); } } /** * This method is to move and rename the files from original directory to images directory. * * @param attachment * @param isbn * @param fileNames * @throws Exception */ public void renameFile(Attachment attachment, String isbn, List<String> fileNames) throws Exception { String extension = getFileExtension(attachment.getFilename()); String sourceFilePath = getRootAttachmentPath() + attachment.getFilePath(); String destFilePath = getRootAttachmentPath() + getRelativeFilePath(attachment.getProductID()) + File.separator + attachment.getID(); destFilePath += (extension != null) ? "." + extension.toLowerCase() : ""; /* File sourceFile = new File(sourceFilePath); File destFile = new File(destFilePath); if (!sourceFile.renameTo(destFile)) { log.error("File rename failed for src: " + sourceFilePath + ", dest: " + destFilePath); return; } */ java.nio.file.Path FROM = Paths.get(sourceFilePath); java.nio.file.Path TO = Paths.get(destFilePath); Files.move(FROM, TO); attachment.setFilePath(getRelativeFilePath(attachment.getProductID()) + File.separator + TO.getFileName()); if (StringUtils.isNotEmpty(isbn)) { attachment.setFilename(createUniqueISBNFileName(attachment.getFilename(), isbn, fileNames)); } } /** * Create a thumbnail image directly on the NAS for a given source image. Uses the default width and height of 150x150. * * @since OPA 6.3 (2012) * @param parentFile * @param fileType * @param targetPassDirectory * @param targetRejectDirectory * * @return String message from conversion servlet (ImageMagick) * @throws Exception */ public String createThumbnailImageMagick(File parentFile, String thumbnailPath, String targetPassDirectory, String targetRejectDirectory) throws Exception { String result = resizeImage(parentFile, thumbnailPath, targetPassDirectory, targetRejectDirectory, 150, 150); return result; } /** * Creates a resized image from a given image, parentFile. If the image resizing is successful, the resized image is stored in the targetPassDirectory; otherwise, the parentFile is moved to the * targetRejectDirectory. * * @param parentFile * @param targetPassDirectory * @param targetRejectDirectory * @return */ public String resizeImage(File parentFile, String thumbnailPath, String targetPassDirectory, String targetRejectDirectory, int imgWidth, int imgHeight) throws Exception { if (log.isDebugEnabled()) { log.debug("createThumbnail() - start, " + "targetPassDirectory is " + targetPassDirectory); } File thumbnailImg = null; File originalFile = parentFile; try { OPAImage opaImage = new OPAImage(originalFile); opaImage.setResizeHeight(imgHeight); opaImage.setResizeWidth(imgWidth); opaImage.setResultDirectory(targetPassDirectory); opaImage.setThumbnailPath(thumbnailPath); log.info("createThumbnail Cache Dir : " + opaImage.getResultDirectory()); boolean wasThumbnailCreated = imageService.resizeImage(opaImage); String resultFilePath = getRootAttachmentPath() + File.separator + thumbnailPath + File.separator + getThumbnailFileName(originalFile.getName()); log.debug("checking if the thumbnail is there... in directory " + resultFilePath); thumbnailImg = new File(resultFilePath); if (!thumbnailImg.exists() || !wasThumbnailCreated) { // OPA 6.4 - if the image failed, then don't update the path return null; } } catch (Exception e) { throw e; } log.debug("createThumbnail() - finish"); return thumbnailImg.getAbsolutePath(); } /** * Save the input stream into the destination file * * @param iStream * @param destinationFile * @throws Exception */ public long uploadFile(InputStream iStream, File destinationFile) throws Exception { FileOutputStream oStream = null; long bytesWritten = 0; // AGS Replacement 2012 try { // write the stream to the specified file oStream = new FileOutputStream(destinationFile); byte[] buffer = new byte[8192]; int bytesRead = 0; while ((bytesRead = iStream.read(buffer)) != -1) { oStream.write(buffer, 0, bytesRead); bytesWritten += bytesRead; } } catch (FileNotFoundException fnfe) { throw new Exception("AttachmentUtils: FileNotFoundException " + fnfe.getMessage()); } catch (IOException ioe) { throw new Exception("AttachmentUtils: IOException " + ioe.getMessage()); } finally { // try to close the input stream if (iStream != null) { try { iStream.close(); } catch (IOException e) { log.error(e); } } // try to close the output stream if (oStream != null) { try { oStream.close(); } catch (IOException e) { log.error(e); } } } return bytesWritten; } /** * This method is to handle the user authentication and authorization validation. * * @param requestContext * @param requestUserId * @param response * @return true if user has access otherwise false */ public boolean hasAccess(ContainerRequestContext requestContext, int requestUserId, BaseJsonResponse response) { try { UserInfo userInfo = (UserInfo) requestContext.getProperty("userInfo"); if (null == userInfo) { throw new ValidationException("Access Denied"); } int userId = Integer.parseInt(userInfo.getUserId()); if (!RequestUtil.isAdmin(userId) && userId != requestUserId) { throw new ValidationException("Permission Denied"); } } catch (ValidationException e) { log.info("Validation error: " + e); response.setSuccess(false); response.setMessage(e.getMessage()); return false; } catch (Exception e) { log.error("Exception in hasAccess: " + e); response.setSuccess(false); response.setMessage(e.getMessage()); return false; } return true; } /** * Get the last attachment from the list of attachments. * * @param dbAttachments * @param product * @param lastFileName * @return last attachment */ public Attachment getLastAttachment(Attachment[] dbAttachments, Product product, String lastFileName) { if (dbAttachments != null && dbAttachments.length > 0) { int productStatus = product.getApprovalStatusID(); boolean isImageThumbnailAllowed = !(productStatus == product.getApprovalStatusID() || productStatus == Product.CANCELLED || productStatus == Product.APPROVED_EXTERNALLY); if (isImageThumbnailAllowed) { Attachment lastAttachment = null; for (Attachment attachment : dbAttachments) { if (attachment.getFilename().equals(lastFileName)) { lastAttachment = attachment; break; } } if (lastAttachment != null) { return lastAttachment; } } } return null; } /** * Save original file to disk. * * @param bodyParts * @param productId */ public void saveOriginalFile(List<FormDataBodyPart> bodyParts, int productId) { try { if (bodyParts == null || bodyParts.size() == 0) { return; } String dir = getOriginalAttachmentsPath(productId) + File.separator; for (FormDataBodyPart part : bodyParts) { String fileName = part.getContentDisposition().getFileName(); if (StringUtils.isNotEmpty(fileName)) { FileOutputStream fos = new FileOutputStream(dir + StringEscapeUtils.unescapeHtml(fileName)); fos.write(part.getEntityAs(byte[].class)); fos.flush(); fos.close(); } } } catch (Exception e) { log.error("Error in saveOriginalFile, productId: " + productId, e); throw new ValidationException("Error while saving file: " + e.getMessage()); } } /** * Check user has permission to edit the product or not * * @param userPermission * @return true if user has edit permission otherwise false */ public boolean canEditSubmission(UserPermission userPermission) { try { Product product = userPermission.getProduct(); int productIds[] = new int[] { product.getID() }; int userIds[] = new int[] { userPermission.getUserId() }; PASearchResultSet[] resultSets = searchEngineDao.searchQuick(productIds, userIds, 1, 1, 1, null, userPermission.getUserId()); if (resultSets == null || resultSets.length == 0 || resultSets[0] == null || resultSets[0].getSearchItems() == null || resultSets[0].getSearchItems().length == 0 || resultSets[0].getSearchItems()[0] == null || resultSets[0].getSearchItems()[0].getProductSummary() == null || resultSets[0].getSearchItems()[0].getProductSummary().getProductID() != userPermission .getProduct().getID()) { throw new ValidationException("User doesn't have permission to access the product."); } Module module = moduleService.getModule(product.getProductTemplateID(), PageTypes.EDIT_CREATE, UserSelectionTypes.LICENSEE, ModuleTypes.ASSET_MANAGER); if (module == null) { throw new ValidationException("Asset Manager module not found in product template."); } ProductState state = userPermission.getState(); if (state == null) { throw new ValidationException("Product doesn't have state."); } int userId = userPermission.getUserId(); if (state.getCurrentPerformerID() == userId || state.getCurrentStepOwnerID() == userId || userPermission.isActAsManagingEditor() || userPermission.isActAsAgent()) { if (userPermission.isActAsAgent()) { userPermission.setShowReadonlyReviewPage((userId != state.getCurrentPerformerID())); } else if (ProductUtil.isLineSheet(product.getProductTemplateID())) { int statusId = product.getProductStatusID(); boolean isApproved = (statusId == product.getApprovalStatusID() || statusId == Product.LINE_LIST_APPROVED || statusId == Product.APPROVED_EXTERNALLY); userPermission.setShowReadonlyReviewPage(isApproved); } else { userPermission.setShowReadonlyReviewPage(false); } } else if (PermissionUtil.isUserReviewer(product, userId, state)) { userPermission.setShowReadonlyReviewPage(false); } else { userPermission.setShowReadonlyReviewPage(true); } if (userPermission.isShowReadonlyReviewPage()) { throw new ValidationException("User has permission only to view this product."); } } catch (ValidationException e) { throw e; } catch (Exception e) { log.error("Error in canEditSubmission", e); throw new ValidationException("Unknown error while validating user permissions, error: " + e); } return true; } public boolean checkForDoubleByteCharacters(String s) { boolean doubleByte = false; try { for (int i = 0; i < s.length(); i++) { String test = "" + s.charAt(i); byte[] bytes = test.getBytes("UTF-8"); if (bytes.length > 1) { doubleByte = true; } } } catch (Exception e) { //If we throw an error we can't tell return false; } return doubleByte; } }