@AuthorizedPhotos
public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album {
- private static final Logger LOGGER = Logger.getLogger(AuthorizedAlbum.class
- .getName());
+ private static final Logger LOGGER = Logger.getLogger(AuthorizedAlbum.class.getName());
private AuthorizationService _authorizer;
private HttpSession _session;
- protected AuthorizedAlbum() {
- super(null);
- // for CDI
- }
-
/**
* Constructs concurrent album as a decorator for an album implementation.
- *
- * @param aAlbum
- * Album to decorate.
+ *
+ * @param aAlbum Album to decorate.
*/
@Inject
- public AuthorizedAlbum(@AllPhotos Album aAlbum,
- AuthorizationService aService,
- @PhotoCache Cache<String, ArrayList<PhotoEntry>> aCache,
- HttpSession aSession) {
+ public AuthorizedAlbum(@AllPhotos Album aAlbum, AuthorizationService aService,
+ @PhotoCache Cache<String, ArrayList<PhotoEntry>> aCache, HttpSession aSession) {
super(aAlbum);
_authorizer = aService;
- _authorizedEntries = new CachedObject<String, ArrayList<PhotoEntry>>(
- aCache, aSession.getId() + "/" + aAlbum.getPath(),
- new CachedObject.Computation<String, ArrayList<PhotoEntry>>() {
- public ArrayList<PhotoEntry> getObject(String aObjectKey) {
- return AuthorizedAlbum.this.compute();
- }
- });
+ _authorizedEntries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache,
+ "session:" + aSession.getId() + "/" + aAlbum.getPath(),
+ new CachedObject.Computation<String, ArrayList<PhotoEntry>>() {
+ public ArrayList<PhotoEntry> getObject(String aObjectKey) {
+ return AuthorizedAlbum.this.compute();
+ }
+ });
_session = aSession;
}
/**
* Computes the cache of photo entries to which read access is allowed.
- *
+ *
* @return Photo entries to which read access is allowed.
*/
private synchronized ArrayList<PhotoEntry> compute() {
// automatically.
}
}
+ if (result == null) {
+ throw new RuntimeException("Result is null");
+ }
return result;
}
/**
* Creates a decorate for the photo entry to make it safe for concurrent
* access.
- *
- * @param aEntry
- * Entry to decorate
+ *
+ * @param aEntry Entry to decorate
* @return Decorated photo.
*/
private <T extends PhotoEntry> T decorate(T aEntry) {
} else if (aEntry instanceof Photo) {
return (T) new AuthorizedPhoto((Photo) aEntry);
} else if (aEntry instanceof Album) {
- return (T) new AuthorizedAlbum((Album) aEntry, _authorizer,
- _authorizedEntries.getCache(), _session);
+ return (T) new AuthorizedAlbum((Album) aEntry, _authorizer, _authorizedEntries.getCache(), _session);
} else {
- throw new IllegalArgumentException(
- "Entry is neither a photo nor an album: " + aEntry);
+ throw new IllegalArgumentException("Entry is neither a photo nor an album: " + aEntry);
}
}
} else {
if (!(entry instanceof Album)) {
throw new IllegalArgumentException(getPath() + " " +
- aPath);
+ aPath);
}
return ((Album) entry).getEntry(remainder);
}
*/
public void addImage(String aId, InputStream aImage) throws IOException {
_authorizer.check(this, new WriteOperation());
+ int oldsize = _authorizedEntries.get().size();
_authorizedEntries.invalidate();
decorated().addImage(aId, aImage);
+ int newsize = _authorizedEntries.get().size();
+ if (newsize != oldsize + 1) {
+ throw new RuntimeException("cache was not refreshed property");
+ }
}
/*
*/
public void removeEntry(String aId) throws IOException {
// Check whether deletion is allowed.
- PhotoEntry entry = _authorizer.check(decorated().getEntry("/" + aId),
- new DeleteOperation());
+ PhotoEntry entry = _authorizer.check(decorated().getEntry("/" + aId), new DeleteOperation());
_authorizedEntries.invalidate();
decorated().removeEntry(aId);
}
public Photo findPhotoBefore(String aId) {
Photo entry = decorated().findPhotoBefore(aId);
- while (entry != null &&
- !_authorizer.isAllowed(entry, new AllOperation())) {
+ while (entry != null && !_authorizer.isAllowed(entry, new AllOperation())) {
entry = decorated().findPhotoBefore(entry.getId());
}
return decorate(entry);
public Photo findPhotoAfter(String aId) {
Photo entry = decorated().findPhotoAfter(aId);
- while (entry != null &&
- !_authorizer.isAllowed(entry, new AllOperation())) {
+ while (entry != null && !_authorizer.isAllowed(entry, new AllOperation())) {
entry = decorated().findPhotoAfter(entry.getId());
}
return decorate(entry);
}
_dir = aDir;
_path = aPath;
- _entries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache, aPath, new AlbumComputation(this));
+ _entries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache, "fs:" + aPath, new AlbumComputation(this));
}
/**
--- /dev/null
+/*
+ * Copyright 2005 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.photos.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.inject.Inject;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.wamblee.photos.model.Album;
+import org.wamblee.photos.model.Photo;
+import org.wamblee.photos.model.PhotoEntry;
+import org.wamblee.photos.model.plumbing.AuthorizedPhotos;
+
+/**
+ * Sends an image (either thumbnail or full size) from the photo album.
+ * <p/>
+ * The returned picture is defined based on
+ * {@link javax.servlet.http.HttpServletRequest#getPathInfo}. as follows. If the
+ * path info starts with the string defined by {@link #THUMBNAIL_NAME}, then a
+ * thumbnail image is served and the rest of the path info is the relative path
+ * of the picture. Otherwise the path info is identical to the relative path of
+ * the picture.
+ */
+public class ImageSender extends HttpServlet {
+
+ @Inject
+ @AuthorizedPhotos
+ private Album root;
+
+ static final long serialVersionUID = 4069997717483260853L;
+
+ enum ImageType {
+ thumbnail,
+ photo,
+ resource
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest
+ * , javax.servlet.http.HttpServletResponse)
+ */
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ doPost(request, response);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest
+ * , javax.servlet.http.HttpServletResponse)
+ */
+ protected void doPost(HttpServletRequest aRequest, HttpServletResponse aResponse)
+ throws ServletException, IOException {
+
+ String entryPath = aRequest.getPathInfo();
+ if (entryPath == null) {
+ entryPath = "/";
+ }
+
+ ImageType type = null;
+ for (ImageType t : ImageType.values()) {
+ if (entryPath.startsWith("/" + t + "/")) {
+ entryPath = entryPath.substring(t.toString().length() + 1);
+ type = t;
+ break;
+ }
+ }
+
+ if (type == null) {
+ throw new RuntimeException("unsupported URL " + aRequest.getPathInfo());
+ }
+
+ switch (type) {
+ case thumbnail:
+ case photo: {
+ if (entryPath.endsWith(".jpg")) {
+ entryPath = entryPath.substring(0, entryPath.length() - ".jpg".length());
+ }
+ PhotoEntry entry = root.getEntry(entryPath);
+
+ Photo photo = (Photo) entry;
+ InputStream is = null;
+ if (type == ImageType.thumbnail) {
+ is = photo.getThumbNail();
+ } else {
+ is = photo.getPhoto();
+ }
+ sendImage(aResponse, is);
+ break;
+ }
+ case resource: {
+ try (InputStream is = getServletContext().getResourceAsStream("/images/" + entryPath)) {
+ ServletOutputStream os = aResponse.getOutputStream();
+ byte[] buffer = new byte[4096];
+ int n;
+ while ((n = is.read(buffer)) > 0) {
+ os.write(buffer, 0, n);
+ }
+ }
+ break;
+ }
+
+ default: {
+ //throw new RuntimeException("Unknown type " + type);
+ }
+ }
+ }
+
+ /**
+ * Sends the image.
+ *
+ * @param response Response
+ * @param is Input stream of the image.
+ * @throws IOException In case an IO problem occurs.
+ */
+
+ private void sendImage(HttpServletResponse response, InputStream is) throws IOException {
+ int c;
+ while ((c = is.read()) >= 0) {
+ response.getOutputStream().write(c);
+ }
+ }
+}
</tr>
</table>
</div>
+ <div id="upload">
+ <span wicket:id="uploadPanel"/>
+ </div>
</wicket:panel>
</body>
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.Serializable;
import java.util.logging.Logger;
import javax.inject.Inject;
+import javax.servlet.ServletContext;
import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
-import org.apache.wicket.resource.ByteArrayResource;
+import org.wamblee.general.ValueHolder;
import org.wamblee.photos.model.Album;
import org.wamblee.photos.model.Photo;
import org.wamblee.photos.model.PhotoEntry;
*/
public class AlbumPanel extends Panel {
+ public static class MyValueHolder<T extends Serializable> extends ValueHolder<T> implements Serializable {
+ public MyValueHolder(T aValue) {
+ super(aValue);
+ }
+
+ public MyValueHolder() {
+ super();
+ }
+ }
+
private static final Logger LOGGER = Logger.getLogger(AlbumPanel.class.getName());
private static final long serialVersionUID = 1L;
@AuthorizedPhotos
private transient Album authorized;
+ @Inject
+ private ServletContext context;
+
private class SerializableEntryLink extends Link {
private String path;
@Override
public void onClick() {
- System.out.println("Entry " + path + " was clicked");
PageParameters pars = new PageParameters();
pars.put("path", path);
index = 0;
}
- PhotoEntry current = authorized.getEntry(path);
- if (current instanceof Photo) {
- throw new RuntimeException("AlbumPanel can only show album: " + current.getClass().getName());
- }
- final Album album = (Album) current;
-
Link prevLink = new Link("prevLink") {
- {
- if (index - MAX_ROWS * MAX_COLUMNS < 0) {
- setEnabled(false);
- }
- }
-
@Override
public void onClick() {
PageParameters pars = new PageParameters();
pars.put("index", index - MAX_ROWS * MAX_COLUMNS);
setResponsePage(HomePage.class, pars);
}
+
+ @Override
+ public boolean isEnabled() {
+ return index - MAX_ROWS * MAX_COLUMNS >= 0;
+ }
};
add(prevLink);
// Avoid implicit references to the album to keep the link objects
// small and serializable.
- final int albumSize = album.size();
+ final int albumSize = getAlbum().size();
Link nextLink = new Link("nextLink") {
- {
- if (index + MAX_ROWS * MAX_COLUMNS >= albumSize) {
- setEnabled(false);
- }
- }
-
@Override
public void onClick() {
PageParameters pars = new PageParameters();
pars.put("index", index + MAX_ROWS * MAX_COLUMNS);
setResponsePage(HomePage.class, pars);
}
+
+ @Override
+ public boolean isEnabled() {
+ return index + MAX_ROWS * MAX_COLUMNS < albumSize;
+ }
};
add(nextLink);
RepeatingView pageLinks = new RepeatingView("pageLinks");
add(pageLinks);
+ Album album = getAlbum();
for (int i = 0; i < album.size() / MAX_ROWS / MAX_COLUMNS; i++) {
final int istart = i * MAX_ROWS * MAX_COLUMNS;
Link pageLink = new Link("pageLink") {
pageLinks.add(container);
}
- int ientry = index;
- int irow = 0;
- RepeatingView row = new RepeatingView("row");
- add(row);
- while (irow < MAX_ROWS && ientry < album.size()) {
- int icolumn = 0;
- WebMarkupContainer columns = new WebMarkupContainer(row.newChildId());
- row.add(columns);
- RepeatingView column = new RepeatingView("column");
- columns.add(column);
- while (icolumn < MAX_COLUMNS && ientry < album.size()) {
- WebMarkupContainer thumbnail = new WebMarkupContainer(column.newChildId());
- column.add(thumbnail);
-
- final PhotoEntry entry = album.getEntry(ientry);
- Link link = new SerializableEntryLink("thumbnail", entry.getPath());
- thumbnail.add(link);
- ImageData data = getData(entry);
-
- // TODO very inefficient. all data is loaded when generating the page.
- link.add(new Image("image", new ByteArrayResource(data.getContentType(), data.getData())));
-
- link.add(new Label("name", album.getEntry(ientry).getId()));
- icolumn++;
- ientry++;
+ RepeatingView row = new RepeatingView("row") {
+ @Override
+ protected void onPopulate() {
+ removeAll();
+ final ValueHolder<Integer> ientry = new MyValueHolder<Integer>(index);
+ int irow = 0;
+ Album album = getAlbum();
+ while (irow < MAX_ROWS && ientry.getValue() < album.size()) {
+ WebMarkupContainer columns = new WebMarkupContainer(newChildId());
+ add(columns);
+ RepeatingView column = new RepeatingView("column") {
+ @Override
+ protected void onPopulate() {
+ removeAll();
+ int icolumn = 0;
+ Album album = getAlbum();
+ while (icolumn < MAX_COLUMNS && ientry.getValue() < album.size()) {
+ WebMarkupContainer thumbnail = new WebMarkupContainer(newChildId());
+ add(thumbnail);
+
+ final PhotoEntry entry = album.getEntry(ientry.getValue());
+ Link link = new SerializableEntryLink("thumbnail", entry.getPath());
+ thumbnail.add(link);
+ //ImageData data = getData(entry);
+
+ // TODO very inefficient. all data is loaded when generating the page.
+ //link.add(new Image("image",
+ // new ByteArrayResource(data.getContentType(), data.getData())));
+
+ //link.add(new Image("image",
+ // new ContextRelativeResource("image/thumbnail" + entry.getPath())));
+
+ //final String url = "/image/thumbnail/" + entry.getPath();
+
+ if (entry instanceof Photo) {
+ link.add(new Image("image") {
+ @Override
+ protected void onComponentTag(ComponentTag tag) {
+ tag.put("src",
+ context.getContextPath() + "/image/thumbnail/" + entry.getPath());
+ }
+ });
+ } else {
+ link.add(new Image("image") {
+ @Override
+ protected void onComponentTag(ComponentTag tag) {
+ //tag.put("src", context.getContextPath() + "/resources/folder.png" +
+ // entry.getPath());
+ tag.put("src", context.getContextPath() + "/image/resource/folder.png");
+ }
+ });
+ }
+
+ link.add(new Label("name", album.getEntry(ientry.getValue()).getId()));
+ icolumn++;
+ ientry.setValue(ientry.getValue() + 1);
+ }
+ }
+ };
+ columns.add(column);
+ irow++;
+ }
}
- irow++;
+ };
+
+ add(row);
+
+ // upload panel
+ if (path.equals("/"))
+
+ {
+ add(new WebMarkupContainer("uploadPanel"));
+ } else
+
+ {
+ add(new UploadPanel("uploadPanel", path));
+ }
+ }
+
+ private Album getAlbum() {
+ PhotoEntry current = authorized.getEntry(path);
+ if (current instanceof Photo) {
+ throw new RuntimeException("AlbumPanel can only show album: " + current.getClass().getName());
}
+ return (Album) current;
}
public static final class ImageData {
@Override
public void onClick() {
- System.out.println("Entry " + path + " was clicked");
PageParameters pars = new PageParameters();
pars.put("path", path);
setResponsePage(HomePage.class, pars);
}
add(new Label("path", path));
- PhotoEntry current = authorized.getEntry(path);
- if (current instanceof Album) {
- throw new RuntimeException("PhotoPanel can only show a photo: " + current.getClass().getName());
- }
- final Photo photo = (Photo) current;
-
- String parentPath_ = path.substring(0, path.lastIndexOf("/"));
- if (parentPath_.length() == 0) {
- parentPath_ = "/";
- }
- final String parentPath = parentPath_;
- final Album parent = (Album) authorized.getEntry(parentPath);
- final Photo before = parent.findPhotoBefore(photo.getId());
- final Photo after = parent.findPhotoAfter(photo.getId());
+ String parentPath = getParentPath();
Link prevLink = new Link("prevLink") {
- {
- if (before == null) {
- setEnabled(false);
- }
- }
-
@Override
public void onClick() {
+ Photo before = getPrevPhoto();
if (before == null) {
return;
}
pars.put("path", before.getPath());
setResponsePage(HomePage.class, pars);
}
+
+ @Override
+ public boolean isEnabled() {
+ return getPrevPhoto() != null;
+ }
};
add(prevLink);
Link nextLink = new Link("nextLink") {
- {
- if (after == null) {
- setEnabled(false);
- }
- }
-
@Override
public void onClick() {
+ Photo after = getNextPhoto();
if (after == null) {
return;
}
pars.put("path", after.getPath());
setResponsePage(HomePage.class, pars);
}
+
+ @Override
+ public boolean isEnabled() {
+ return getNextPhoto() != null;
+ }
};
add(nextLink);
public void onClick() {
PageParameters pars = new PageParameters();
- pars.put("path", parentPath);
+ pars.put("path", getParentPath());
pars.put("index", 0);
setResponsePage(HomePage.class, pars);
}
add(parentLink);
- Image image = new Image("photo", new ByteArrayResource("image/jpeg", getData(photo)));
+ Image image = new Image("photo", new ByteArrayResource("image/jpeg", getData(getPhoto())));
add(image);
}
+ private Photo getPhoto() {
+ PhotoEntry current = authorized.getEntry(path);
+ if (current instanceof Album) {
+ throw new RuntimeException("PhotoPanel can only show a photo: " + current.getClass().getName());
+ }
+ return (Photo) current;
+ }
+
+ private Photo getPrevPhoto() {
+ return getAlbum().findPhotoBefore(getPhoto().getId());
+ }
+
+ private Photo getNextPhoto() {
+ return getAlbum().findPhotoAfter(getPhoto().getId());
+ }
+
+ private Album getAlbum() {
+ return (Album) getAuthorizedPhotos().getEntry(getParentPath());
+ }
+
+ private String getParentPath() {
+ String parentPath = path.substring(0, path.lastIndexOf("/"));
+ if (parentPath.length() == 0) {
+ parentPath = "/";
+ }
+ return parentPath;
+ }
+
private byte[] getData(Photo aPhoto) {
try (InputStream is = aPhoto.getPhoto()) {
return getBytes(is);
}
return bos.toByteArray();
}
+
+ private Album getAuthorizedPhotos() {
+ return authorized;
+ }
}
\ No newline at end of file
--- /dev/null
+<html
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+ <title>Wicket Quickstart Archetype Homepage</title>
+</head>
+<body>
+
+<wicket:panel>
+ <form wicket:id="uploadForm">
+ <br/>
+ Upload individual jpg photos or a zip of individual jpg photos.
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <input wicket:id="file" type="file" size="40"/>
+ </td>
+ <td>
+ <input type="submit" value="Upload photo(s)"/>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </form>
+</wicket:panel>
+
+</body>
+</html>
--- /dev/null
+/*
+ * Copyright 2005-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.photos.wicket;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import javax.inject.Inject;
+
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.upload.FileUpload;
+import org.apache.wicket.markup.html.form.upload.FileUploadField;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.util.lang.Bytes;
+import org.wamblee.photos.model.Album;
+import org.wamblee.photos.model.plumbing.AuthorizedPhotos;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: erik
+ * Date: 9/23/13
+ * Time: 8:33 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class UploadPanel extends Panel {
+
+ private static final Logger LOGGER = Logger.getLogger(UploadPanel.class.getName());
+
+ /**
+ * Extension to use for JPEGs.
+ */
+ private static final String JPG_EXTENSION = ".jpg";
+
+ /**
+ * Extension to use for ZIP files.
+ */
+ private static final String ZIP_EXTENSION = ".zip";
+
+ @Inject
+ @AuthorizedPhotos
+ private transient Album _authorized;
+
+ private String _path;
+
+ /**
+ * Upload field.
+ */
+ private FileUploadField _uploadField;
+
+ public UploadPanel(String aId, String aPath) {
+ super(aId);
+
+ _path = aPath;
+
+ Form form = new Form("uploadForm") {
+ protected void onSubmit() {
+ final FileUpload upload = _uploadField.getFileUpload();
+
+ if (upload == null) {
+ return;
+ }
+
+ try {
+ String filename = upload.getClientFileName();
+ InputStream is = upload.getInputStream();
+
+ if (filename.trim().length() == 0) {
+ return;
+ }
+ Album album = (Album) _authorized.getEntry(_path);
+ if (filename.toLowerCase().endsWith(JPG_EXTENSION)) {
+ insertPhoto(album, is, filename);
+ } else if (filename.toLowerCase().endsWith(ZIP_EXTENSION)) {
+
+ try (ZipInputStream zip = new ZipInputStream(is)) {
+ insertPhotosFromZipFile(album, zip);
+ }
+ } else {
+ warn("Skipping entry with unknown file type '" + filename + "'");
+ }
+ }
+ catch (Exception e) {
+ LOGGER.log(Level.WARNING, e.getMessage(), e);
+ error("ERROR:" + e.getMessage());
+ }
+ }
+ };
+ add(form);
+ _uploadField = new FileUploadField("file");
+ form.add(_uploadField);
+ form.setMultiPart(true);
+ form.setMaxSize(Bytes.megabytes(500));
+ }
+
+ private void insertPhotosFromZipFile(Album aAlbum, ZipInputStream aZipFile) throws IOException {
+ // zip extension
+ ZipEntry entry;
+ while ((entry = aZipFile.getNextEntry()) != null) {
+ try {
+ if (!entry.isDirectory() && entry.getName().toLowerCase().endsWith(JPG_EXTENSION)) {
+ insertPhoto(aAlbum, aZipFile, new File(entry.getName()).getName());
+ } else {
+ warn("Skipping entry '" + entry.getName() + "' from zip file.");
+ }
+ } finally {
+ aZipFile.closeEntry();
+ }
+ }
+ }
+
+ private void insertPhoto(Album aAlbum, InputStream aPhotoInputStream, String aFilename) throws IOException {
+ String photoName = aFilename.substring(0, aFilename.length() - JPG_EXTENSION.length());
+
+ if (aAlbum.getEntry("/" + photoName) != null) {
+ error("Photo '" + photoName + "' already exists in this album");
+ return;
+ }
+ aAlbum.addImage(photoName, aPhotoInputStream);
+ info("Photo '" + photoName + "' uploaded");
+ }
+}
or "deployment". If no configuration is found, "development" is the default.
-->
+ <!-- The image sender servlet has the sole task of sending
+ images to the client, either a thumbnail or full image -->
+ <servlet>
+ <description>Servlet which sends the raw images.</description>
+ <display-name>ImageSender</display-name>
+ <servlet-name>ImageSender</servlet-name>
+ <servlet-class>org.wamblee.photos.servlet.ImageSender</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>ImageSender</servlet-name>
+ <url-pattern>/image/*</url-pattern>
+ </servlet-mapping>
+
+
<filter>
<filter-name>authentication</filter-name>
<filter-class>org.wamblee.photos.security.AuthenticationFilter</filter-class>
*/
public class AlbumTest {
- private static final String ADDED_METHOD = "photoAdded";
- private static final String REMOVED_METHOD = "photoRemoved";
-
private static final String TEST_RESOURCES = "src/test/resources/albumdata";
private String resourcesPath;
assertTrue(path.startsWith("file:"));
path = path.substring("file:".length());
resourcesPath = path + "../../" + TEST_RESOURCES;
- System.out.println(resourcesPath);
}
private void copyDir(File aSource) {
return new File(_testData.getRoot(), "data");
}
+ protected Album createAlbum(File aDir, String aPath, Cache<String, ArrayList<PhotoEntry>> aCache)
+ throws IOException {
+ return new FileSystemAlbum(aDir, aPath, aCache);
+ }
+
/**
* Verifies that a non-existing album cannot be opened.
*/
public void testNonExistingAlbum() {
File dir = new File(_testData.getRoot(), "NonExisting");
try {
- Album album = new FileSystemAlbum(dir, "", _cache);
+ Album album = createAlbum(dir, "", _cache);
}
catch (IOException e) {
return; // ok
File dir = getTestOutputDir();
copyDir(_dir);
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
int nentries = album.size();
assertEquals(3, nentries);
File dir = getTestOutputDir();
copyDir(_dir);
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
assertEquals(0, album.size());
}
File dir = getTestOutputDir();
copyDir(_dir);
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
assertEquals(0, album.size());
}
File _dir = new File(getTestAlbumData(), "AlbumPhotoMissing");
File dir = getTestOutputDir();
copyDir(_dir);
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
assertEquals(0, album.size());
}
assertTrue(new File(dir, FileSystemAlbum.PHOTOS_DIR).mkdir());
assertTrue(new File(dir, FileSystemAlbum.THUMBNAILS_DIR).mkdir());
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
File image = new File(getTestAlbumData(), "a.jpg");
album.addImage("xyz", getImage(image));
assertTrue(album.getEntry("/xyz") != null);
- Album album2 = new FileSystemAlbum(dir, "/", new ForeverCache<String, ArrayList<PhotoEntry>>());
+ Album album2 = createAlbum(dir, "/", new ForeverCache<String, ArrayList<PhotoEntry>>());
assertTrue(album2.getEntry("/xyz") != null);
}
assertTrue(new File(dir, FileSystemAlbum.PHOTOS_DIR).mkdir());
assertTrue(new File(dir, FileSystemAlbum.THUMBNAILS_DIR).mkdir());
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
File image = new File(getTestAlbumData(), "a.jpg");
album.addImage("xyz", getImage(image));
assertTrue(new File(dir, FileSystemAlbum.PHOTOS_DIR).mkdir());
assertTrue(new File(dir, FileSystemAlbum.THUMBNAILS_DIR).mkdir());
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
File sub = new File(dir, "sub");
album.addAlbum("sub");
assertTrue(new File(sub, FileSystemAlbum.PHOTOS_DIR).isDirectory());
assertTrue(new File(sub, FileSystemAlbum.THUMBNAILS_DIR).isDirectory());
- Album album2 = new FileSystemAlbum(dir, "/", new ForeverCache<String, ArrayList<PhotoEntry>>());
+ Album album2 = createAlbum(dir, "/", new ForeverCache<String, ArrayList<PhotoEntry>>());
PhotoEntry entry = album2.getEntry("/sub");
assertTrue(entry != null);
assertTrue(new File(dir, FileSystemAlbum.PHOTOS_DIR).mkdir());
assertTrue(new File(dir, FileSystemAlbum.THUMBNAILS_DIR).mkdir());
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
File sub = new File(dir, "sub");
album.addAlbum("sub");
File dir = getTestOutputDir();
File origDir = new File(getTestAlbumData(), "AlbumRemove");
copyDir(origDir);
- Album album = new FileSystemAlbum(dir, "/", _cache);
+ Album album = createAlbum(dir, "/", _cache);
try {
album.removeEntry("Nested");
}
--- /dev/null
+/*
+ * Copyright 2005-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.photos.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import javax.servlet.http.HttpSession;
+
+import org.wamblee.cache.Cache;
+import org.wamblee.cache.EhCache;
+import org.wamblee.io.ClassPathResource;
+import org.wamblee.photos.model.authorization.AuthorizedAlbum;
+import org.wamblee.security.authorization.AuthorizationService;
+import org.wamblee.security.authorization.Operation;
+import static org.mockito.Mockito.*;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: erik
+ * Date: 9/23/13
+ * Time: 9:08 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class AuthorizedAlbumTest extends AlbumTest {
+
+ @Override
+ protected Album createAlbum(File aDir, String aPath, Cache<String, ArrayList<PhotoEntry>> aCache)
+ throws IOException {
+ Album fileSystemAlbum = super.createAlbum(aDir, aPath,
+ aCache); //To change body of overridden methods use File | Settings | File Templates.
+ AuthorizationService service = mock(AuthorizationService.class);
+ when(service.isAllowed(anyObject(), any(Operation.class))).thenReturn(true);
+ HttpSession session = mock(HttpSession.class);
+ when(session.getId()).thenReturn("myid");
+ Album authorized = new AuthorizedAlbum(fileSystemAlbum, service, createCache(), session);
+ return authorized;
+ }
+
+ @Override
+ protected Cache createCache() {
+ try {
+ return new EhCache(new ClassPathResource("META-INF/ehcache.xml"), "test");
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+}