Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 961 → Rev 962

/PhotoAlbum/trunk/src/ak/photoalbum/webapp/IndexAction.java
0,0 → 1,45
package ak.photoalbum.webapp;
 
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
import ak.photoalbum.util.FileUtils;
 
public final class IndexAction
extends BaseAction
{
private static final Logger logger = Logger.getLogger(IndexAction.class);
 
public ActionForward executeAction(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
PathForm theForm = (PathForm)form;
String dir = theForm.getPath();
IndexEntry entry = new IndexEntry();
IndexEntry top = new IndexEntry();
IndexEntry prev = new IndexEntry();
IndexEntry current = new IndexEntry();
IndexEntry next = new IndexEntry();
List index;
 
if(dir == null) dir = ""; // the images root
 
logger.info("get index for " + dir);
Logic.getLogic().getEntry(dir, entry, top, prev, current, next);
index = Logic.getLogic().listDirectory(dir);
 
request.setAttribute("dir", FileUtils.replaceFileSeparator(dir, " - "));
request.setAttribute("index", index);
request.setAttribute("top", top);
request.setAttribute("prevEntry", prev);
request.setAttribute("current", current);
request.setAttribute("nextEntry", next);
 
return mapping.findForward("success");
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/BaseAction.java
0,0 → 1,51
package ak.photoalbum.webapp;
 
import java.util.List;
import java.io.FileNotFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
import ak.photoalbum.util.FileUtils;
 
public abstract class BaseAction
extends Action
{
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
Logger logger = Logger.getLogger(getClass());
 
try {
return executeAction(mapping, form, request, response);
}
catch(LogicSecurityException ex) {
logger.warn("forbidden: " + ex.getMessage());
logger.debug("forbidden", ex);
response.sendError(HttpServletResponse.SC_FORBIDDEN);
 
return null;
}
catch(FileNotFoundException ex) {
logger.warn("not found: " + ex.getMessage());
logger.debug("not found", ex);
response.sendError(HttpServletResponse.SC_NOT_FOUND);
 
return null;
}
catch(Exception ex) {
logger.error("exception", ex);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 
return null;
}
}
 
public abstract ActionForward executeAction(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception;
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/InitServlet.java
0,0 → 1,50
package ak.photoalbum.webapp;
 
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
 
public class InitServlet
extends HttpServlet
{
public void init()
throws ServletException
{
ServletConfig config = getServletConfig();
 
String imagesRoot;
String imagesMask;
String cacheDir;
String thumbnailFormat;
Integer smallWidth = null;
Integer smallHeight = null;
Integer mediumWidth = null;
Integer mediumHeight = null;
Integer columns = null;
String dirTemplate;
String dirThumbnailPositions;
 
imagesRoot = config.getInitParameter("images root");
imagesMask = config.getInitParameter("images mask");
cacheDir = config.getInitParameter("cache dir");
thumbnailFormat = config.getInitParameter("thumbnail format");
 
if(config.getInitParameter("small width") != null)
smallWidth = new Integer(config.getInitParameter("small width"));
if(config.getInitParameter("small height") != null)
smallHeight = new Integer(config.getInitParameter("small height"));
if(config.getInitParameter("medium width") != null)
mediumWidth = new Integer(config.getInitParameter("medium width"));
if(config.getInitParameter("medium heught") != null)
mediumHeight = new Integer(config.getInitParameter("medium heught"));
if(config.getInitParameter("columns") != null)
columns = new Integer(config.getInitParameter("columns"));
 
dirTemplate = config.getInitParameter("dir template");
dirThumbnailPositions = config.getInitParameter("dir thumbnails positions");
 
Logic.getLogic().init(imagesRoot, imagesMask, cacheDir, thumbnailFormat,
smallWidth, smallHeight, mediumWidth, mediumHeight, columns,
dirTemplate, dirThumbnailPositions);
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/IndexEntry.java
0,0 → 1,94
package ak.photoalbum.webapp;
 
import java.io.File;
 
public class IndexEntry
{
private File file;
private String path;
private String title;
private boolean isDir;
private int width;
private int height;
 
public IndexEntry()
{
}
 
public IndexEntry(File file, String path, String title, boolean isDir,
int width, int height)
{
this.file = file;
this.path = path;
this.title = title;
this.isDir = isDir;
this.width = width;
this.height = height;
}
 
public File getFile()
{
return file;
}
 
public void setFile(File file)
{
this.file = file;
}
 
public String getPath()
{
return path;
}
 
public void setPath(String path)
{
this.path = path;
}
 
public String getTitle()
{
return title;
}
 
public void setTitle(String title)
{
this.title = title;
}
 
public boolean getIsDir()
{
return isDir;
}
 
public void setIsDir(boolean isDir)
{
this.isDir = isDir;
}
 
public int getWidth()
{
return width;
}
 
public void setWidth(int width)
{
this.width = width;
}
 
public int getHeight()
{
return height;
}
 
public void setHeight(int height)
{
this.height = height;
}
 
public String toString()
{
return super.toString() + ": " + file + " - " + path + " - " + title
+ " " + width + "x" + height;
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/PageAction.java
0,0 → 1,41
package ak.photoalbum.webapp;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
 
public final class PageAction
extends BaseAction
{
private static final Logger logger = Logger.getLogger(IndexAction.class);
 
public ActionForward executeAction(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
PathForm theForm = (PathForm)form;
String page = theForm.getPath();
IndexEntry entry = new IndexEntry();
IndexEntry index = new IndexEntry();
IndexEntry prev = new IndexEntry();
IndexEntry current = new IndexEntry();
IndexEntry next = new IndexEntry();
 
if(page == null) page = ""; // the images root
 
logger.info("get page " + page);
Logic.getLogic().getEntry(page, entry, index, prev, current, next);
 
request.setAttribute("page", page);
request.setAttribute("entry", entry);
request.setAttribute("index", index);
request.setAttribute("prevEntry", prev);
request.setAttribute("current", current);
request.setAttribute("nextEntry", next);
 
return mapping.findForward("success");
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/LogicException.java
0,0 → 1,10
package ak.photoalbum.webapp;
 
public class LogicException
extends Exception
{
public LogicException(String message)
{
super(message);
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/Logic.java
0,0 → 1,342
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() + "]");
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/ImageAction.java
0,0 → 1,45
package ak.photoalbum.webapp;
 
import java.io.FileNotFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
 
public final class ImageAction
extends BaseAction
{
private static final Logger logger = Logger.getLogger(ImageAction.class);
 
public ActionForward executeAction(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
PathForm theForm = (PathForm)form;
String path = theForm.getPath();
Logic logic = Logic.getLogic();
 
logger.info("get image " + mapping.getParameter() + " for " + path);
 
if("dir".equals(mapping.getParameter())) {
response.setContentType(logic.getThumbnailMime());
logic.writeDir(path, response.getOutputStream());
}
else if("small".equals(mapping.getParameter())) {
response.setContentType(logic.getThumbnailMime());
logic.writeSmall(path, response.getOutputStream());
}
else if("medium".equals(mapping.getParameter())) {
response.setContentType(logic.getThumbnailMime());
logic.writeMedium(path, response.getOutputStream());
}
else if("origin".equals(mapping.getParameter())) {
response.setContentType(logic.getOriginMime(path));
logic.writeOrigin(path, response.getOutputStream());
}
 
return null;
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/PathForm.java
0,0 → 1,31
package ak.photoalbum.webapp;
 
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
 
public class PathForm
extends ActionForm
{
protected String path;
 
public String getPath()
{
return path;
}
 
public void setPath(String path)
{
this.path = path;
}
 
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request)
{
ActionErrors errors = new ActionErrors();
 
return errors;
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/BuildCacheAction.java
0,0 → 1,25
package ak.photoalbum.webapp;
 
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
 
public final class BuildCacheAction
extends Action
{
private static final Logger logger = Logger.getLogger(IndexAction.class);
 
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
Logic.getLogic().buildCache();
 
return mapping.findForward("success");
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/webapp/LogicSecurityException.java
0,0 → 1,10
package ak.photoalbum.webapp;
 
public class LogicSecurityException
extends LogicException
{
public LogicSecurityException(String message)
{
super(message);
}
}