001/*
002 * cilla - Blog Management System
003 *
004 * Copyright (C) 2012 Richard "Shred" Körber
005 *   http://cilla.shredzone.org
006 *
007 * This program is free software: you can redistribute it and/or modify
008 * it under the terms of the GNU Affero General Public License as published
009 * by the Free Software Foundation, either version 3 of the License, or
010 * (at your option) any later version.
011 *
012 * This program is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU Affero General Public License
018 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
019 */
020package org.shredzone.cilla.view;
021
022import java.util.List;
023
024import javax.annotation.Resource;
025import javax.servlet.http.HttpServletRequest;
026import javax.servlet.http.HttpServletResponse;
027
028import org.shredzone.cilla.core.datasource.ResourceDataSource;
029import org.shredzone.cilla.core.model.GallerySection;
030import org.shredzone.cilla.core.model.Picture;
031import org.shredzone.cilla.service.PageService;
032import org.shredzone.cilla.service.PictureService;
033import org.shredzone.cilla.view.annotation.Framed;
034import org.shredzone.cilla.view.model.PictureInfoModel;
035import org.shredzone.cilla.web.comment.CommentFormHandler;
036import org.shredzone.cilla.web.page.ResourceLockManager;
037import org.shredzone.cilla.web.plugin.manager.ImageProcessingManager;
038import org.shredzone.cilla.ws.ImageProcessing;
039import org.shredzone.cilla.ws.exception.CillaServiceException;
040import org.shredzone.commons.view.annotation.Optional;
041import org.shredzone.commons.view.annotation.PathPart;
042import org.shredzone.commons.view.annotation.Qualifier;
043import org.shredzone.commons.view.annotation.View;
044import org.shredzone.commons.view.annotation.ViewHandler;
045import org.shredzone.commons.view.exception.ErrorResponseException;
046import org.shredzone.commons.view.exception.PageNotFoundException;
047import org.shredzone.commons.view.exception.ViewException;
048import org.springframework.stereotype.Component;
049
050/**
051 * Views for showing the standalone parts of the gallery section.
052 *
053 * @author Richard "Shred" Körber
054 */
055@ViewHandler
056@Component
057public class GalleryView extends AbstractView {
058
059    private @Resource PageService pageService;
060    private @Resource PictureService pictureService;
061    private @Resource ResourceLockManager unlockService;
062    private @Resource ImageProcessingManager imageProcessingManager;
063    private @Resource CommentFormHandler commentFormHandler;
064
065    /**
066     * Shows a single picture of a gallery.
067     */
068    @Framed
069    @View(pattern = "/show/gallery/${section.id}/picture/${picture.id}.html", signature = {"section", "picture"})
070    @View(pattern = "/ajax/gallery/${section.id}/picture/${picture.id}.html", signature = {"section", "picture"}, qualifier = "ajax")
071    public String galleryPictureView(
072            @PathPart("section.id") GallerySection section,
073            @PathPart("picture.id") Picture picture,
074            @Qualifier String qualifier,
075            HttpServletRequest req, HttpServletResponse resp)
076    throws ViewException {
077        if (!pageService.isVisible(section.getPage())) {
078            throw new ErrorResponseException(HttpServletResponse.SC_FORBIDDEN);
079        }
080
081        commentFormHandler.handleComment(picture, req, section.isCommentable());
082
083        List<Picture> pictureList = section.getPictures();
084        int size = pictureList.size();
085        int current = pictureList.indexOf(picture);
086
087        if (current < 0 || size == 0) {
088            // There is such a picture, but not in this gallery!
089            throw new PageNotFoundException("No such picture in this gallery.");
090        }
091
092        if (redirectRestricted(section.getPage(), req, resp)) {
093            return null;
094        }
095
096        req.setAttribute("page", section.getPage());
097        req.setAttribute("section", section);
098        req.setAttribute("picture", picture);
099        req.setAttribute("info", new PictureInfoModel(pictureList, current));
100
101        if ("ajax".equals(qualifier)) {
102            return "section/gallery/picture-ajax.jsp";
103        } else {
104            return "section/gallery/picture.jsp";
105        }
106    }
107
108    /**
109     * Shows a map of the location the picture was taken.
110     */
111    @Framed
112    @View(pattern = "/show/gallery/${section.id}/map/${picture.id}.html", name="gallery.map")
113    public String galleryMapView(
114            @PathPart("section.id") GallerySection section,
115            @PathPart("picture.id") Picture picture,
116            HttpServletRequest req, HttpServletResponse resp)
117    throws ViewException {
118        if (!pageService.isVisible(section.getPage())) {
119            throw new ErrorResponseException(HttpServletResponse.SC_FORBIDDEN);
120        }
121
122        if (!section.getPictures().contains(picture)) {
123            // There is such a picture, but not in this gallery!
124            throw new PageNotFoundException("No such picture in this gallery.");
125        }
126
127        if (redirectRestricted(section.getPage(), req, resp)) {
128            return null;
129        }
130
131        req.setAttribute("page", section.getPage());
132        req.setAttribute("section", section);
133        req.setAttribute("picture", picture);
134
135        return "section/gallery/map.jsp";
136    }
137
138    /**
139     * Streams the picture of a gallery.
140     */
141    @View(pattern = "/picture/${picture.id}-${#type}.${#suffix(picture.image.contentType)}", signature = {"picture", "#type"})
142    @View(pattern = "/picture/${picture.id}.${#suffix(picture.image.contentType)}", signature = {"picture"})
143    public void pictureView(
144            @PathPart("picture.id") Picture picture,
145            @Optional @PathPart("#type") String type,
146            HttpServletRequest req, HttpServletResponse resp)
147    throws ViewException, CillaServiceException {
148        // Take measures against deep linking of the pictures. No need to check page
149        // permissions, as the picture is not unlocked if the visitor had no access
150        // to the page.
151        if (!unlockService.isUnlocked(req.getSession(), picture)) {
152            throw new ErrorResponseException(HttpServletResponse.SC_FORBIDDEN);
153        }
154
155        ImageProcessing ip = null;
156        if (type != null) {
157            ip = imageProcessingManager.createImageProcessing(type);
158            if (ip == null) {
159                throw new ErrorResponseException(HttpServletResponse.SC_NOT_FOUND);
160            }
161        }
162
163        ResourceDataSource ds = pictureService.getImage(picture, ip);
164        streamDataSource(ds, req, resp);
165    }
166
167}