/sun/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; |
} |
Property changes: |
Added: svn:keywords |
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id |
\ No newline at end of property |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/webapp/PageAction.java |
---|
1,9 → 1,7 |
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; |
10,11 → 8,11 |
import org.apache.log4j.Logger; |
public final class PageAction |
extends Action |
extends BaseAction |
{ |
private static final Logger logger = Logger.getLogger(IndexAction.class); |
public ActionForward execute(ActionMapping mapping, ActionForm form, |
public ActionForward executeAction(ActionMapping mapping, ActionForm form, |
HttpServletRequest request, HttpServletResponse response) |
throws Exception |
{ |
29,26 → 27,15 |
if(page == null) page = ""; // the images root |
logger.info("get page " + page); |
Logic.getLogic().getEntry(page, entry, index, prev, current, next); |
if(Logic.getLogic().getEntry(page, entry, index, prev, current, next)) { |
logger.debug("ok"); |
request.setAttribute("page", page); |
request.setAttribute("entry", entry); |
request.setAttribute("index", index); |
request.setAttribute("prevEntry", prev); |
request.setAttribute("current", current); |
request.setAttribute("nextEntry", 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"); |
} |
else { |
logger.warn("not found [" + page + "]"); |
response.sendError(HttpServletResponse.SC_NOT_FOUND); |
return null; |
} |
return mapping.findForward("success"); |
} |
} |
/sun/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); |
} |
} |
Property changes: |
Added: svn:keywords |
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id |
\ No newline at end of property |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/webapp/Logic.java |
---|
10,6 → 10,7 |
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; |
72,6 → 73,8 |
catch(Exception ex) { |
logger.error("init thumbnailer", ex); |
} |
logger.info("started"); |
} |
public void buildCache() |
80,14 → 83,18 |
thumbnailer.buildCache(); |
} |
public boolean getEntry(String path, IndexEntry page, |
public void getEntry(String path, IndexEntry page, |
IndexEntry index, IndexEntry prev, IndexEntry current, IndexEntry next) |
throws IOException |
throws IOException, LogicException |
{ |
File file = new File(imagesRoot, path); |
if(!file.exists()) return false; |
securePath(imagesRoot, file); |
if(!file.exists()) |
throw new FileNotFoundException( |
"[" + file.getCanonicalPath() + "] not found"); |
File dir = file.getParentFile(); |
File[] children = dir.listFiles(imagesFilter); |
int pos; |
95,7 → 102,9 |
Arrays.sort(children, fileNameComparator); |
pos = Arrays.binarySearch(children, file, fileNameComparator); |
if(pos < 0) return false; |
if(pos < 0) |
throw new FileNotFoundException("[" + file.getCanonicalPath() |
+ "] not found in [" + dir.getCanonicalPath() + "]"); |
setEntryInfo(page, file, false); |
setEntryInfo(current, file, true); |
102,8 → 111,6 |
setEntryInfo(index, dir, true); |
if(pos > 0) setEntryInfo(prev, children[pos-1], true); |
if(pos < children.length-1) setEntryInfo(next, children[pos+1], true); |
return true; |
} |
protected void setEntryInfo(IndexEntry entry, File file, boolean small) |
139,35 → 146,53 |
} |
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 |
throws IOException, LogicException |
{ |
thumbnailer.writeDir(new File(imagesRoot, path), out); |
File file = new File(imagesRoot, path); |
securePath(imagesRoot, file); |
thumbnailer.writeDir(file, out); |
} |
public void writeSmall(String path, OutputStream out) |
throws IOException |
throws IOException, LogicException |
{ |
thumbnailer.writeSmall(new File(imagesRoot, path), out); |
File file = new File(imagesRoot, path); |
securePath(imagesRoot, file); |
thumbnailer.writeSmall(file, out); |
} |
public void writeMedium(String path, OutputStream out) |
throws IOException |
throws IOException, LogicException |
{ |
thumbnailer.writeMedium(new File(imagesRoot, path), out); |
File file = new File(imagesRoot, path); |
securePath(imagesRoot, file); |
thumbnailer.writeMedium(file, out); |
} |
public void writeOrigin(String path, OutputStream out) |
throws IOException |
throws IOException, LogicException |
{ |
FileInputStream in = null; |
FileInputStream in = null; |
File file = new File(imagesRoot, path); |
securePath(imagesRoot, file); |
try { |
in = new FileInputStream(new File(imagesRoot, path)); |
in = new FileInputStream(file); |
FileUtils.copyStreams(in, out); |
} |
finally { |
176,10 → 201,11 |
} |
public List listDirectory(String dirName) |
throws UnsupportedEncodingException, IOException |
throws UnsupportedEncodingException, IOException, LogicException |
{ |
File dir = new File(imagesRoot, dirName); |
securePath(imagesRoot, dir); |
if(!dir.exists()) return null; |
File[] children = dir.listFiles(imagesFilter); |
292,4 → 318,25 |
{ |
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() + "]"); |
} |
} |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/webapp/ImageAction.java |
---|
1,10 → 1,8 |
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; |
11,11 → 9,11 |
import org.apache.log4j.Logger; |
public final class ImageAction |
extends Action |
extends BaseAction |
{ |
private static final Logger logger = Logger.getLogger(ImageAction.class); |
public ActionForward execute(ActionMapping mapping, ActionForm form, |
public ActionForward executeAction(ActionMapping mapping, ActionForm form, |
HttpServletRequest request, HttpServletResponse response) |
throws Exception |
{ |
25,31 → 23,22 |
logger.info("get image " + mapping.getParameter() + " for " + path); |
try { |
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()); |
} |
if("dir".equals(mapping.getParameter())) { |
response.setContentType(logic.getThumbnailMime()); |
logic.writeDir(path, response.getOutputStream()); |
} |
catch(FileNotFoundException ex) { |
logger.warn("not found: " + ex.getMessage()); |
response.sendError(HttpServletResponse.SC_NOT_FOUND); |
else if("small".equals(mapping.getParameter())) { |
response.setContentType(logic.getThumbnailMime()); |
logic.writeSmall(path, response.getOutputStream()); |
} |
catch(Exception ex) { |
logger.error("create thumbnail", ex); |
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; |
} |
/sun/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); |
} |
} |
Property changes: |
Added: svn:keywords |
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id |
\ No newline at end of property |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/webapp/IndexAction.java |
---|
3,7 → 3,6 |
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; |
11,11 → 10,11 |
import ak.photoalbum.util.FileUtils; |
public final class IndexAction |
extends Action |
extends BaseAction |
{ |
private static final Logger logger = Logger.getLogger(IndexAction.class); |
public ActionForward execute(ActionMapping mapping, ActionForm form, |
public ActionForward executeAction(ActionMapping mapping, ActionForm form, |
HttpServletRequest request, HttpServletResponse response) |
throws Exception |
{ |
26,31 → 25,21 |
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); |
if(Logic.getLogic().getEntry(dir, entry, top, prev, current, next)) { |
List index = Logic.getLogic().listDirectory(dir); |
logger.debug("ok"); |
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); |
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"); |
} |
else { |
logger.warn("not found [" + dir + "]"); |
response.sendError(HttpServletResponse.SC_NOT_FOUND); |
return null; |
} |
return mapping.findForward("success"); |
} |
} |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/images/jiu/JiuResizer.java |
---|
156,7 → 156,8 |
/** |
* Creates an {@link RGB24Image} from the argument AWT image instance. |
* @param image AWT image object to be converted to a {@link RGB24Image} |
* @return a {@link RGB24Image} object holding the image data from the argument image |
* @return a {@link RGB24Image} object holding the |
* image data from the argument image |
*/ |
protected static RGB24Image convertImageToRGB24Image(Image image) |
{ |
171,7 → 172,9 |
return null; |
} |
int[] pixels = new int[width * height]; |
PixelGrabber pg = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width); |
PixelGrabber pg = new PixelGrabber( |
image, 0, 0, width, height, pixels, 0, width); |
try |
{ |
pg.grabPixels(); |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/images/Thumbnailer.java |
---|
229,6 → 229,7 |
if(cached.getOriginTimestamp() != imageFile.lastModified()) { |
cached.getFile().delete(); |
cache.remove(imageFile.getCanonicalPath()); |
logger.debug("timestamps dont match"); |
return null; |
} |
357,8 → 358,8 |
children[i].delete(); |
if(logger.isDebugEnabled()) |
logger.debug("deleted: " |
+ origin.exists() + " " + cachedTimestamp + " " + originTimestamp); |
logger.debug("deleted: " + origin.exists() |
+ " " + cachedTimestamp + " " + originTimestamp); |
} |
} |
} |
463,13 → 464,15 |
} |
} |
synchronized protected BufferedImage createThumbnail(File imageFile, int width, int height) |
synchronized protected BufferedImage createThumbnail(File imageFile, |
int width, int height) |
throws IOException |
{ |
if(logger.isDebugEnabled()) |
logger.debug("create thumbnail " + imageFile.getCanonicalPath()); |
Image image = loadImage(imageFile.getCanonicalPath()); //ImageIO.read(imageFile); |
Image image = loadImage(imageFile.getCanonicalPath()); |
// = ImageIO.read(imageFile); |
int[] sizes; |
if(image == null) { // not supported format |
478,7 → 481,8 |
return null; |
} |
else { |
sizes = calcSizes(image.getWidth(null), image.getHeight(null), width, height); |
sizes = calcSizes(image.getWidth(null), image.getHeight(null), |
width, height); |
logger.debug("resize to " + sizes[0] + "x" + sizes[1]); |
return resizer.resize(image, sizes[0], sizes[1]); |
543,6 → 547,8 |
protected Image loadImage(String fileName) |
{ |
// FIXME: probably toolbox reads an image not by every request but |
// caches it |
Toolkit toolkit = Toolkit.getDefaultToolkit(); |
Image image = toolkit.getImage(fileName); |
554,13 → 560,12 |
if((status & ImageObserver.ALLBITS) != 0) break; |
if((status & ImageObserver.ERROR) != 0) return null; |
//Thread.currentThread().yield(); |
try { |
Thread.currentThread().sleep(100); |
} |
catch(Exception ex) { |
return null; |
}; |
} |
} |
return image; |
/sun/PhotoAlbum/trunk/src/ak/photoalbum/util/FileUtils.java |
---|
20,7 → 20,10 |
public static String getMime(String ext) |
{ |
return (String)MIME_MAP.get(ext); |
if(ext == null) |
return null; |
else |
return (String)MIME_MAP.get(ext.toLowerCase()); |
} |
public static void copyStreams(InputStream in, OutputStream out) |
/sun/PhotoAlbum/trunk/build.xml |
---|
24,6 → 24,8 |
</copy> |
<copy todir="webapp/WEB-INF/classes" file="conf/log4j.properties" /> |
<touch file="webapp/WEB-INF/web.xml" /> |
</target> |
<target name="clean"> |
/sun/PhotoAlbum/trunk/todo.txt |
---|
0,0 → 1,8 |
PhotoAlbum TODO |
1. Sometimes by changing image size (or image rotation) the cached thumbnail is not recreated. |
2. Cached files are not deleted where origins are. |
3. Split thumbnal and cache. |
4. Hierarchy of exceptions. |
5. Limits for memory caches (?). |
6. Design. |
Property changes: |
Added: svn:keywords |
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id |
\ No newline at end of property |
/sun/PhotoAlbum/trunk/conf/log4j.properties |
---|
5,4 → 5,5 |
log4j.appender.stdout.layout.ConversionPattern=[%t] %-5p %c - %m%n |
log4j.logger.ak=warn |
log4j.logger.ak.photoalbum.webapp=warn |
log4j.logger.ak.photoalbum=warn |
log4j.logger.ak.photoalbum.webapp=info |