Subversion Repositories general

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
936 dev 1
package ak.photoalbum.webapp;
2
 
3
import java.util.List;
4
import java.util.ArrayList;
5
import java.util.Arrays;
6
import java.util.Comparator;
7
import java.util.StringTokenizer;
8
import java.io.File;
9
import java.io.IOException;
10
import java.io.FileInputStream;
11
import java.io.OutputStream;
12
import java.io.UnsupportedEncodingException;
13
import java.io.FileNotFoundException;
14
import java.net.URLEncoder;
15
import org.apache.log4j.Logger;
16
import ak.photoalbum.images.Thumbnailer;
17
import ak.photoalbum.images.ThumbnailPosition;
18
import ak.photoalbum.util.FileUtils;
19
import ak.photoalbum.util.FileNameComparator;
20
import ak.photoalbum.util.ImagesFilter;
21
 
22
public class Logic
23
{
24
  protected static final int    DEFAULT_COLUMNS = 4;
25
  protected static final String URL_ENCODING    = "UTF-8";
26
 
27
  protected Logger       logger;
28
  protected Thumbnailer  thumbnailer;
29
  protected File         imagesRoot;
30
  protected int          columns            = DEFAULT_COLUMNS;
31
  protected ImagesFilter imagesFilter;
32
  protected Comparator   fileNameComparator = new FileNameComparator(true);
33
 
34
  protected Logic()
35
  {
36
    this.logger = Logger.getLogger(this.getClass());
37
  }
38
 
39
  public void init(String imagesRoot, String imagesMask,
40
    String cacheDir, String thumbnailFormat,
41
    Integer smallWidth, Integer smallHeight,
42
    Integer mediumWidth, Integer mediumHeight, Integer columns,
43
    String  dirTemplate, String  dirThumbnailPositions)
44
  {
45
    this.imagesRoot   = new File(imagesRoot);
46
    this.imagesFilter = new ImagesFilter(imagesMask);
47
    if(columns != null) this.columns = columns.intValue();
48
 
49
    this.thumbnailer = new Thumbnailer();
50
    this.thumbnailer.setImagesRoot(this.imagesRoot);
51
    this.thumbnailer.setCacheDir(new File(cacheDir));
52
 
53
    if(thumbnailFormat != null)
54
      this.thumbnailer.setFormat(thumbnailFormat);
55
    if(smallWidth != null)
56
      this.thumbnailer.setSmallWidth(smallWidth.intValue());
57
    if(smallHeight != null)
58
      this.thumbnailer.setSmallHeight(smallHeight.intValue());
59
    if(mediumWidth != null)
60
      this.thumbnailer.setMediumWidth(mediumWidth.intValue());
61
    if(mediumHeight != null)
62
      this.thumbnailer.setMediumHeight(mediumHeight.intValue());
63
 
64
    thumbnailer.setResizer(new ak.photoalbum.images.jiu.JiuResizer());
65
    thumbnailer.setImagesFilter(this.imagesFilter);
66
    thumbnailer.setDirTemplate(new File(dirTemplate));
67
    thumbnailer.setDirThumbnailPositions(
68
      parseThumbnailPositions(dirThumbnailPositions));
69
 
70
    try {
71
      thumbnailer.startup();
72
    }
73
    catch(Exception ex) {
74
      logger.error("init thumbnailer", ex);
75
    }
76
 
77
    logger.info("started");
78
  }
79
 
80
  public void buildCache()
81
    throws IOException
82
  {
83
    thumbnailer.buildCache();
84
  }
85
 
86
  public void getEntry(String path, IndexEntry page,
87
      IndexEntry index, IndexEntry prev, IndexEntry current, IndexEntry next)
88
    throws IOException, LogicException
89
  {
90
    File file = new File(imagesRoot, path);
91
 
92
    securePath(imagesRoot, file);
93
 
94
    if(!file.exists())
95
      throw new FileNotFoundException(
96
        "[" + file.getCanonicalPath() + "] not found");
97
 
98
    File   dir      = file.getParentFile();
99
    File[] children = dir.listFiles(imagesFilter);
100
    int    pos;
101
 
102
    Arrays.sort(children, fileNameComparator);
103
    pos = Arrays.binarySearch(children, file, fileNameComparator);
104
 
105
    if(pos < 0)
106
      throw new FileNotFoundException("[" + file.getCanonicalPath()
107
        + "] not found in [" + dir.getCanonicalPath() + "]");
108
 
109
    setEntryInfo(page,    file, false);
110
    setEntryInfo(current, file, true);
111
    setEntryInfo(index,   dir,  true);
112
    if(pos > 0)                 setEntryInfo(prev,  children[pos-1], true);
113
    if(pos < children.length-1) setEntryInfo(next,  children[pos+1], true);
114
  }
115
 
116
  protected void setEntryInfo(IndexEntry entry, File file, boolean small)
117
    throws IOException
118
  {
119
    String title = file.getName();
120
    int[]  size;
121
    String path  = getPath(file);
122
 
123
    if(file.isDirectory()) {
124
      size = thumbnailer.getDirSize(file);
125
    }
126
    else {
127
       title = FileUtils.extractFileName(title);
128
 
129
      if(small)
130
        size = thumbnailer.getSmallSize(file);
131
       else
132
        size = thumbnailer.getMediumSize(file);
133
    }
134
 
135
    entry.setFile(file);
136
    entry.setPath(path == null ? null : URLEncoder.encode(path, URL_ENCODING));
137
    entry.setTitle(title);
138
    entry.setIsDir(file.isDirectory());
139
    entry.setWidth(size[0]);
140
    entry.setHeight(size[1]);
141
  }
142
 
143
  public String getThumbnailMime()
144
  {
145
    return thumbnailer.getMime();
146
  }
147
 
148
  public String getOriginMime(String path)
149
    throws IOException, LogicException
150
  {
151
    File file = new File(imagesRoot, path);
152
 
153
    if(!file.exists()) return null;
154
    securePath(imagesRoot, file);
155
 
156
    return FileUtils.getMime(FileUtils.extractFileExt(path));
157
  }
158
 
159
  public void writeDir(String path, OutputStream out)
160
    throws IOException, LogicException
161
  {
162
    File file = new File(imagesRoot, path);
163
 
164
    securePath(imagesRoot, file);
165
    thumbnailer.writeDir(file, out);
166
  }
167
 
168
  public void writeSmall(String path, OutputStream out)
169
    throws IOException, LogicException
170
  {
171
    File file = new File(imagesRoot, path);
172
 
173
    securePath(imagesRoot, file);
174
    thumbnailer.writeSmall(file, out);
175
  }
176
 
177
  public void writeMedium(String path, OutputStream out)
178
    throws IOException, LogicException
179
  {
180
    File file = new File(imagesRoot, path);
181
 
182
    securePath(imagesRoot, file);
183
    thumbnailer.writeMedium(file, out);
184
  }
185
 
186
  public void writeOrigin(String path, OutputStream out)
187
    throws IOException, LogicException
188
  {
189
    FileInputStream in   = null;
190
    File            file = new File(imagesRoot, path);
191
 
192
    securePath(imagesRoot, file);
193
 
194
    try {
195
      in  = new FileInputStream(file);
196
      FileUtils.copyStreams(in, out);
197
    }
198
    finally {
199
      if(in != null) in.close();
200
    }
201
  }
202
 
203
  public List listDirectory(String dirName)
204
    throws UnsupportedEncodingException, IOException, LogicException
205
  {
206
    File dir = new File(imagesRoot, dirName);
207
 
208
    securePath(imagesRoot, dir);
209
    if(!dir.exists()) return null;
210
 
211
    File[] children = dir.listFiles(imagesFilter);
212
    List   rows     = new ArrayList();
213
    int    pos      = 0;
214
 
215
    Arrays.sort(children, fileNameComparator);
216
 
217
    while(pos < children.length) {
218
      List row    = new ArrayList();
219
      int  rowPos = 0;
220
 
221
      rows.add(row);
222
 
223
      while(rowPos < columns && pos < children.length) {
224
        String path  = getPath(children[pos]);
225
        String title = children[pos].getName();
226
        int[]  size;
227
 
228
        if(children[pos].isDirectory()) {
229
          size  = thumbnailer.getDirSize(children[pos]);
230
        }
231
        else {
232
          size  = thumbnailer.getSmallSize(children[pos]);
233
          title = FileUtils.extractFileName(title);
234
        }
235
 
236
        row.add(new IndexEntry(children[pos],
237
          URLEncoder.encode(path, URL_ENCODING),
238
          title, children[pos].isDirectory(), size[0], size[1]));
239
        rowPos++;
240
        pos++;
241
      }
242
 
243
      while(rowPos < columns) {
244
        row.add(null);
245
        rowPos++;
246
      }
247
    }
248
 
249
    return rows;
250
  }
251
 
252
  protected String getPath(File file)
253
    throws IOException
254
  {
255
    String path     = file.getCanonicalPath();
256
    String rootPath = imagesRoot.getCanonicalPath();
257
 
258
    if(path.equals(rootPath)) return "";
259
    if(!rootPath.endsWith(File.separator)) rootPath += File.separator;
260
 
261
    if(!path.startsWith(rootPath))
262
      return null;
263
 
264
    return path.substring(rootPath.length());
265
  }
266
 
267
  protected ThumbnailPosition[] parseThumbnailPositions(String str)
268
  {
269
    List            list      = new ArrayList();
270
    StringTokenizer tokenizer = new StringTokenizer(str, ";");
271
 
272
    while(tokenizer.hasMoreTokens()) {
273
      StringTokenizer tokenParser
274
        = new StringTokenizer(tokenizer.nextToken(), ",");
275
      int    x            = Integer.parseInt(tokenParser.nextToken().trim());
276
      int    y            = Integer.parseInt(tokenParser.nextToken().trim());
277
      int    width        = Integer.parseInt(tokenParser.nextToken().trim());
278
      int    height       = Integer.parseInt(tokenParser.nextToken().trim());
279
      String horAlignStr  = tokenParser.nextToken().trim().toLowerCase();
280
      String vertAlignStr = tokenParser.nextToken().trim().toLowerCase();
281
      int    horAlign;
282
      int    vertAlign;
283
 
284
      if("l".equals(horAlignStr))
285
        horAlign = ThumbnailPosition.ALIGN_HOR_LEFT;
286
      else if("r".equals(horAlignStr))
287
        horAlign = ThumbnailPosition.ALIGN_HOR_RIGHT;
288
      else if("c".equals(horAlignStr))
289
        horAlign = ThumbnailPosition.ALIGN_HOR_CENTER;
290
      else
291
        throw new RuntimeException(
292
          "Cannot parse " + horAlignStr + " as horizontal alignment");
293
 
294
      if("t".equals(vertAlignStr))
295
        vertAlign = ThumbnailPosition.ALIGN_VERT_TOP;
296
      else if("b".equals(vertAlignStr))
297
        vertAlign = ThumbnailPosition.ALIGN_VERT_BOTTOM;
298
      else if("c".equals(vertAlignStr))
299
        vertAlign = ThumbnailPosition.ALIGN_VERT_CENTER;
300
      else
301
        throw new RuntimeException(
302
          "Cannot parse " + vertAlignStr + " as vertical alignment");
303
 
304
      list.add(new ThumbnailPosition(x, y, width, height, horAlign, vertAlign));
305
    }
306
 
307
    ThumbnailPosition[] res = new ThumbnailPosition[list.size()];
308
 
309
    for(int i = 0; i < res.length; i++)
310
      res[i] = (ThumbnailPosition)list.get(i);
311
 
312
    return res;
313
  }
314
 
315
  protected static final Logic instance = new Logic();
316
 
317
  public static Logic getLogic()
318
  {
319
    return instance;
320
  }
321
 
322
  /**
323
   * checks if given file is really under the parent directory
324
   */
325
  protected void securePath(File parentDir, File file)
326
    throws IOException, LogicException
327
  {
328
    if(parentDir == null || file == null) return;
329
 
330
    File partFile = file.getCanonicalFile();
331
 
332
    parentDir = parentDir.getCanonicalFile();
333
    while(partFile != null) {
334
      if(partFile.equals(parentDir)) return;
335
      partFile = partFile.getParentFile();
336
    }
337
 
338
    throw new LogicSecurityException(
339
      "[" + file.getCanonicalPath() + "] is outside of directory ["
340
      + parentDir.getCanonicalPath() + "]");
341
  }
342
}