Java tutorial
/******************************************************************************* * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-3.0-standalone.html ******************************************************************************/ package se.unlogic.hierarchy.foregroundmodules.imagegallery; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.sql.Blob; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.List; import java.util.Random; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.sql.DataSource; import javax.sql.rowset.serial.SerialBlob; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.io.FilenameUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import se.unlogic.fileuploadutils.MultipartRequest; import se.unlogic.hierarchy.core.annotations.ModuleSetting; import se.unlogic.hierarchy.core.annotations.TextFieldSettingDescriptor; import se.unlogic.hierarchy.core.annotations.WebPublic; import se.unlogic.hierarchy.core.beans.Breadcrumb; import se.unlogic.hierarchy.core.beans.Group; import se.unlogic.hierarchy.core.beans.SettingDescriptor; import se.unlogic.hierarchy.core.beans.SimpleForegroundModuleResponse; import se.unlogic.hierarchy.core.beans.User; import se.unlogic.hierarchy.core.beans.ValueDescriptor; import se.unlogic.hierarchy.core.enums.URLType; import se.unlogic.hierarchy.core.exceptions.AccessDeniedException; import se.unlogic.hierarchy.core.exceptions.URINotFoundException; import se.unlogic.hierarchy.core.interfaces.AccessInterface; import se.unlogic.hierarchy.core.interfaces.ForegroundModuleDescriptor; import se.unlogic.hierarchy.core.interfaces.MutableSettingHandler; import se.unlogic.hierarchy.core.interfaces.SectionInterface; import se.unlogic.hierarchy.core.utils.AccessUtils; import se.unlogic.hierarchy.foregroundmodules.AnnotatedForegroundModule; import se.unlogic.hierarchy.foregroundmodules.imagegallery.beans.Comment; import se.unlogic.hierarchy.foregroundmodules.imagegallery.beans.Gallery; import se.unlogic.hierarchy.foregroundmodules.imagegallery.beans.Picture; import se.unlogic.hierarchy.foregroundmodules.imagegallery.daos.CommentDao; import se.unlogic.hierarchy.foregroundmodules.imagegallery.daos.GalleryDao; import se.unlogic.hierarchy.foregroundmodules.imagegallery.daos.PictureDao; import se.unlogic.hierarchy.foregroundmodules.imagegallery.populators.GalleryPopulator; import se.unlogic.standardutils.dao.querys.UpdateQuery; import se.unlogic.standardutils.datatypes.SimpleEntry; import se.unlogic.standardutils.db.DBUtils; import se.unlogic.standardutils.image.ImageUtils; import se.unlogic.standardutils.io.BinarySizes; import se.unlogic.standardutils.io.FileUtils; import se.unlogic.standardutils.mime.MimeUtils; import se.unlogic.standardutils.numbers.NumberUtils; import se.unlogic.standardutils.streams.StreamUtils; import se.unlogic.standardutils.string.StringUtils; import se.unlogic.standardutils.threads.MutexKeyProvider; import se.unlogic.standardutils.time.TimeUtils; import se.unlogic.standardutils.validation.PositiveStringIntegerValidator; import se.unlogic.standardutils.validation.StringIntegerValidator; import se.unlogic.standardutils.validation.ValidationError; import se.unlogic.standardutils.validation.ValidationErrorType; import se.unlogic.standardutils.validation.ValidationException; import se.unlogic.standardutils.xml.XMLUtils; import se.unlogic.standardutils.zip.ZipUtils; import se.unlogic.webutils.http.HTTPUtils; import se.unlogic.webutils.http.RequestUtils; import se.unlogic.webutils.http.URIParser; public class GalleryModule extends AnnotatedForegroundModule implements AccessInterface { //TODO let users specify alias manually //TODO support multiple file uploads without using a zip file (HTML5) private static final ArrayList<SettingDescriptor> SETTINGDESCRIPTORS = new ArrayList<SettingDescriptor>(); static { SETTINGDESCRIPTORS.add(SettingDescriptor.createTextFieldSetting("numOfThumbsPerPage", "Thumbnails per page", "The number of thumbnails per page (default is 15)", false, "15", new StringIntegerValidator(1, null))); SETTINGDESCRIPTORS.add(SettingDescriptor.createTextFieldSetting("smallImageMaxHeight", "Small image max height ", "The max height of the small thumbnails (default is 93)", false, "93", new StringIntegerValidator(1, null))); SETTINGDESCRIPTORS.add(SettingDescriptor.createTextFieldSetting("smallImageMaxWidth", "Small image max width ", "The max width of the small thumbnails (default is 125)", false, "125", new StringIntegerValidator(1, null))); SETTINGDESCRIPTORS.add(SettingDescriptor.createTextFieldSetting("mediumImageMaxHeight", "Medium image max height ", "The max height of the medium thumbnails (default is 500)", false, "500", new StringIntegerValidator(1, null))); SETTINGDESCRIPTORS.add(SettingDescriptor.createTextFieldSetting("mediumImageMaxWidth", "Medium image max width ", "The max width of the medium thumbnails (default is 500)", false, "500", new StringIntegerValidator(1, null))); SETTINGDESCRIPTORS.add(SettingDescriptor.createCheckboxSetting("allowAnonymousComments", "Allow anonymous comments", "Control wheter or not logged in user can post comments", false)); SETTINGDESCRIPTORS.add(SettingDescriptor.createTextFieldSetting("diskThreshold", "Max upload size", "Maxmium upload size in megabytes allowed in a single post request", false, "100", new StringIntegerValidator(1, null))); SETTINGDESCRIPTORS.add(SettingDescriptor.createDropDownSetting("thumbQuality", "Thumbnail quality", "Selects which algorithm that should be used when generating thumbnails", true, Image.SCALE_SMOOTH + "", new ValueDescriptor("SCALE_SMOOTH", Image.SCALE_SMOOTH + ""), new ValueDescriptor("SCALE_AREA_AVERAGING", Image.SCALE_AREA_AVERAGING + ""), new ValueDescriptor("SCALE_FAST", Image.SCALE_FAST + ""), new ValueDescriptor("SCALE_REPLICATE", Image.SCALE_REPLICATE + ""))); } private static final GalleryPopulator GalleryPopulator = new GalleryPopulator(); protected static final SimpleFileFilter fileFilter = new SimpleFileFilter(); protected GalleryDao galleryDao; protected PictureDao pictureDao; protected CommentDao commentDao; @ModuleSetting(allowsNull = true) @TextFieldSettingDescriptor(name = "Base path", description = "Path to directory in which gallery directories will automatically created.\r\nIf base path is omitted, auto creation of gallery directories is disabled.\r\nAuto created directories will never use (merge with) existing direcories.", required = false) protected String path; @ModuleSetting protected Integer numOfThumbsPerPage = 15; @ModuleSetting protected Integer smallImageMaxHeight = 93; @ModuleSetting protected Integer smallImageMaxWidth = 125; @ModuleSetting protected Integer mediumImageMaxHeight = 500; @ModuleSetting protected Integer mediumImageMaxWidth = 500; @ModuleSetting protected Boolean allowAnonymousComments = false; @ModuleSetting protected Integer diskThreshold = 100; @ModuleSetting @TextFieldSettingDescriptor(name = "RAM threshold", description = "Maximum size of files in KB to be buffered in RAM during file uploads. Files exceeding the threshold are written to disk instead.", required = true, formatValidator = PositiveStringIntegerValidator.class) protected Integer ramThreshold = 500; @ModuleSetting(allowsNull = true) protected List<Integer> adminGroupIDs; @ModuleSetting(allowsNull = true) protected List<Integer> adminUserIDs; protected Integer thumbQuality = Image.SCALE_SMOOTH; protected MutexKeyProvider<Gallery> mutexKeyProvider = new MutexKeyProvider<Gallery>(); @Override public void init(ForegroundModuleDescriptor moduleDescriptor, SectionInterface sectionInterface, DataSource dataSource) throws Exception { super.init(moduleDescriptor, sectionInterface, dataSource); System.setProperty("java.awt.headless", "true"); this.checkTables(dataSource); this.galleryDao = new GalleryDao(dataSource); this.pictureDao = new PictureDao(dataSource); this.commentDao = new CommentDao(dataSource, sectionInterface.getSystemInterface().getUserHandler()); this.checkSettings(moduleDescriptor.getMutableSettingHandler()); } @Override public void update(ForegroundModuleDescriptor moduleDescriptor, DataSource dataSource) throws Exception { super.update(moduleDescriptor, dataSource); this.checkTables(dataSource); this.galleryDao = new GalleryDao(dataSource); this.pictureDao = new PictureDao(dataSource); this.commentDao = new CommentDao(dataSource, sectionInterface.getSystemInterface().getUserHandler()); this.checkSettings(moduleDescriptor.getMutableSettingHandler()); } // TODO This should be done in a DAOFactory but is done here until we have one for this module... private void checkTables(DataSource dataSource) throws SQLException, IOException { log.debug("Checking for gallery tables in datasource " + dataSource + "..."); if (!DBUtils.tableExists(this.dataSource, "galleries")) { log.info(this.moduleDescriptor + " creating galleries table in datasource " + dataSource); String sql = StringUtils .readStreamAsString(this.getClass().getResourceAsStream("daos/dbscripts/GalleryTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } if (!DBUtils.tableExists(this.dataSource, "gallerygroups")) { log.info(this.moduleDescriptor + " creating gallerygroups table in datasource " + dataSource); String sql = StringUtils.readStreamAsString( this.getClass().getResourceAsStream("daos/dbscripts/GalleryGroupsTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } if (!DBUtils.tableExists(this.dataSource, "galleryusers")) { log.info(this.moduleDescriptor + " creating galleryusers table in datasource " + dataSource); String sql = StringUtils.readStreamAsString( this.getClass().getResourceAsStream("daos/dbscripts/GalleryUsersTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } if (!DBUtils.tableExists(this.dataSource, "galleryuploadgroups")) { log.info(this.moduleDescriptor + " creating galleryuploadgroups table in datasource " + dataSource); String sql = StringUtils.readStreamAsString( this.getClass().getResourceAsStream("daos/dbscripts/GalleryUploadGroupsTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } if (!DBUtils.tableExists(this.dataSource, "galleryuploadusers")) { log.info(this.moduleDescriptor + " creating galleryuploadusers table in datasource " + dataSource); String sql = StringUtils.readStreamAsString( this.getClass().getResourceAsStream("daos/dbscripts/GalleryUploadUsersTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } if (!DBUtils.tableExists(this.dataSource, "pictures")) { log.info(this.moduleDescriptor + " creating pictures table in datasource " + dataSource); String sql = StringUtils .readStreamAsString(this.getClass().getResourceAsStream("daos/dbscripts/PicturesTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } if (!DBUtils.tableExists(this.dataSource, "picturecomments")) { log.info(this.moduleDescriptor + " creating picturecomments table in datasource " + dataSource); String sql = StringUtils.readStreamAsString( this.getClass().getResourceAsStream("daos/dbscripts/PictureCommentsTable.sql")); new UpdateQuery(this.dataSource.getConnection(), true, sql).executeUpdate(); } } private void checkSettings(MutableSettingHandler mutableSettingHandler) { Integer thumbQuality = mutableSettingHandler.getInt("thumbQuality"); if (thumbQuality != null && (thumbQuality == Image.SCALE_AREA_AVERAGING || thumbQuality == Image.SCALE_FAST || thumbQuality == Image.SCALE_REPLICATE || thumbQuality == Image.SCALE_SMOOTH)) { this.thumbQuality = thumbQuality; } else if (thumbQuality != null) { log.warn("Illegal thumbQuality setting value detected, " + thumbQuality + " in module " + this.moduleDescriptor); } } @Override public SimpleForegroundModuleResponse defaultMethod(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws Exception { log.info("User " + user + " listing galleries"); ArrayList<Gallery> galleryList = this.galleryDao.getAll(); Document doc = this.createDocument(req, uriParser, user); Element galleriesElement = doc.createElement("galleries"); doc.getFirstChild().appendChild(galleriesElement); if (galleryList != null) { for (Gallery gallery : galleryList) { if (checkBooleanAccess(user, gallery)) { Node galleryNode = gallery.toXML(doc); // get gallery random image SimpleEntry<String, String> pictureEntry = getRandomImage(gallery); if (pictureEntry != null) { galleryNode.appendChild(XMLUtils.createElement("randomFile", pictureEntry.getKey(), doc)); galleryNode.appendChild(XMLUtils.createElement("numPics", pictureEntry.getValue(), doc)); } else { galleryNode.appendChild(XMLUtils.createElement("numPics", "0", doc)); } galleriesElement.appendChild(galleryNode); } } } return new SimpleForegroundModuleResponse(doc, this.moduleDescriptor.getName(), this.getDefaultBreadcrumb()); } protected SimpleEntry<String, String> getRandomImage(Gallery gallery) { SimpleEntry<String, String> pictureEntry = null; // check that url in gallery exist File dir = new File(gallery.getUrl()); boolean read = dir.canRead(); if (!read) { return null; } File[] files = dir.listFiles(fileFilter); if (files.length == 0) { return null; } Random rand = new Random(); int idx = rand.nextInt(files.length); pictureEntry = new SimpleEntry<String, String>(files[idx].getName(), String.valueOf(files.length)); return pictureEntry; } protected Document createDocument(HttpServletRequest req, URIParser uriParser, User user) { Document doc = XMLUtils.createDomDocument(); Element document = doc.createElement("document"); document.appendChild(RequestUtils.getRequestInfoAsXML(doc, req, uriParser)); document.appendChild(this.moduleDescriptor.toXML(doc)); document.appendChild(this.sectionInterface.getSectionDescriptor().toXML(doc)); document.appendChild(XMLUtils.createElement("isAdmin", this.checkBooleanAdminAccess(user).toString(), doc)); doc.appendChild(document); return doc; } @WebPublic public SimpleForegroundModuleResponse gallery(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { //This was done to keep compability with old liks pointing to showGallery return showGallery(req, res, user, uriParser); } @WebPublic public SimpleForegroundModuleResponse showGallery(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { Gallery gallery = null; if (uriParser.size() < 3 || uriParser.size() > 4 || (gallery = this.galleryDao.get(uriParser.get(2).toString())) == null) { throw new URINotFoundException(uriParser); } else { this.checkAccess(user, gallery); Integer page = 1; if (uriParser.size() == 4) { page = NumberUtils.toInt(uriParser.get(3)); if (page == null || page <= 0) { throw new URINotFoundException(uriParser); } } log.info("User " + user + " requested page " + page + " in gallery " + gallery); // check if path is valid File dir = new File(gallery.getUrl()); if (!dir.canRead()) { throw new URINotFoundException(uriParser); } // check that requested page exist // get all filenames, only allow images File[] allFiles = dir.listFiles(fileFilter); int num = allFiles.length; // find number of pages in gallery int pagesInGallery = num % numOfThumbsPerPage == 0 ? num / numOfThumbsPerPage : (num / numOfThumbsPerPage) + 1; if (num == 0) { Document doc = this.createDocument(req, uriParser, user); Element galleryElement = doc.createElement("showGallery"); doc.getFirstChild().appendChild(galleryElement); Node gNode = gallery.toXML(doc); gNode.appendChild(XMLUtils.createElement("pages", "1", doc)); gNode.appendChild(XMLUtils.createElement("currentPage", "1", doc)); gNode.appendChild(XMLUtils.createElement("numPics", "0", doc)); galleryElement.appendChild(XMLUtils.createElement("hasUploadAccess", this.checkBooleanUploadAccess(user, gallery).toString(), doc)); galleryElement.appendChild(gNode); return new SimpleForegroundModuleResponse(doc, gallery.getName(), getDefaultBreadcrumb(), getGalleryBreadcrumb(gallery, req)); } else if (page <= pagesInGallery) { Arrays.sort(allFiles); // find next and previous page Integer nextPage = page == pagesInGallery ? null : page + 1; Integer prevPage = page == 1 ? null : page - 1; // calculate start- and endindex int startIndex = (numOfThumbsPerPage * page) - numOfThumbsPerPage; int endIndex = startIndex + numOfThumbsPerPage; if (page == pagesInGallery) { endIndex = allFiles.length; } // create XML-document containing information about the requested gallery and images Document doc = this.createDocument(req, uriParser, user); Element galleryElement = doc.createElement("showGallery"); doc.getFirstChild().appendChild(galleryElement); galleryElement.appendChild(XMLUtils.createElement("hasUploadAccess", this.checkBooleanUploadAccess(user, gallery).toString(), doc)); Element filesElement = doc.createElement("files"); Node gNode = gallery.toXML(doc); gNode.appendChild(XMLUtils.createElement("pages", String.valueOf(pagesInGallery), doc)); gNode.appendChild(XMLUtils.createElement("currentPage", String.valueOf(page), doc)); gNode.appendChild(XMLUtils.createElement("numPics", String.valueOf(num), doc)); if (nextPage != null) { gNode.appendChild(XMLUtils.createElement("nextPage", nextPage.toString(), doc)); } if (prevPage != null) { gNode.appendChild(XMLUtils.createElement("prevPage", prevPage.toString(), doc)); } // find images for requested page for (int i = startIndex; i < endIndex; i++) { Element fileElement = doc.createElement("file"); String filename = allFiles[i].getName(); fileElement.appendChild(XMLUtils.createElement("filename", filename, doc)); Element commentsElement = doc.createElement("comments"); ArrayList<Comment> comments = commentDao.getByFilenameAndGallery(filename, gallery); if (comments != null) { for (Comment comment : comments) { commentsElement.appendChild(comment.toXML(doc)); } fileElement.appendChild(commentsElement); } filesElement.appendChild(fileElement); } gNode.appendChild(filesElement); galleryElement.appendChild(gNode); return new SimpleForegroundModuleResponse(doc, gallery.getName(), getDefaultBreadcrumb(), getGalleryBreadcrumb(gallery, req)); } else { throw new URINotFoundException(uriParser); } } } private Breadcrumb getGalleryBreadcrumb(Gallery gallery, HttpServletRequest req) { return new Breadcrumb(gallery.getName(), gallery.getDescription(), this.getFullAlias() + "/showGallery/" + gallery.getAlias(), URLType.RELATIVE_FROM_CONTEXTPATH); } @WebPublic public SimpleForegroundModuleResponse image(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { return this.showImage(req, res, user, uriParser); } @WebPublic public SimpleForegroundModuleResponse showImage(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { Gallery gallery = null; if (uriParser.size() != 4 || (gallery = this.galleryDao.get(uriParser.get(2).toString())) == null) { throw new URINotFoundException(uriParser); } else { this.checkAccess(user, gallery); // check if path is valid File dir = null; try { dir = new File(gallery.getUrl()); } catch (Exception ex) { throw new URINotFoundException(uriParser); } // get all filenames String filename = uriParser.get(3); // get all files File[] allFiles = dir.listFiles(fileFilter); Arrays.sort(allFiles); // check if filename exist boolean found = false; int currentIdx = -1; for (int i = 0; i < allFiles.length; i++) { if (allFiles[i].getName().equals(filename)) { found = true; currentIdx = i; break; } } int picsInGallery = allFiles.length; if (found) { log.info("User " + user + " requested image " + filename + " in gallery " + gallery); HttpSession session = req.getSession(true); // find next and previous picture String nextPicture = currentIdx < picsInGallery - 1 ? allFiles[currentIdx + 1].getName() : null; String prevPicture = currentIdx > 0 ? allFiles[currentIdx - 1].getName() : null; // create XML-document containing information about the requested gallery and images Document doc = this.createDocument(req, uriParser, user); Element pictureElement = doc.createElement("showImage"); doc.getFirstChild().appendChild(pictureElement); Node gNode = gallery.toXML(doc); gNode.appendChild(XMLUtils.createElement("numPics", String.valueOf(picsInGallery), doc)); gNode.appendChild(XMLUtils.createElement("currentPic", String.valueOf(currentIdx + 1), doc)); if (currentIdx == 0) { currentIdx++; } pictureElement.appendChild( XMLUtils.createElement("currentPage", (((currentIdx) / numOfThumbsPerPage) + 1) + "", doc)); if (nextPicture != null) { gNode.appendChild(XMLUtils.createElement("nextImage", nextPicture.toString(), doc)); } if (prevPicture != null) { gNode.appendChild(XMLUtils.createElement("prevImage", prevPicture.toString(), doc)); } Element fileElement = doc.createElement("file"); fileElement.appendChild(XMLUtils.createElement("filename", filename, doc)); Element commentsElement = doc.createElement("comments"); ArrayList<Comment> comments = commentDao.getByFilenameAndGallery(filename, gallery); //TODO move this to a separate method and add captcha support if (req.getMethod().equalsIgnoreCase("POST")) { String commentStatus = req.getParameter("viewComments"); if (commentStatus != null) { if (commentStatus.equals("true")) { session.setAttribute(this.moduleDescriptor.getModuleID() + ".showAll", true); } else { session.setAttribute(this.moduleDescriptor.getModuleID() + ".showAll", false); } } String commentText = req.getParameter("commentText"); if (commentText != null && (this.allowAnonymousComments || user != null)) { try { if (StringUtils.isEmpty(commentText)) { throw new ValidationException( new ValidationError("commentText", ValidationErrorType.RequiredField)); } Comment comment = new Comment(); comment.setComment(commentText); comment.setDate(new Timestamp(System.currentTimeMillis())); comment.setPictureID(pictureDao.getPictureIDByFilenameAndGallery(filename, gallery)); if (user != null) { comment.setUser(user); } log.info("User " + user + " adding comment " + comment + " to image " + filename + " in gallery " + gallery); commentDao.add(comment); res.sendRedirect(req.getRequestURI()); } catch (ValidationException e) { fileElement.appendChild(e.toXML(doc)); } } } // check if user wants to show all comments or not Boolean showAll = (Boolean) session.getAttribute(this.moduleDescriptor.getModuleID() + ".showAll"); if (showAll == null || showAll) { commentsElement.appendChild(XMLUtils.createElement("showAll", "true", doc)); if (comments != null) { for (Comment comment : comments) { commentsElement.appendChild(comment.toXML(doc)); } } } if (comments != null) { commentsElement.appendChild( XMLUtils.createElement("commentsNum", String.valueOf(comments.size()), doc)); } fileElement.appendChild(commentsElement); if (this.allowAnonymousComments || user != null) { fileElement.appendChild(doc.createElement("commentsAllowed")); } gNode.appendChild(fileElement); pictureElement.appendChild(gNode); return new SimpleForegroundModuleResponse(doc, filename, getDefaultBreadcrumb(), getGalleryBreadcrumb(gallery, req), getImageBreadcrumb(gallery, filename, req)); } else { throw new URINotFoundException(uriParser); } } } private Breadcrumb getImageBreadcrumb(Gallery gallery, String filename, HttpServletRequest req) { return new Breadcrumb(filename, filename, this.getFullAlias() + "/showImage/" + gallery.getAlias() + "/" + filename, URLType.RELATIVE_FROM_CONTEXTPATH); } @WebPublic public SimpleForegroundModuleResponse smallThumb(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { Gallery gallery = null; // check that the requested gallery exist if (uriParser.size() != 4 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { this.checkAccess(user, gallery); String filename = uriParser.get(3).toString(); // check if file is readable if (FileUtils.isReadable(gallery.getUrl() + File.separator + filename) && SimpleFileFilter.isValidFilename(filename)) { log.debug( "User " + user + " requesting small thumb of image " + filename + " in gallery " + gallery); // check if there are thumbnails created Picture picture = pictureDao.getByFilename(filename, gallery.getGalleryID(), true, false); if (picture == null) { picture = createThumbs(filename, gallery); } try { writePicture(picture, false, res); } catch (Exception e) { log.info("Caught exception " + e + " while sending picture " + picture + " in gallery " + gallery + " to " + user); } } else { log.info("The picture " + filename + " does not exist in gallery " + gallery); throw new URINotFoundException(uriParser); } } return null; } @WebPublic public SimpleForegroundModuleResponse mediumThumb(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { Gallery gallery = null; // check that the requested gallery exist if (uriParser.size() != 4 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { this.checkAccess(user, gallery); String filename = uriParser.get(3).toString(); if (FileUtils.isReadable(gallery.getUrl() + File.separator + filename) && SimpleFileFilter.isValidFilename(filename)) { log.debug("User " + user + " requesting medium thumb of image " + filename + " in gallery " + gallery); // check if there are thumbnails created Picture picture = pictureDao.getByFilename(filename, gallery.getGalleryID(), false, true); if (picture == null) { picture = createThumbs(filename, gallery); } try { writePicture(picture, true, res); } catch (Exception e) { log.info("Caught exception " + e + " while sending picture " + picture + " in gallery " + gallery + " to " + user); } } else { log.info("The picture " + filename + " does not exist in gallery " + gallery); throw new URINotFoundException(uriParser); } } return null; } protected Picture createThumbs(String filename, Gallery gallery) throws SQLException, IOException { log.info("Creating thumbs for picture " + filename + " in gallery " + gallery); Picture picture = new Picture(); BufferedImage image = ImageUtils.getImage(gallery.getUrl() + File.separator + filename); BufferedImage smallImage = ImageUtils.scaleImage(image, this.smallImageMaxHeight, this.smallImageMaxWidth, thumbQuality, BufferedImage.TYPE_INT_RGB); BufferedImage mediumImage = ImageUtils.scaleImage(image, this.mediumImageMaxHeight, this.mediumImageMaxWidth, thumbQuality, BufferedImage.TYPE_INT_RGB); ByteArrayOutputStream smallThumbStream = new ByteArrayOutputStream(); ImageIO.write(smallImage, "jpg", smallThumbStream); byte[] smallThumbByteArray = smallThumbStream.toByteArray(); ByteArrayOutputStream mediumThumbStream = new ByteArrayOutputStream(); ImageIO.write(mediumImage, "jpg", mediumThumbStream); byte[] mediumThumbByteArray = mediumThumbStream.toByteArray(); picture.setSmallThumb(new SerialBlob(smallThumbByteArray)); picture.setMediumThumb(new SerialBlob(mediumThumbByteArray)); picture.setFilename(filename); picture.setGalleryID(gallery.getGalleryID()); pictureDao.set(picture); return picture; } protected void checkAccess(User user, Gallery gallery) throws AccessDeniedException { if (!AccessUtils.checkAccess(user, gallery) && !AccessUtils.checkAccess(user, this)) { throw new AccessDeniedException("Permission to gallery " + gallery + " denied"); } } protected void checkAdminAccess(User user) throws AccessDeniedException { if (!AccessUtils.checkAccess(user, this)) { throw new AccessDeniedException("Gallery admin access denied"); } } private void checkUploadAccess(User user, Gallery gallery) throws AccessDeniedException { if (!AccessUtils.checkAccess(user, this) && !AccessUtils.checkAccess(user, new GalleryUploadAccessWrapper(gallery))) { throw new AccessDeniedException("Gallery upload access denied in gallery " + gallery); } } protected boolean checkBooleanAccess(User user, Gallery gallery) { return AccessUtils.checkAccess(user, gallery) || this.checkBooleanAdminAccess(user); } protected Boolean checkBooleanAdminAccess(User user) { return AccessUtils.checkAccess(user, this); } private Boolean checkBooleanUploadAccess(User user, Gallery gallery) { return AccessUtils.checkAccess(user, new GalleryUploadAccessWrapper(gallery)); } public static void writePicture(Picture picture, boolean mediumThumb, HttpServletResponse res) throws SQLException, IOException { // send thumb to user Blob blob = null; if (mediumThumb) { blob = picture.getMediumThumb(); } else { blob = picture.getSmallThumb(); } HTTPUtils.setContentLength(blob.length(), res); res.setContentType("image/jpeg"); res.setHeader("Content-Disposition", "inline; filename=\"" + FileUtils.toValidHttpFilename(picture.getFilename()) + "\""); InputStream in = null; OutputStream out = null; try { in = blob.getBinaryStream(); out = res.getOutputStream(); StreamUtils.transfer(in, out); } finally { StreamUtils.closeStream(in); StreamUtils.closeStream(out); } } @WebPublic public SimpleForegroundModuleResponse getImage(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws SQLException, URINotFoundException, AccessDeniedException { Gallery gallery = null; // check that the requested gallery exist if (uriParser.size() != 4 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { this.checkAccess(user, gallery); String filename = uriParser.get(3).toString(); // check if file is readable if (FileUtils.isReadable(gallery.getUrl() + File.separator + filename) && SimpleFileFilter.isValidFilename(filename)) { FileInputStream in = null; OutputStream out = null; try { log.debug("User " + user + " requesting image " + filename + " in gallery " + gallery); File file = new File(gallery.getUrl() + File.separator + filename); in = new FileInputStream(file); HTTPUtils.setContentLength(file.length(), res); res.setContentType(MimeUtils.getMimeType(file)); res.setHeader("Content-Disposition", "inline; filename=\"" + FileUtils.toValidHttpFilename(filename) + "\""); out = res.getOutputStream(); StreamUtils.transfer(in, out); } catch (RuntimeException e) { log.debug("Caught exception " + e + " while sending picture " + filename + " in gallery " + gallery + " to " + user); } catch (IOException e) { log.debug("Caught exception " + e + " while sending picture " + filename + " in gallery " + gallery + " to " + user); } finally { StreamUtils.closeStream(in); StreamUtils.closeStream(out); } } else { log.info("The picture " + filename + " in gallery " + gallery + " requested by user " + user + " does not exist"); throw new URINotFoundException(uriParser); } } return null; } @Override public List<SettingDescriptor> getSettings() { ArrayList<SettingDescriptor> combinedSettings = new ArrayList<SettingDescriptor>(); List<? extends SettingDescriptor> superSettings = super.getSettings(); if (superSettings != null) { combinedSettings.addAll(superSettings); } combinedSettings.addAll(SETTINGDESCRIPTORS); // Generate group multilist settingdescriptor ArrayList<ValueDescriptor> groupValueDescriptors = new ArrayList<ValueDescriptor>(); for (Group group : sectionInterface.getSystemInterface().getGroupHandler().getGroups(false)) { groupValueDescriptors.add(new ValueDescriptor(group.getName(), group.getGroupID().toString())); } combinedSettings.add(SettingDescriptor.createMultiListSetting("adminGroupIDs", "Admin groups", "Groups that are allowed to administrate the gallery module", false, null, groupValueDescriptors)); // Generate user multilist settingdescriptor ArrayList<ValueDescriptor> userValueDescriptors = new ArrayList<ValueDescriptor>(); for (User user : sectionInterface.getSystemInterface().getUserHandler().getUsers(false, false)) { userValueDescriptors.add(new ValueDescriptor(user.getFirstname() + " " + user.getLastname(), user.getUserID().toString())); } combinedSettings.add(SettingDescriptor.createMultiListSetting("adminUserIDs", "Admin users", "Users that are allowed to administrate the gallery module", false, null, userValueDescriptors)); return combinedSettings; } @WebPublic public SimpleForegroundModuleResponse deleteGallery(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { this.checkAdminAccess(user); Gallery gallery = null; if (uriParser.size() < 3 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { log.info("User " + user + " deleting gallery " + gallery); this.galleryDao.delete(gallery); this.redirectToDefaultMethod(req, res); return null; } } @WebPublic public SimpleForegroundModuleResponse regenerateGalleryThubms(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { this.checkAdminAccess(user); Gallery gallery = null; if (uriParser.size() < 3 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { Long currentTime = System.currentTimeMillis(); log.info("User " + user + " regenerating thumbs for gallery " + gallery + "..."); this.createGalleryThumbs(gallery, true); log.info("User " + user + " regenerated thumbs for gallery " + gallery + " in " + TimeUtils.millisecondsToString(System.currentTimeMillis() - currentTime)); this.redirectToDefaultMethod(req, res); return null; } } @WebPublic(alias = "download") public SimpleForegroundModuleResponse downloadGallery(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws SQLException, URINotFoundException { Gallery gallery = null; if (uriParser.size() < 3 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } // check if path is valid File dir = new File(gallery.getUrl()); if (!dir.canRead()) { throw new URINotFoundException(uriParser); } log.info("User " + user + " downloading gallery " + gallery + "..."); long startTime = System.currentTimeMillis(); File[] files = dir.listFiles(fileFilter); ZipOutputStream zipOutputStream = null; try { res.setContentType("application/zip"); res.setHeader("Content-Disposition", "inline; filename=\"" + FileUtils.toValidHttpFilename(gallery.getName()) + ".zip\""); res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate"); zipOutputStream = new ZipOutputStream(res.getOutputStream()); zipOutputStream.setLevel(ZipOutputStream.STORED); ZipUtils.addFiles(files, zipOutputStream); zipOutputStream.flush(); log.info("Sent gallery " + gallery + " containing " + files.length + " files to user " + user + " in " + TimeUtils.millisecondsToString(System.currentTimeMillis() - startTime)); } catch (IOException e) { log.info("Error sending gallery " + gallery + " to user " + user); } finally { StreamUtils.closeStream(zipOutputStream); } return null; } @WebPublic public synchronized SimpleForegroundModuleResponse regenerateThumbs(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws Exception { this.checkAdminAccess(user); Long currentTime = System.currentTimeMillis(); log.info("User " + user + " regenerating thumbs for all galleries..."); ArrayList<Gallery> galleries = this.galleryDao.getAll(); for (Gallery gallery : galleries) { this.createGalleryThumbs(gallery, true); } log.info("User " + user + " regenerated thumbs for all galleries in " + TimeUtils.millisecondsToString(System.currentTimeMillis() - currentTime)); this.redirectToDefaultMethod(req, res); return null; } @WebPublic public SimpleForegroundModuleResponse updateComment(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { this.checkAdminAccess(user); Comment comment = null; if (uriParser.size() < 3 || (comment = this.commentDao.get(Integer.parseInt((uriParser.get(2))))) == null) { throw new URINotFoundException(uriParser); } else { String commentText = req.getParameter("comment"); if (!StringUtils.isEmpty(commentText)) { log.info("User " + user + " updating comment " + comment + " new text " + commentText); comment.setComment(commentText); this.commentDao.update(comment); } Picture picture = this.pictureDao.get(comment.getPictureID(), false, false); Gallery gallery = this.galleryDao.get(picture.getGalleryID()); res.sendRedirect(this.getModuleURI(req) + "/showImage/" + URLEncoder.encode(gallery.getAlias(), "UTF-8") + "/" + URLEncoder.encode(picture.getFilename(), "UTF-8")); return null; } } @WebPublic public SimpleForegroundModuleResponse deleteComment(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { this.checkAdminAccess(user); Comment comment = null; if (uriParser.size() < 3 || (comment = this.commentDao.get(Integer.parseInt((uriParser.get(2))))) == null) { throw new URINotFoundException(uriParser); } else { log.info("User " + user + " deleting comment " + comment); Picture picture = this.pictureDao.get(comment.getPictureID(), false, false); Gallery gallery = this.galleryDao.get(picture.getGalleryID()); this.commentDao.delete(comment); res.sendRedirect(this.getModuleURI(req) + "/showImage/" + URLEncoder.encode(gallery.getAlias(), "UTF-8") + "/" + URLEncoder.encode(picture.getFilename(), "UTF-8")); return null; } } @WebPublic public SimpleForegroundModuleResponse deleteImage(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, ValidationException, AccessDeniedException { this.checkAdminAccess(user); Gallery gallery = null; if (req.getMethod().equalsIgnoreCase("POST")) { if (uriParser.size() < 3 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } String[] filenames; if ((filenames = req.getParameterValues("delete")) != null) { List<File> filesToDelete = new ArrayList<File>(); for (String filename : filenames) { File f = new File(gallery.getUrl() + "/" + filename); // Make sure the picture (file) exists and isn't write protected if (!f.exists() || !f.canWrite() || f.isDirectory()) { throw new URINotFoundException(uriParser); } filesToDelete.add(f); } for (File f : filesToDelete) { log.info("User " + user + " deleting image " + f); // delete picture boolean success = f.delete(); // delete thumbs from database Picture picture = pictureDao.getByFilename(f.getName(), gallery.getGalleryID(), false, false); pictureDao.delete(picture); if (!success) { throw new ValidationException(new ValidationError("UnableToParseRequest")); } } } res.sendRedirect( this.getModuleURI(req) + "/showGallery/" + URLEncoder.encode(gallery.getAlias(), "UTF-8")); } else if (uriParser.size() < 4 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { String filename = uriParser.get(3); File f = new File(gallery.getUrl() + "/" + filename); // Make sure the picture (file) exists and isn't write protected if (!f.exists() || !f.canWrite() || f.isDirectory()) { throw new URINotFoundException(uriParser); } log.info("User " + user + " deleting image " + f); // delete picture boolean success = f.delete(); // delete thumbs from database Picture picture = pictureDao.getByFilename(filename, gallery.getGalleryID(), false, false); pictureDao.delete(picture); if (!success) { throw new ValidationException(new ValidationError("UnableToParseRequest")); } res.sendRedirect( this.getModuleURI(req) + "/showGallery/" + URLEncoder.encode(gallery.getAlias(), "UTF-8")); } return null; } @SuppressWarnings("deprecation") @WebPublic public SimpleForegroundModuleResponse addGallery(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws Exception { this.checkAdminAccess(user); ValidationException validationException = null; MultipartRequest requestWrapper = null; if (req.getMethod().equalsIgnoreCase("POST")) { try { requestWrapper = new MultipartRequest(this.ramThreshold * BinarySizes.KiloByte, this.diskThreshold * BinarySizes.MegaByte, req); Gallery gallery = GalleryPopulator.populate(requestWrapper); log.info("User " + user + " adding gallery " + gallery); gallery.setGalleryID(this.galleryDao.add(gallery)); Boolean zipUpload = requestWrapper.getParameter("uploadCheck") != null; if (zipUpload) { try { FileItem fileItem = requestWrapper.getFile(0); this.uploadGalleryZip(fileItem, gallery); } catch (FileUploadException e) { this.galleryDao.delete(gallery); throw new ValidationException(new ValidationError("UnableToParseRequest")); } catch (IOException e) { this.galleryDao.delete(gallery); throw new ValidationException(new ValidationError("UnableToParseRequest")); } finally { if (requestWrapper != null) { requestWrapper.deleteFiles(); } } } // create thumbs this.createGalleryThumbs(gallery, false); res.sendRedirect(this.getModuleURI(req)); return null; } catch (ValidationException e) { validationException = e; } } Document doc = this.createDocument(req, uriParser, user); Element addGalleryElement = doc.createElement("addGallery"); doc.getFirstChild().appendChild(addGalleryElement); if (!StringUtils.isEmpty(this.path)) { addGalleryElement.appendChild(XMLUtils.createElement("path", this.path, doc)); } if (validationException != null) { addGalleryElement.appendChild(validationException.toXML(doc)); addGalleryElement.appendChild(RequestUtils.getRequestParameters(requestWrapper, doc)); } AccessUtils.appendGroupsAndUsers(doc, addGalleryElement, sectionInterface.getSystemInterface().getUserHandler(), sectionInterface.getSystemInterface().getGroupHandler()); return new SimpleForegroundModuleResponse(doc, this.moduleDescriptor.getName(), this.getDefaultBreadcrumb()); } @SuppressWarnings("deprecation") @WebPublic public SimpleForegroundModuleResponse addImages(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws Exception { Gallery gallery = null; if (uriParser.size() < 3 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { this.checkUploadAccess(user, gallery); ValidationException validationException = null; if (req.getMethod().equalsIgnoreCase("POST")) { MultipartRequest requestWrapper = null; try { requestWrapper = new MultipartRequest(this.ramThreshold * BinarySizes.KiloByte, this.diskThreshold * BinarySizes.MegaByte, req); FileItem fileItem = requestWrapper.getFile(0); if (fileItem.getName() != null && fileItem.getName().toLowerCase().endsWith(".zip")) { log.info("User " + user + " adding images from zip file to gallery " + gallery); int imageCount = this.uploadGalleryZip(fileItem, gallery); log.info("User " + user + " added " + imageCount + " images to gallery " + gallery); } else if (fileFilter.accept(fileItem)) { log.info("User " + user + " adding image to gallery " + gallery); File file = new File(gallery.getUrl() + "/" + fileItem.getName()); fileItem.write(file); log.info("User " + user + " added 1 image to gallery " + gallery); } else { throw new ValidationException(new ValidationError("UnableToParseRequest")); } // create thumbs this.createGalleryThumbs(gallery, false); res.sendRedirect(this.getModuleURI(req)); return null; } catch (ValidationException e) { validationException = e; } catch (FileSizeLimitExceededException e) { validationException = new ValidationException(new ValidationError("FileSizeLimitExceeded")); } catch (FileUploadException e) { validationException = new ValidationException(new ValidationError("UnableToParseRequest")); } finally { if (requestWrapper != null) { requestWrapper.deleteFiles(); } } } Document doc = this.createDocument(req, uriParser, user); Element addImageElement = doc.createElement("addImages"); doc.getFirstChild().appendChild(addImageElement); addImageElement.appendChild(gallery.toXML(doc)); XMLUtils.appendNewElement(doc, addImageElement, "diskThreshold", diskThreshold); if (validationException != null) { addImageElement.appendChild(validationException.toXML(doc)); addImageElement.appendChild(RequestUtils.getRequestParameters(req, doc)); } AccessUtils.appendGroupsAndUsers(doc, addImageElement, sectionInterface.getSystemInterface().getUserHandler(), sectionInterface.getSystemInterface().getGroupHandler()); return new SimpleForegroundModuleResponse(doc, this.moduleDescriptor.getName(), this.getDefaultBreadcrumb()); } } @SuppressWarnings("deprecation") @WebPublic public SimpleForegroundModuleResponse updateGallery(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws IOException, SQLException, URINotFoundException, AccessDeniedException { this.checkAdminAccess(user); Gallery gallery = null; if (uriParser.size() != 3 || (gallery = this.galleryDao.get(uriParser.get(2))) == null) { throw new URINotFoundException(uriParser); } else { ValidationException validationException = null; if (req.getMethod().equalsIgnoreCase("POST")) { try { gallery = GalleryPopulator.populate(gallery, req); log.info("User " + user + " updating gallery " + gallery); this.galleryDao.update(gallery); res.sendRedirect(this.getModuleURI(req)); return null; } catch (ValidationException e) { validationException = e; } } Document doc = this.createDocument(req, uriParser, user); Element updateGalleryElement = doc.createElement("updateGallery"); doc.getFirstChild().appendChild(updateGalleryElement); if (!StringUtils.isEmpty(this.path)) { updateGalleryElement.appendChild(XMLUtils.createElement("path", this.path, doc)); } updateGalleryElement.appendChild(gallery.toXML(doc)); if (validationException != null) { updateGalleryElement.appendChild(validationException.toXML(doc)); updateGalleryElement.appendChild(RequestUtils.getRequestParameters(req, doc)); } AccessUtils.appendGroupsAndUsers(doc, updateGalleryElement, sectionInterface.getSystemInterface().getUserHandler(), sectionInterface.getSystemInterface().getGroupHandler()); return new SimpleForegroundModuleResponse(doc, this.moduleDescriptor.getName(), this.getDefaultBreadcrumb()); } } @WebPublic public synchronized SimpleForegroundModuleResponse checkForNewImages(HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser) throws Exception { this.checkAdminAccess(user); log.info("User " + user + " checking for new images in all galleries"); ArrayList<Gallery> galleries = this.galleryDao.getAll(); for (Gallery gallery : galleries) { this.createGalleryThumbs(gallery, false); } this.redirectToDefaultMethod(req, res); return null; } protected int uploadGalleryZip(FileItem fileItem, Gallery gallery) throws FileNotFoundException, IOException, Exception { File file = null; int fileCount = 0; try { file = File.createTempFile("galleryupload-" + System.currentTimeMillis(), ".zip"); fileItem.write(file); ZipFile zipFile = new ZipFile(file); Enumeration<? extends ZipEntry> e = zipFile.entries(); while (e.hasMoreElements()) { ZipEntry ze = e.nextElement(); if (!ze.isDirectory() && SimpleFileFilter.isValidFilename(ze.getName())) { String filename = FilenameUtils.getName(ze.getName()); if (new File(gallery.getUrl() + "/" + filename).exists()) { log.info("Skipping file " + filename + ", already exists in gallery " + gallery + " in directory " + gallery.getUrl()); continue; } log.info("Adding file " + filename + " to gallery " + gallery + " in directory " + gallery.getUrl()); FileOutputStream fileOutputStream = null; InputStream zipEntryInputStream = null; try { fileOutputStream = new FileOutputStream(gallery.getUrl() + "/" + filename); zipEntryInputStream = zipFile.getInputStream(ze); StreamUtils.transfer(zipEntryInputStream, fileOutputStream); fileCount++; } finally { StreamUtils.closeStream(zipEntryInputStream); StreamUtils.closeStream(fileOutputStream); } } } } finally { if (file != null) { file.delete(); } } return fileCount; } protected void createGalleryThumbs(Gallery gallery, boolean overwrite) throws URINotFoundException, SQLException, IOException { synchronized (this.mutexKeyProvider.getKey(gallery)) { // get all files from the gallery on filesystem File dir = new File(gallery.getUrl()); if (!dir.canRead()) { return; } // get all images in gallerydirectory File[] allFiles = dir.listFiles(fileFilter); if (allFiles != null) { for (File file : allFiles) { if (file.exists() && file.canRead()) { if (overwrite) { this.createThumbs(file.getName(), gallery); } else { Picture picture = this.pictureDao.getByFilename(file.getName(), gallery.getGalleryID(), false, false); if (picture == null) { try { this.createThumbs(file.getName(), gallery); } catch (RuntimeException e) { log.error("Error " + e + " creating thumb for file " + file.getName() + " in gallery " + gallery); } } } } else { log.warn("Unable to read file " + file + " in gallery " + gallery); } } } } } @Override public boolean allowsAdminAccess() { return false; } @Override public boolean allowsAnonymousAccess() { return false; } @Override public boolean allowsUserAccess() { return false; } @Override public Collection<Integer> getAllowedGroupIDs() { return this.adminGroupIDs; } @Override public Collection<Integer> getAllowedUserIDs() { return this.adminUserIDs; } }