First version of view of album.
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.wamblee.photos</groupId>
- <artifactId>wamblee-photos</artifactId>
- <packaging>war</packaging>
- <version>0.1-SNAPSHOT</version>
- <name>photos</name>
- <description>
- Photos application.
- </description>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.wamblee.photos</groupId>
+ <artifactId>wamblee-photos</artifactId>
+ <packaging>war</packaging>
+ <version>0.1-SNAPSHOT</version>
+ <name>photos</name>
+ <description>
+ Photos application.
+ </description>
- <properties>
- <wicket.version>1.4.9</wicket.version>
- <jetty.version>6.1.4</jetty.version>
- <utils.version>0.6</utils.version>
- </properties>
+ <properties>
+ <wicket.version>1.4.9</wicket.version>
+ <jetty.version>6.1.4</jetty.version>
+ <utils.version>0.6</utils.version>
+ </properties>
- <!--
- TODO <organization> <name>company name</name> <url>company url</url>
- </organization>
- -->
- <url>http://wamblee.org</url>
- <licenses>
- <license>
- <name>The Apache Software License, Version 2.0</name>
- <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
- <distribution>repo</distribution>
- </license>
- </licenses>
- <scm>
- <url>http://wamblee.org/gitweb/photos</url>
- <connection>scm:git:https://wamblee.org/git/public/photos</connection>
- <developerConnection>scm:git:https://wamblee.org/git/public/photos</developerConnection>
- </scm>
- <developers>
- <developer>
- <email>erik@wamblee.org</email>
- <name>Erik Brakkee</name>
- <url>http://brakkee.org</url>
- </developer>
- </developers>
+ <!--
+ TODO <organization> <name>company name</name> <url>company url</url>
+ </organization>
+ -->
+ <url>http://wamblee.org</url>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <url>http://wamblee.org/gitweb/photos</url>
+ <connection>scm:git:https://wamblee.org/git/public/photos</connection>
+ <developerConnection>scm:git:https://wamblee.org/git/public/photos</developerConnection>
+ </scm>
+ <developers>
+ <developer>
+ <email>erik@wamblee.org</email>
+ <name>Erik Brakkee</name>
+ <url>http://brakkee.org</url>
+ </developer>
+ </developers>
- <dependencies>
+ <dependencies>
- <dependency>
- <groupId>javax.portlet</groupId>
- <artifactId>portlet-api</artifactId>
- <version>2.0</version>
- </dependency>
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <version>2.0</version>
+ </dependency>
- <dependency>
- <groupId>dom4j</groupId>
- <artifactId>dom4j</artifactId>
- <version>1.6</version>
- <exclusions>
- <exclusion>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>jaxen</groupId>
- <artifactId>jaxen</artifactId>
- <version>1.1-beta-9</version>
- <exclusions>
- <exclusion>
- <groupId>xom</groupId>
- <artifactId>xom</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xerces</groupId>
- <artifactId>xmlParserAPIs</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6</version>
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>jaxen</groupId>
+ <artifactId>jaxen</artifactId>
+ <version>1.1-beta-9</version>
+ <exclusions>
+ <exclusion>
+ <groupId>xom</groupId>
+ <artifactId>xom</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xmlParserAPIs</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-wicket-joe</artifactId>
+ <version>${utils.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-wicket-components</artifactId>
+ <version>${utils.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-support-cdi</artifactId>
+ <version>${utils.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-support-cdi</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ <version>${utils.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-security-usermgt</artifactId>
+ <version>${utils.version}</version>
+ </dependency>
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-wicket-joe</artifactId>
- <version>${utils.version}</version>
- </dependency>
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-wicket-components</artifactId>
- <version>${utils.version}</version>
- </dependency>
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-support-cdi</artifactId>
- <version>${utils.version}</version>
- </dependency>
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-support-cdi</artifactId>
- <type>test-jar</type>
- <scope>test</scope>
- <version>${utils.version}</version>
- </dependency>
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-security-usermgt</artifactId>
- <version>${utils.version}</version>
- </dependency>
+ <!-- WICKET DEPENDENCIES -->
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket</artifactId>
+ <version>${wicket.version}</version>
+ </dependency>
+ <!--
+ OPTIONAL <dependency> <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-extensions</artifactId>
+ <version>${wicket.version}</version> </dependency>
+ -->
- <!-- WICKET DEPENDENCIES -->
- <dependency>
- <groupId>org.apache.wicket</groupId>
- <artifactId>wicket</artifactId>
- <version>${wicket.version}</version>
- </dependency>
- <!--
- OPTIONAL <dependency> <groupId>org.apache.wicket</groupId>
- <artifactId>wicket-extensions</artifactId>
- <version>${wicket.version}</version> </dependency>
- -->
+ <!-- LOGGING DEPENDENCIES - LOG4J -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.4.2</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
- <!-- LOGGING DEPENDENCIES - LOG4J -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>1.4.2</version>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.14</version>
- </dependency>
+ <!-- JUNIT DEPENDENCY FOR TESTING -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.8.5</version>
+ <scope>test</scope>
+ </dependency>
- <!-- JUNIT DEPENDENCY FOR TESTING -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.4</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <version>1.8.5</version>
- <scope>test</scope>
- </dependency>
+ <!-- JETTY DEPENDENCIES FOR TESTING -->
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-management</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
- <!-- JETTY DEPENDENCIES FOR TESTING -->
- <dependency>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>jetty</artifactId>
- <version>${jetty.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- <version>${jetty.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>jetty-management</artifactId>
- <version>${jetty.version}</version>
- <scope>provided</scope>
- </dependency>
+ <!-- JPA testing -->
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-test-enterprise</artifactId>
+ <version>${utils.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.wamblee</groupId>
+ <artifactId>wamblee-test-eclipselink</artifactId>
+ <version>${utils.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>javax.persistence</artifactId>
+ <version>2.0.0</version>
+ <scope>provided</scope>
+ </dependency>
- <!-- JPA testing -->
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-test-enterprise</artifactId>
- <version>${utils.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.wamblee</groupId>
- <artifactId>wamblee-test-eclipselink</artifactId>
- <version>${utils.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.eclipse.persistence</groupId>
- <artifactId>javax.persistence</artifactId>
- <version>2.0.0</version>
- <scope>provided</scope>
- </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>eclipselink</artifactId>
+ <version>2.0.2</version>
+ <scope>test</scope>
+ </dependency>
- <dependency>
- <groupId>org.eclipse.persistence</groupId>
- <artifactId>eclipselink</artifactId>
- <version>2.0.2</version>
- <scope>test</scope>
- </dependency>
+ <dependency>
+ <groupId>javax</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>6.0</version>
+ <scope>provided</scope>
+ </dependency>
- <dependency>
- <groupId>javax</groupId>
- <artifactId>javaee-api</artifactId>
- <version>6.0</version>
- <scope>provided</scope>
- </dependency>
+ </dependencies>
+ <build>
+ <resources>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ <testResources>
+ <testResource>
+ <filtering>false</filtering>
+ <directory>src/test/java</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </testResource>
+ </testResources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.0</version>
+ <configuration></configuration>
+ </plugin>
- </dependencies>
- <build>
- <resources>
- <resource>
- <filtering>false</filtering>
- <directory>src/main/resources</directory>
- </resource>
- <resource>
- <filtering>false</filtering>
- <directory>src/main/java</directory>
- <includes>
- <include>**</include>
- </includes>
- <excludes>
- <exclude>**/*.java</exclude>
- </excludes>
- </resource>
- </resources>
- <testResources>
- <testResource>
- <filtering>false</filtering>
- <directory>src/test/java</directory>
- <includes>
- <include>**</include>
- </includes>
- <excludes>
- <exclude>**/*.java</exclude>
- </excludes>
- </testResource>
- </testResources>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <version>2.0</version>
- <configuration> </configuration>
- </plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>package</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>java
+ <source>1.7</source>
+ <target>1.7</target>
+ <optimize>true</optimize>
+ <debug>true</debug>
+ <compilerArgument>-XDignore.symbol.file</compilerArgument>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ </plugin>
- <plugin>
- <inherited>true</inherited>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration> java
- <source>1.6</source>
- <target>1.6</target>
- <optimize>true</optimize>
- <debug>true</debug>
- <compilerArgument>-XDignore.symbol.file</compilerArgument>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>maven-jetty-plugin</artifactId>
- </plugin>
+ </plugins>
+ </build>
- </plugins>
- </build>
+ <repositories>
+ <repository>
+ <id>EclipseLink Repo</id>
+ <url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
+ </repository>
+ </repositories>
- <repositories>
- <repository>
- <id>EclipseLink Repo</id>
- <url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
- </repository>
- </repositories>
-
- <profiles>
- <profile>
- <id>release</id>
- <activation>
- <property>
- <name>performRelease</name>
- <value>true</value>
- </property>
- </activation>
+ <profiles>
+ <profile>
+ <id>release</id>
+ <activation>
+ <property>
+ <name>performRelease</name>
+ <value>true</value>
+ </property>
+ </activation>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-release-plugin</artifactId>
- <version>2.0</version>
- <configuration>
- <autoVersionSubmodules>true</autoVersionSubmodules>
- <goals>javadoc:jar deploy</goals>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-gpg-plugin</artifactId>
- <executions>
- <execution>
- <id>sign-artifacts</id>
- <phase>verify</phase>
- <goals>
- <goal>sign</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.0</version>
+ <configuration>
+ <autoVersionSubmodules>true</autoVersionSubmodules>
+ <goals>javadoc:jar deploy</goals>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
<profile>
<id>ide</id>
<build>
<directory>target-ide</directory>
</build>
</profile>
- </profiles>
+ </profiles>
- <distributionManagement>
- <repository>
- <id>sonatype-nexus-staging</id>
- <name>Nexus Release Repository</name>
- <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
- </repository>
- </distributionManagement>
+ <distributionManagement>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <name>Nexus Release Repository</name>
+ <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+ </repository>
+ </distributionManagement>
</project>
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
private String _path;
private class CreateEntryCallback implements EntryFoundCallback {
- public boolean photoFound(List<PhotoEntry> aEntries, File aThumbnail,
- File aPhoto, String aPath) {
+ public boolean photoFound(List<PhotoEntry> aEntries, File aThumbnail, File aPhoto, String aPath) {
PhotoEntry entry = new FileSystemPhoto(aThumbnail, aPhoto, aPath);
aEntries.add(entry);
return true;
}
- public boolean albumFound(List<PhotoEntry> aEntries, File aAlbum,
- String aPath) throws IOException {
- PhotoEntry entry = new FileSystemAlbum(aAlbum, aPath,
- _entries.getCache());
+ public boolean albumFound(List<PhotoEntry> aEntries, File aAlbum, String aPath) throws IOException {
+ PhotoEntry entry = new FileSystemAlbum(aAlbum, aPath, _entries.getCache());
aEntries.add(entry);
return true;
}
}
+ private static final class AlbumComputation
+ implements CachedObject.Computation<String, ArrayList<PhotoEntry>>, Serializable {
+ private FileSystemAlbum album;
+
+ public AlbumComputation(FileSystemAlbum aAlbum) {
+ album = aAlbum;
+ }
+
+ @Override
+ public ArrayList<PhotoEntry> getObject(String aObjectKey) throws Exception {
+ return album.compute();
+ }
+ }
+
/**
* Creates the album.
- *
- * @param aDir
- * Directory where the album is located.
- * @param aPath
- * Path that this album represents.
- * @param aCache
- * Cache to use.
+ *
+ * @param aDir Directory where the album is located.
+ * @param aPath Path that this album represents.
+ * @param aCache Cache to use.
* @throws IOException
*/
- public FileSystemAlbum(File aDir, String aPath,
- Cache<String, ArrayList<PhotoEntry>> aCache) throws IOException {
+ public FileSystemAlbum(File aDir, String aPath, Cache<String, ArrayList<PhotoEntry>> aCache) throws IOException {
if (!aDir.isDirectory()) {
throw new IOException("Directory '" + aDir.getPath() +
- "' does not exist.");
+ "' does not exist.");
}
_dir = aDir;
_path = aPath;
- _entries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache,
- aPath,
- new CachedObject.Computation<String, ArrayList<PhotoEntry>>() {
- public ArrayList<PhotoEntry> getObject(String aObjectKey) {
- return FileSystemAlbum.this.compute();
- }
- });
-
+ _entries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache, aPath, new AlbumComputation(this));
}
/**
* Computes the photo entries for this album based on the file system.
- *
+ *
* @return List of photo entries.
*/
private ArrayList<PhotoEntry> compute() {
try {
LOG.info("Initializing album for directory " + _dir);
traverse(getPath(), result, _dir, new CreateEntryCallback());
- } catch (IOException e) {
+ }
+ catch (IOException e) {
LOG.fatal("IOException occurred: " + e.getMessage(), e);
}
return result;
/**
* Initializes the album.
- *
- * @param aPath
- * Path of the album
- * @param aEntries
- * Photo entries for the album.
- * @param aDir
- * Directory where the album is stored.
+ *
+ * @param aPath Path of the album
+ * @param aEntries Photo entries for the album.
+ * @param aDir Directory where the album is stored.
* @throws IOException
*/
- static boolean traverse(String aPath, List<PhotoEntry> aEntries, File aDir,
- EntryFoundCallback aCallback) throws IOException {
+ static boolean traverse(String aPath, List<PhotoEntry> aEntries, File aDir, EntryFoundCallback aCallback)
+ throws IOException {
File[] files = listFilesInDir(aDir);
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
if (file.getName().equals(THUMBNAILS_DIR)) {
- if (!traverseThumbnails(aPath, aEntries, aDir, aCallback,
- file)) {
+ if (!traverseThumbnails(aPath, aEntries, aDir, aCallback, file)) {
return false;
}
} else if (file.getName().equals(PHOTOS_DIR)) {
/**
* Traverse the thumnails directory.
- *
- * @param aPath
- * Path of the photo album.
- * @param aEntries
- * Entries of the album.
- * @param aDir
- * Directory of the album.
- * @param aCallback
- * Callback to call when a thumbnail has been found.
- * @param aFile
- * Directory of the photo album.
- */
- private static boolean traverseThumbnails(String aPath,
- List<PhotoEntry> aEntries, File aDir, EntryFoundCallback aCallback,
- File aFile) {
+ *
+ * @param aPath Path of the photo album.
+ * @param aEntries Entries of the album.
+ * @param aDir Directory of the album.
+ * @param aCallback Callback to call when a thumbnail has been found.
+ * @param aFile Directory of the photo album.
+ */
+ private static boolean traverseThumbnails(String aPath, List<PhotoEntry> aEntries, File aDir,
+ EntryFoundCallback aCallback, File aFile) {
// Go inside the thumbnails directory to scan
// for available photos.
}
} else {
LOG.info("Thumbnails director " + aFile.getPath() +
- " exists but corresponding photo directory " +
- photosDir.getPath() + " not found");
+ " exists but corresponding photo directory " +
+ photosDir.getPath() + " not found");
}
return true;
}
/**
* Builds up the photo album for a given thumbnails and photo directory.
- *
- * @param aPath
- * Path of the album.
- * @param aEntries
- * Photo entries of the album.
- * @param aThumbnailsDir
- * Directory containing thumbnail pictures.
- * @param aPhotosDir
- * Directory containing full size photos.
- */
- private static boolean buildAlbum(String aPath, List<PhotoEntry> aEntries,
- File aThumbnailsDir, File aPhotosDir, EntryFoundCallback aCallback) {
+ *
+ * @param aPath Path of the album.
+ * @param aEntries Photo entries of the album.
+ * @param aThumbnailsDir Directory containing thumbnail pictures.
+ * @param aPhotosDir Directory containing full size photos.
+ */
+ private static boolean buildAlbum(String aPath, List<PhotoEntry> aEntries, File aThumbnailsDir, File aPhotosDir,
+ EntryFoundCallback aCallback) {
File[] thumbnails = listFilesInDir(aThumbnailsDir);
for (int i = 0; i < thumbnails.length; i++) {
File thumbnail = thumbnails[i];
if (!isThumbNail(thumbnail)) {
LOG.info("Skipping " + thumbnail.getPath() +
- " because it is not a thumbnail file.");
+ " because it is not a thumbnail file.");
continue;
}
File photo = new File(aPhotosDir, photoName(thumbnail.getName()));
if (!photo.isFile()) {
LOG.info("Photo file " + photo.getPath() + " for thumbnail " +
- thumbnail.getPath() + " does not exist.");
+ thumbnail.getPath() + " does not exist.");
continue;
}
String photoPath = photo.getName();
- photoPath = photoPath.substring(0, photoPath.length() -
- JPG_EXTENSION.length());
+ photoPath = photoPath.substring(0, photoPath.length() - JPG_EXTENSION.length());
photoPath = aPath + "/" + photoPath;
photoPath = photoPath.replaceAll("//", "/");
if (!aCallback.photoFound(aEntries, thumbnail, photo, photoPath)) {
/**
* Checks if the file represents a thumbnail.
- *
- * @param aFile
- * File to check.
+ *
+ * @param aFile File to check.
* @return True iff the file is a thumbnail.
*/
private static boolean isThumbNail(File aFile) {
/**
* Constructs the photo name based on the thumbnail name.
- *
- * @param aThumbnailName
- * Thumbnail name.
+ *
+ * @param aThumbnailName Thumbnail name.
* @return Photo name.
*/
private static String photoName(String aThumbnailName) {
- return aThumbnailName.substring(0, aThumbnailName.length() -
- THUMBNAIL_ENDING.length()) +
- JPG_EXTENSION;
+ return aThumbnailName.substring(0, aThumbnailName.length() - THUMBNAIL_ENDING.length()) + JPG_EXTENSION;
}
/*
*/
public PhotoEntry getEntry(String aPath) {
if (!aPath.startsWith("/")) {
- throw new IllegalArgumentException(
- "Path must start with / character");
+ throw new IllegalArgumentException("Path must start with / character");
}
if (aPath.equals("/")) {
return this;
/**
* Gets the entry at a given path.
- *
- * @param aPath
- * Array of components of the path.
- * @param aLevel
- * Current level in the path.
+ *
+ * @param aPath Array of components of the path.
+ * @param aLevel Current level in the path.
* @return Entry.
*/
private PhotoEntry getEntry(String[] aPath, int aLevel) {
/**
* Finds an entry in the album with the given id.
- *
- * @param aId
- * Photo entry id.
+ *
+ * @param aId Photo entry id.
* @return Photo entry.
*/
private PhotoEntry find(String aId) {
/**
* Finds a photo entry in the map.
- *
- * @param aId
- * Id of the photo entry.
+ *
+ * @param aId Id of the photo entry.
* @return Pair of a photo entry and the index of the item.
*/
private Pair<PhotoEntry, Integer> findInMap(String aId) {
/**
* Prints the album with a given indentation.
- *
- * @param aIndent
- * Indentation string.
+ *
+ * @param aIndent Indentation string.
* @return String representation of the album.
*/
private String print(String aIndent) {
* @see org.wamblee.photos.database.Album#addImage(java.lang.String,
* java.awt.Image)
*/
- public void addImage(String aId, InputStream aImageStream)
- throws IOException {
+ public void addImage(String aId, InputStream aImageStream) throws IOException {
File photoDir = getPhotoDir();
File thumbnailDir = getThumbnailDir();
BufferedImage image;
try {
image = JpegUtils.loadJpegImage(aImageStream);
- } catch (InterruptedException e) {
- throw new IOException("Loading image interruptedS: " +
- e.getMessage());
}
- BufferedImage thumbnailImage = JpegUtils.scaleImage(THUMBNAIL_WIDTH,
- THUMBNAIL_HEIGHT, image);
+ catch (InterruptedException e) {
+ throw new IOException("Loading image interruptedS: " + e.getMessage());
+ }
+ BufferedImage thumbnailImage = JpegUtils.scaleImage(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, image);
File thumbnail = new File(thumbnailDir, aId + THUMBNAIL_ENDING);
File photo = new File(photoDir, aId + JPG_EXTENSION);
writeImage(photo, image);
writeImage(thumbnail, thumbnailImage);
- Photo photoEntry = new FileSystemPhoto(thumbnail, photo, (getPath()
- .equals("/") ? "" : getPath()) + "/" + aId);
+ Photo photoEntry = new FileSystemPhoto(thumbnail, photo, (getPath().equals("/") ? "" : getPath()) + "/" + aId);
addEntry(photoEntry);
}
/**
* Checks if a given entry can be added to the album.
- *
- * @param aId
- * Id of the new entry.
- * @param aPhotoDir
- * Photo directory.
- * @param aThumbnailDir
- * Thumbnail directory.
+ *
+ * @param aId Id of the new entry.
+ * @param aPhotoDir Photo directory.
+ * @param aThumbnailDir Thumbnail directory.
* @throws IOException
*/
- private void checkPhotoDirs(String aId, File aPhotoDir, File aThumbnailDir)
- throws IOException {
+ private void checkPhotoDirs(String aId, File aPhotoDir, File aThumbnailDir) throws IOException {
// Create directories if they do not already exist.
aPhotoDir.mkdir();
aThumbnailDir.mkdir();
if (!aPhotoDir.isDirectory() || !aThumbnailDir.isDirectory()) {
throw new IOException("Album " + getId() +
- " does not accept new images.");
+ " does not accept new images.");
}
if (getEntry("/" + aId) != null) {
throw new IOException("An entry with the name '" + aId +
- "' already exists in the album " + getPath());
+ "' already exists in the album " + getPath());
}
}
/**
* Gets the thumbnail directory for the album.
- *
+ *
* @return Directory.
*/
private File getThumbnailDir() {
/**
* Gets the photo directory for the album.
- *
+ *
* @return Photo directory
*/
private File getPhotoDir() {
/**
* Writes an image to a file.
- *
- * @param aFile
- * File to write to.
- * @param aImage
- * Image.
+ *
+ * @param aFile File to write to.
+ * @param aImage Image.
* @throws IOException
*/
- private static void writeImage(File aFile, BufferedImage aImage)
- throws IOException {
- OutputStream output = new BufferedOutputStream(new FileOutputStream(
- aFile));
+ private static void writeImage(File aFile, BufferedImage aImage) throws IOException {
+ OutputStream output = new BufferedOutputStream(new FileOutputStream(aFile));
JpegUtils.writeJpegImage(output, JPG_QUALITY, aImage);
output.close();
}
PhotoEntry entry = find(aId);
if (entry != null) {
throw new IOException("Entry already exists in album " + getId() +
- " : " + aId);
+ " : " + aId);
}
// Entry not yet found. Try to create it.
File albumDir = new File(_dir, aId);
}
File photosDir = new File(albumDir, PHOTOS_DIR);
if (!photosDir.mkdir()) {
- throw new IOException("Could not create photo storage dir: " +
- photosDir.getPath());
+ throw new IOException("Could not create photo storage dir: " + photosDir.getPath());
}
File thumbnailsDir = new File(albumDir, THUMBNAILS_DIR);
if (!thumbnailsDir.mkdir()) {
- throw new IOException("Coul dnot create thumbnails storage dir: " +
- thumbnailsDir.getPath());
+ throw new IOException("Coul dnot create thumbnails storage dir: " + thumbnailsDir.getPath());
}
String newPath = _path + "/" + aId;
newPath = newPath.replaceAll("//", "/");
- FileSystemAlbum album = new FileSystemAlbum(albumDir, newPath,
- _entries.getCache());
+ FileSystemAlbum album = new FileSystemAlbum(albumDir, newPath, _entries.getCache());
addEntry(album);
}
/**
* Removes a photo entry.
- *
- * @param aEntry
- * Photo entry to remove.
+ *
+ * @param aEntry Photo entry to remove.
* @throws IOException
*/
private void removePhoto(PhotoEntry aEntry) throws IOException {
throw new IOException("Photo file not found: " + photo.getPath());
}
if (!thumbnail.isFile()) {
- throw new IOException("Thumbnail file not found: " +
- thumbnail.getPath());
+ throw new IOException("Thumbnail file not found: " + thumbnail.getPath());
}
if (!thumbnail.delete()) {
- throw new IOException("Could not delete thumbnail file: " +
- thumbnail.getPath());
+ throw new IOException("Could not delete thumbnail file: " + thumbnail.getPath());
}
_entries.get().remove(aEntry);
if (!photo.delete()) {
- throw new IOException("Could not delete photo file: " +
- photo.getPath());
+ throw new IOException("Could not delete photo file: " + photo.getPath());
}
}
/**
* Removes the album entry from this album.
- *
- * @param aAlbum
- * Album to remove
+ *
+ * @param aAlbum Album to remove
* @throws IOException
*/
private void removeAlbum(FileSystemAlbum aAlbum) throws IOException {
File photosDir = new File(aAlbum._dir, PHOTOS_DIR);
File thumbnailsDir = new File(aAlbum._dir, THUMBNAILS_DIR);
if (!photosDir.delete() || !thumbnailsDir.delete() ||
- !aAlbum._dir.delete()) {
- throw new IOException("Could not delete directories for album:" +
- aAlbum.getId());
+ !aAlbum._dir.delete()) {
+ throw new IOException("Could not delete directories for album:" + aAlbum.getId());
}
_entries.get().remove(aAlbum);
}
/**
* Adds an entry.
- *
- * @param aEntry
- * Entry to add.
+ *
+ * @param aEntry Entry to add.
*/
private void addEntry(PhotoEntry aEntry) {
int i = 0;
/**
* Returns and alphabetically sorted list of files.
- *
+ *
* @param aDir
* @return Sorted list of files.
*/
Pair<PhotoEntry, Integer> entry = findInMap(aId);
if (entry.getFirst() == null) {
throw new IllegalArgumentException("Entry with id '" + aId +
- "' not found in album '" + getPath() + "'");
+ "' not found in album '" + getPath() + "'");
}
int i = entry.getSecond() - 1;
List<PhotoEntry> entries = _entries.get();
while (i >= 0 && i < entries.size() &&
- !(entries.get(i) instanceof Photo)) {
+ !(entries.get(i) instanceof Photo)) {
i--;
}
if (i >= 0) {
Pair<PhotoEntry, Integer> entry = findInMap(aId);
if (entry.getFirst() == null) {
throw new IllegalArgumentException("Entry with id '" + aId +
- "' not found in album '" + getPath() + "'");
+ "' not found in album '" + getPath() + "'");
}
int i = entry.getSecond() + 1;
List<PhotoEntry> entries = _entries.get();
while (i >= 0 && i < entries.size() &&
- !(entries.get(i) instanceof Photo)) {
+ !(entries.get(i) instanceof Photo)) {
i++;
}
if (i < entries.size()) {
<html
- xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<head>
-<title>Wicket Quickstart Archetype Homepage</title>
+ <title>Wicket Quickstart Archetype Homepage</title>
</head>
<body>
<strong>Wicket Quickstart Archetype Homepage</strong>
-<br />
-<br />
+<br/>
+<br/>
<wicket:extend>
-
- <span wicket:id="message">Message here.</span>
+
+ <span wicket:id="message">Message here.</span>
+
+ <div id="album">
+ <table border=1>
+ <tr wicket:id="row">
+
+ <td wicket:id="column">
+
+ <a href="#" wicket:id="thumbnail">
+ <table>
+ <tr>
+ <td><img wicket:id="image" border="0"/></td>
+ </tr>
+ <tr>
+ <td><span wicket:id="name">photo name</span></td>
+ </tr>
+ </table>
+ </a>
+ </td>
+ </tr>
+ </table>
+ </div>
</wicket:extend>
*/
package org.wamblee.photos.wicket;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
-
import javax.inject.Inject;
import org.apache.wicket.PageParameters;
+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.repeater.RepeatingView;
+import org.apache.wicket.resource.ByteArrayResource;
import org.wamblee.photos.model.Album;
+import org.wamblee.photos.model.Photo;
import org.wamblee.photos.model.PhotoEntry;
import org.wamblee.photos.model.plumbing.AllPhotos;
import org.wamblee.photos.model.plumbing.AuthorizedPhotos;
private static final long serialVersionUID = 1L;
@Inject
- private User user;
+ private transient User user;
@Inject
- private UserAdministration userAdmin;
+ private transient UserAdministration userAdmin;
+
+ // TODO the state should be stored as a path.
@Inject
@AllPhotos
- private Album album;
+ private transient Album album;
@Inject
@AuthorizedPhotos
- private Album authorized;
+ private transient Album authorized;
+
+ private class SerializableEntryLink extends Link {
+
+ private String path;
+
+ public SerializableEntryLink(String aId, String aPath) {
+ super(aId);
+ path = aPath;
+ }
+
+ @Override
+ public void onClick() {
+ System.out.println("Entry " + path + " was clicked");
+ }
+ }
/**
* Constructor that is invoked when page is invoked without a session.
PhotoEntry entry = authorized.getEntry(i);
System.out.println("Entry " + i + " " + entry.getId() + " " + entry.getPath());
}
+
+ int ientry = 0;
+ int irow = 0;
+ RepeatingView row = new RepeatingView("row");
+ add(row);
+ while (irow < 5 && ientry < authorized.size()) {
+ int icolumn = 0;
+ WebMarkupContainer columns = new WebMarkupContainer(row.newChildId());
+ row.add(columns);
+ RepeatingView column = new RepeatingView("column");
+ columns.add(column);
+ while (icolumn < 5 && ientry < authorized.size()) {
+ WebMarkupContainer thumbnail = new WebMarkupContainer(column.newChildId());
+ column.add(thumbnail);
+
+ final PhotoEntry entry = authorized.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", authorized.getEntry(ientry).getId()));
+ icolumn++;
+ ientry++;
+ }
+ irow++;
+ }
+ }
+
+ public static final class ImageData {
+ private String contentType;
+ private byte[] data;
+
+ public ImageData(String aContentType, byte[] aData) {
+ contentType = aContentType;
+ data = aData;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+ }
+
+ private ImageData getData(PhotoEntry aEntry) {
+ if (aEntry instanceof Photo) {
+ return getData((Photo) aEntry);
+ } else if (aEntry instanceof Album) {
+ return getData((Album) aEntry);
+ } else {
+ throw new RuntimeException("Unsupported type " + aEntry.getClass().getName());
+ }
+ }
+
+ private ImageData getData(Photo aPhoto) {
+ try (InputStream is = aPhoto.getThumbNail()) {
+ return new ImageData("image/jpeg", getBytes(is));
+ }
+ catch (IOException e) {
+ // to improve.
+ throw new RuntimeException("Cannot read photo", e);
+ }
+ }
+
+ private byte[] getBytes(InputStream is) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] block = new byte[1024];
+ int n = is.read(block);
+ while (n > 0) {
+ bos.write(block, 0, n);
+ n = is.read(block);
+ }
+ return bos.toByteArray();
+ }
+
+ private ImageData getData(Album aAlbum) {
+ try (InputStream is = getClass().getResourceAsStream("folder.png")) {
+ return new ImageData("image/png", getBytes(is));
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Cannot read album jpg", e);
+ }
}
-}
+}
\ No newline at end of file