Blame | Last modification | View Log | RSS feed
package ak.photoalbum.webapp;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.FileNotFoundException;
import java.net.URLEncoder;
import org.apache.log4j.Logger;
import ak.photoalbum.images.Thumbnailer;
import ak.photoalbum.images.ThumbnailPosition;
import ak.photoalbum.util.FileUtils;
import ak.photoalbum.util.FileNameComparator;
import ak.photoalbum.util.ImagesFilter;
public class Logic
{
protected static final int DEFAULT_COLUMNS = 4;
protected static final String URL_ENCODING = "UTF-8";
protected Logger logger;
protected Thumbnailer thumbnailer;
protected File imagesRoot;
protected int columns = DEFAULT_COLUMNS;
protected ImagesFilter imagesFilter;
protected Comparator fileNameComparator = new FileNameComparator(true);
protected Logic()
{
this.logger = Logger.getLogger(this.getClass());
}
public void init(String imagesRoot, String imagesMask,
String cacheDir, String thumbnailFormat,
Integer smallWidth, Integer smallHeight,
Integer mediumWidth, Integer mediumHeight, Integer columns,
String dirTemplate, String dirThumbnailPositions)
{
this.imagesRoot = new File(imagesRoot);
this.imagesFilter = new ImagesFilter(imagesMask);
if(columns != null) this.columns = columns.intValue();
this.thumbnailer = new Thumbnailer();
this.thumbnailer.setImagesRoot(this.imagesRoot);
this.thumbnailer.setCacheDir(new File(cacheDir));
if(thumbnailFormat != null)
this.thumbnailer.setFormat(thumbnailFormat);
if(smallWidth != null)
this.thumbnailer.setSmallWidth(smallWidth.intValue());
if(smallHeight != null)
this.thumbnailer.setSmallHeight(smallHeight.intValue());
if(mediumWidth != null)
this.thumbnailer.setMediumWidth(mediumWidth.intValue());
if(mediumHeight != null)
this.thumbnailer.setMediumHeight(mediumHeight.intValue());
thumbnailer.setResizer(new ak.photoalbum.images.jiu.JiuResizer());
thumbnailer.setImagesFilter(this.imagesFilter);
thumbnailer.setDirTemplate(new File(dirTemplate));
thumbnailer.setDirThumbnailPositions(
parseThumbnailPositions(dirThumbnailPositions));
try {
thumbnailer.startup();
}
catch(Exception ex) {
logger.error("init thumbnailer", ex);
}
logger.info("started");
}
public void buildCache()
throws IOException
{
thumbnailer.buildCache();
}
public void getEntry(String path, IndexEntry page,
IndexEntry index, IndexEntry prev, IndexEntry current, IndexEntry next)
throws IOException, LogicException
{
File file = new File(imagesRoot, path);
securePath(imagesRoot, file);
if(!file.exists())
throw new FileNotFoundException(
"[" + file.getCanonicalPath() + "] not found");
File dir = file.getParentFile();
File[] children = dir.listFiles(imagesFilter);
int pos;
Arrays.sort(children, fileNameComparator);
pos = Arrays.binarySearch(children, file, fileNameComparator);
if(pos < 0)
throw new FileNotFoundException("[" + file.getCanonicalPath()
+ "] not found in [" + dir.getCanonicalPath() + "]");
setEntryInfo(page, file, false);
setEntryInfo(current, file, true);
setEntryInfo(index, dir, true);
if(pos > 0) setEntryInfo(prev, children[pos-1], true);
if(pos < children.length-1) setEntryInfo(next, children[pos+1], true);
}
protected void setEntryInfo(IndexEntry entry, File file, boolean small)
throws IOException
{
String title = file.getName();
int[] size;
String path = getPath(file);
if(file.isDirectory()) {
size = thumbnailer.getDirSize(file);
}
else {
title = FileUtils.extractFileName(title);
if(small)
size = thumbnailer.getSmallSize(file);
else
size = thumbnailer.getMediumSize(file);
}
entry.setFile(file);
entry.setPath(path == null ? null : URLEncoder.encode(path, URL_ENCODING));
entry.setTitle(title);
entry.setIsDir(file.isDirectory());
entry.setWidth(size[0]);
entry.setHeight(size[1]);
}
public String getThumbnailMime()
{
return thumbnailer.getMime();
}
public String getOriginMime(String path)
throws IOException, LogicException
{
File file = new File(imagesRoot, path);
if(!file.exists()) return null;
securePath(imagesRoot, file);
return FileUtils.getMime(FileUtils.extractFileExt(path));
}
public void writeDir(String path, OutputStream out)
throws IOException, LogicException
{
File file = new File(imagesRoot, path);
securePath(imagesRoot, file);
thumbnailer.writeDir(file, out);
}
public void writeSmall(String path, OutputStream out)
throws IOException, LogicException
{
File file = new File(imagesRoot, path);
securePath(imagesRoot, file);
thumbnailer.writeSmall(file, out);
}
public void writeMedium(String path, OutputStream out)
throws IOException, LogicException
{
File file = new File(imagesRoot, path);
securePath(imagesRoot, file);
thumbnailer.writeMedium(file, out);
}
public void writeOrigin(String path, OutputStream out)
throws IOException, LogicException
{
FileInputStream in = null;
File file = new File(imagesRoot, path);
securePath(imagesRoot, file);
try {
in = new FileInputStream(file);
FileUtils.copyStreams(in, out);
}
finally {
if(in != null) in.close();
}
}
public List listDirectory(String dirName)
throws UnsupportedEncodingException, IOException, LogicException
{
File dir = new File(imagesRoot, dirName);
securePath(imagesRoot, dir);
if(!dir.exists()) return null;
File[] children = dir.listFiles(imagesFilter);
List rows = new ArrayList();
int pos = 0;
Arrays.sort(children, fileNameComparator);
while(pos < children.length) {
List row = new ArrayList();
int rowPos = 0;
rows.add(row);
while(rowPos < columns && pos < children.length) {
String path = getPath(children[pos]);
String title = children[pos].getName();
int[] size;
if(children[pos].isDirectory()) {
size = thumbnailer.getDirSize(children[pos]);
}
else {
size = thumbnailer.getSmallSize(children[pos]);
title = FileUtils.extractFileName(title);
}
row.add(new IndexEntry(children[pos],
URLEncoder.encode(path, URL_ENCODING),
title, children[pos].isDirectory(), size[0], size[1]));
rowPos++;
pos++;
}
while(rowPos < columns) {
row.add(null);
rowPos++;
}
}
return rows;
}
protected String getPath(File file)
throws IOException
{
String path = file.getCanonicalPath();
String rootPath = imagesRoot.getCanonicalPath();
if(path.equals(rootPath)) return "";
if(!rootPath.endsWith(File.separator)) rootPath += File.separator;
if(!path.startsWith(rootPath))
return null;
return path.substring(rootPath.length());
}
protected ThumbnailPosition[] parseThumbnailPositions(String str)
{
List list = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(str, ";");
while(tokenizer.hasMoreTokens()) {
StringTokenizer tokenParser
= new StringTokenizer(tokenizer.nextToken(), ",");
int x = Integer.parseInt(tokenParser.nextToken().trim());
int y = Integer.parseInt(tokenParser.nextToken().trim());
int width = Integer.parseInt(tokenParser.nextToken().trim());
int height = Integer.parseInt(tokenParser.nextToken().trim());
String horAlignStr = tokenParser.nextToken().trim().toLowerCase();
String vertAlignStr = tokenParser.nextToken().trim().toLowerCase();
int horAlign;
int vertAlign;
if("l".equals(horAlignStr))
horAlign = ThumbnailPosition.ALIGN_HOR_LEFT;
else if("r".equals(horAlignStr))
horAlign = ThumbnailPosition.ALIGN_HOR_RIGHT;
else if("c".equals(horAlignStr))
horAlign = ThumbnailPosition.ALIGN_HOR_CENTER;
else
throw new RuntimeException(
"Cannot parse " + horAlignStr + " as horizontal alignment");
if("t".equals(vertAlignStr))
vertAlign = ThumbnailPosition.ALIGN_VERT_TOP;
else if("b".equals(vertAlignStr))
vertAlign = ThumbnailPosition.ALIGN_VERT_BOTTOM;
else if("c".equals(vertAlignStr))
vertAlign = ThumbnailPosition.ALIGN_VERT_CENTER;
else
throw new RuntimeException(
"Cannot parse " + vertAlignStr + " as vertical alignment");
list.add(new ThumbnailPosition(x, y, width, height, horAlign, vertAlign));
}
ThumbnailPosition[] res = new ThumbnailPosition[list.size()];
for(int i = 0; i < res.length; i++)
res[i] = (ThumbnailPosition)list.get(i);
return res;
}
protected static final Logic instance = new Logic();
public static Logic getLogic()
{
return instance;
}
/**
* checks if given file is really under the parent directory
*/
protected void securePath(File parentDir, File file)
throws IOException, LogicException
{
if(parentDir == null || file == null) return;
File partFile = file.getCanonicalFile();
parentDir = parentDir.getCanonicalFile();
while(partFile != null) {
if(partFile.equals(parentDir)) return;
partFile = partFile.getParentFile();
}
throw new LogicSecurityException(
"[" + file.getCanonicalPath() + "] is outside of directory ["
+ parentDir.getCanonicalPath() + "]");
}
}