Subversion Repositories general

Rev

Rev 1255 | Rev 1267 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1249 dev 1
package ak.photoalbum.logic;
936 dev 2
 
3
import java.util.List;
4
import java.util.ArrayList;
5
import java.util.Arrays;
1242 dev 6
import java.util.Map;
7
import java.util.Hashtable;
1250 dev 8
import java.util.Iterator;
936 dev 9
import java.io.File;
10
import java.io.IOException;
11
import java.io.FileInputStream;
1242 dev 12
import java.io.BufferedReader;
13
import java.io.InputStreamReader;
936 dev 14
import java.io.OutputStream;
15
import java.io.FileNotFoundException;
16
import java.net.URLEncoder;
1249 dev 17
 
1242 dev 18
import org.xml.sax.SAXException;
19
import org.apache.commons.digester.Digester;
936 dev 20
import org.apache.log4j.Logger;
1249 dev 21
 
936 dev 22
import ak.photoalbum.util.FileUtils;
1250 dev 23
import ak.photoalbum.util.ResourceFactory;
1249 dev 24
import ak.photoalbum.config.ConfigRoot;
25
import ak.photoalbum.config.ConfigBranch;
26
import ak.photoalbum.config.ConfigDirThumbnail;
936 dev 27
 
28
public class Logic
29
{
30
  protected static final String URL_ENCODING    = "UTF-8";
1242 dev 31
  protected static final String META_FILE_NAME  = "meta.xml"; // FIXME make configurable (?)
936 dev 32
 
33
  protected Logger       logger;
1247 dev 34
  protected ConfigRoot   config;
1249 dev 35
  protected Map          branches           = new Hashtable(); // <String, Branch>
1247 dev 36
  protected Digester     configDigester     = createConfigDigester();
1242 dev 37
  protected Digester     metaDigester       = createMetaDigester();
936 dev 38
 
39
  protected Logic()
40
  {
41
    this.logger = Logger.getLogger(this.getClass());
42
  }
43
 
1247 dev 44
  protected Digester createConfigDigester()
936 dev 45
  {
1247 dev 46
    Digester digester = new Digester();
47
    digester.setValidating(false);
48
 
1251 dev 49
    digester.addObjectCreate(      "photos",                                ConfigRoot.class);
50
    digester.addBeanPropertySetter("photos/default-branch",                 "defaultBranch");
1247 dev 51
 
1251 dev 52
    digester.addObjectCreate(      "photos/branch",                         ConfigBranch.class);
53
    digester.addBeanPropertySetter("photos/branch/uri");
54
    digester.addBeanPropertySetter("photos/branch/images-root",             "imagesRoot");
55
    digester.addBeanPropertySetter("photos/branch/cache-dir",               "cacheDir");
56
    digester.addBeanPropertySetter("photos/branch/thumbnail-format",        "thumbnailFormat");
57
    digester.addBeanPropertySetter("photos/branch/columns");
58
    digester.addBeanPropertySetter("photos/branch/rows");
59
    digester.addCallMethod(        "photos/branch/images-mask",             "addImagesMask",
60
      0, new Class[] { String.class });
61
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/template",  "dirTemplate");
1247 dev 62
 
1251 dev 63
    digester.addObjectCreate(      "photos/branch/dir-thumbnail/thumbnail", ConfigDirThumbnail.class);
64
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/thumbnail/left");
65
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/thumbnail/top");
66
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/thumbnail/width");
67
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/thumbnail/height");
68
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/thumbnail/align");
69
    digester.addBeanPropertySetter("photos/branch/dir-thumbnail/thumbnail/valign");
1255 dev 70
    digester.addSetNext(           "photos/branch/dir-thumbnail/thumbnail", "addDirThumbnail");
1247 dev 71
 
1251 dev 72
    digester.addSetNext(           "photos/branch",                         "addBranch");
73
 
1247 dev 74
    return digester;
75
  }
76
 
77
  protected Digester createMetaDigester()
78
  {
79
    Digester digester = new Digester();
80
    digester.setValidating(false);
81
 
82
    digester.addObjectCreate("meta", MetaInfo.class);
83
 
84
    digester.addObjectCreate("meta/item", MetaInfoItem.class);
85
    digester.addSetProperties("meta/item", "id", "id");
86
    digester.addBeanPropertySetter("meta/item/title", "title");
87
    digester.addBeanPropertySetter("meta/item/subtitle", "subtitle");
88
    digester.addSetProperties("meta/item/subtitle", "mime", "subtitleMime");
89
    digester.addBeanPropertySetter("meta/item/comment", "comment");
90
    digester.addSetProperties("meta/item/comment", "mime", "commentMime");
91
    digester.addSetNext("meta/item", "addItem");
92
 
93
    return digester;
94
  }
95
 
96
  public void init(ResourceFactory resourceFactory, String configPath)
1249 dev 97
    throws IOException, SAXException, LogicException
1247 dev 98
  {
99
    logger.info("starting");
100
    config = (ConfigRoot)configDigester.parse(resourceFactory.getAsStream(configPath));
936 dev 101
 
1250 dev 102
    for(Iterator i = config.getBranches().iterator(); i.hasNext(); ) {
103
      Branch branch = new Branch(resourceFactory, (ConfigBranch)i.next());
104
      branches.put(branch.getUri(), branch);
1249 dev 105
    }
936 dev 106
 
107
    logger.info("started");
108
  }
109
 
1249 dev 110
  public Branch getBranch(String uri)
1251 dev 111
    throws LogicException
1249 dev 112
  {
1251 dev 113
    if(uri == null || uri.equals("")) {
114
      uri = config.getDefaultBranch();
115
      if(uri == null)
116
        throw new LogicException("No default branch configured");
117
    }
118
 
119
    Branch branch = (Branch)branches.get(uri);
120
 
121
    if(branch == null) 
122
      throw new LogicException("Branch not found");
123
 
124
    return branch;
1249 dev 125
  }
126
 
127
  public void buildCache(String uri)
1251 dev 128
    throws IOException, LogicException
936 dev 129
  {
1249 dev 130
    getBranch(uri).getThumbnailer().buildCache();
936 dev 131
  }
132
 
1257 dev 133
  public void rebuildCache(String uri)
134
    throws IOException, LogicException
135
  {
136
    getBranch(uri).getThumbnailer().rebuildCache();
137
  }
138
 
139
  public void deleteCache(String uri)
140
    throws IOException, LogicException
141
  {
142
    getBranch(uri).getThumbnailer().deleteCache();
143
  }
144
 
145
  public void reloadCache(String uri)
146
    throws IOException, LogicException
147
  {
148
    getBranch(uri).getThumbnailer().reloadCache();
149
  }
150
 
1249 dev 151
  public void getEntry(String uri, String path, IndexEntry page,
936 dev 152
      IndexEntry index, IndexEntry prev, IndexEntry current, IndexEntry next)
1242 dev 153
    throws IOException, SAXException, LogicException
936 dev 154
  {
1249 dev 155
    Branch branch = getBranch(uri);
156
    File   file   = new File(branch.getImagesRoot(), path);
936 dev 157
 
1249 dev 158
    securePath(branch.getImagesRoot(), file);
936 dev 159
 
160
    if(!file.exists())
161
      throw new FileNotFoundException(
162
        "[" + file.getCanonicalPath() + "] not found");
163
 
164
    File   dir      = file.getParentFile();
1249 dev 165
    File[] children = dir.listFiles(branch.getImagesFilter());
936 dev 166
    int    pos;
167
 
1249 dev 168
    Arrays.sort(children, branch.getFileNameComparator());
169
    pos = Arrays.binarySearch(children, file, branch.getFileNameComparator());
936 dev 170
 
171
    if(pos < 0)
172
      throw new FileNotFoundException("[" + file.getCanonicalPath()
173
        + "] not found in [" + dir.getCanonicalPath() + "]");
174
 
1249 dev 175
    branch.getMetaInfos().clear();     // FIXME make this more intelligent
1250 dev 176
    setEntryInfo(branch, page,    file, false);
177
    setEntryInfo(branch, current, file, true);
178
    setEntryInfo(branch, index,   dir,  true);
179
    if(pos > 0)                 setEntryInfo(branch, prev, children[pos-1], true);
180
    if(pos < children.length-1) setEntryInfo(branch, next, children[pos+1], true);
936 dev 181
  }
182
 
1249 dev 183
  protected void setEntryInfo(Branch branch, IndexEntry entry, File file, boolean small)
1242 dev 184
    throws IOException, SAXException
936 dev 185
  {
186
    String title = file.getName();
187
    int[]  size;
1250 dev 188
    String path  = getPath(branch, file);
936 dev 189
 
190
    if(file.isDirectory()) {
1249 dev 191
      size = branch.getThumbnailer().getDirSize(file);
936 dev 192
    }
193
    else {
1242 dev 194
      title = FileUtils.extractFileName(title);
936 dev 195
 
196
      if(small)
1249 dev 197
        size = branch.getThumbnailer().getSmallSize(file);
1242 dev 198
      else
1249 dev 199
        size = branch.getThumbnailer().getMediumSize(file);
936 dev 200
    }
201
 
202
    entry.setFile(file);
203
    entry.setPath(path == null ? null : URLEncoder.encode(path, URL_ENCODING));
204
    entry.setTitle(title);
205
    entry.setIsDir(file.isDirectory());
206
    entry.setWidth(size[0]);
207
    entry.setHeight(size[1]);
1242 dev 208
 
1250 dev 209
    MetaInfoItem meta = findMetaInfo(branch, branch.getImagesRoot(), file);
1242 dev 210
    if(meta != null) {
211
      if(meta.getTitle() != null) {
212
        entry.setTitle(meta.getTitle());
213
      }
214
      if(meta.getSubtitle() != null) {
215
        entry.setSubtitle(meta.getSubtitle());
216
        entry.setSubtitleMime(meta.getSubtitleMime());
217
      }
218
      if(meta.getComment() != null) {
219
        entry.setComment(meta.getComment());
220
        entry.setCommentMime(meta.getCommentMime());
221
      }
222
    }
936 dev 223
  }
224
 
1249 dev 225
  public String getThumbnailMime(String uri)
1251 dev 226
    throws LogicException
936 dev 227
  {
1249 dev 228
    return getBranch(uri).getThumbnailer().getMime();
936 dev 229
  }
230
 
1249 dev 231
  public String getOriginMime(String uri, String path)
936 dev 232
    throws IOException, LogicException
233
  {
1249 dev 234
    Branch branch = getBranch(uri);
235
    File   file   = new File(branch.getImagesRoot(), path);
936 dev 236
 
237
    if(!file.exists()) return null;
1249 dev 238
    securePath(branch.getImagesRoot(), file);
936 dev 239
 
240
    return FileUtils.getMime(FileUtils.extractFileExt(path));
241
  }
242
 
1249 dev 243
  public void writeDir(String uri, String path, OutputStream out)
936 dev 244
    throws IOException, LogicException
245
  {
1249 dev 246
    Branch branch = getBranch(uri);
247
    File   file   = new File(branch.getImagesRoot(), path);
936 dev 248
 
1249 dev 249
    securePath(branch.getImagesRoot(), file);
250
    branch.getThumbnailer().writeDir(file, out);
936 dev 251
  }
252
 
1249 dev 253
  public void writeSmall(String uri, String path, OutputStream out)
936 dev 254
    throws IOException, LogicException
255
  {
1249 dev 256
    Branch branch = getBranch(uri);
257
    File   file   = new File(branch.getImagesRoot(), path);
936 dev 258
 
1249 dev 259
    securePath(branch.getImagesRoot(), file);
260
    branch.getThumbnailer().writeSmall(file, out);
936 dev 261
  }
262
 
1249 dev 263
  public void writeMedium(String uri, String path, OutputStream out)
936 dev 264
    throws IOException, LogicException
265
  {
1249 dev 266
    Branch branch = getBranch(uri);
267
    File   file   = new File(branch.getImagesRoot(), path);
936 dev 268
 
1249 dev 269
    securePath(branch.getImagesRoot(), file);
270
    branch.getThumbnailer().writeMedium(file, out);
936 dev 271
  }
272
 
1249 dev 273
  public void writeOrigin(String uri, String path, OutputStream out)
936 dev 274
    throws IOException, LogicException
275
  {
1249 dev 276
    Branch          branch = getBranch(uri);
277
    FileInputStream in     = null;
278
    File            file   = new File(branch.getImagesRoot(), path);
936 dev 279
 
1249 dev 280
    securePath(branch.getImagesRoot(), file);
936 dev 281
 
282
    try {
283
      in  = new FileInputStream(file);
284
      FileUtils.copyStreams(in, out);
285
    }
286
    finally {
287
      if(in != null) in.close();
288
    }
289
  }
290
 
1249 dev 291
  protected MetaInfo getMetaInfo(Branch branch, File dir)
1242 dev 292
    throws IOException, SAXException
293
  {
1249 dev 294
    MetaInfo meta = (MetaInfo)branch.getMetaInfos().get(dir);
1242 dev 295
    if(meta != null) return meta;
296
 
297
    File metaFile = new File(dir, META_FILE_NAME);
298
    if(!metaFile.exists()) return null;
299
 
300
    meta = (MetaInfo)metaDigester.parse(new FileInputStream(metaFile));
301
    meta.setDir(dir);
1249 dev 302
    branch.getMetaInfos().put(dir, meta);
1242 dev 303
 
304
    return meta;
305
  }
306
 
1250 dev 307
  protected MetaInfoItem findMetaInfo(Branch branch, File rootDir, File file)
1242 dev 308
    throws IOException, SAXException
309
  {
310
    file    = file.getCanonicalFile();
311
    rootDir = rootDir.getCanonicalFile();
312
 
313
    File dir = file;
314
    if(!dir.isDirectory())
315
      dir = dir.getParentFile();
316
 
317
    MetaInfoItem metaItem = null;
318
    for(; metaItem == null; dir = dir.getParentFile()) {
319
      if(dir == null) break;
320
 
1250 dev 321
      MetaInfo meta = getMetaInfo(branch, dir);
1242 dev 322
      if(meta != null) {
323
        metaItem = meta.findItem(file);
324
      }
325
      if(rootDir.equals(dir)) break;
326
    }
327
 
328
    return metaItem;
329
  }
330
 
1249 dev 331
  public boolean listDirectory(String uri, String dirName, int page, List table, List pages)
1242 dev 332
    throws IOException, LogicException, SAXException
333
  {
1249 dev 334
    Branch branch = getBranch(uri);
335
    File   dir    = new File(branch.getImagesRoot(), dirName);
936 dev 336
 
1249 dev 337
    securePath(branch.getImagesRoot(), dir);
1242 dev 338
    if(!dir.exists()) return false;
936 dev 339
 
1249 dev 340
    File[] children  = dir.listFiles(branch.getImagesFilter());
341
    int    pos       = page * branch.getColumns() * branch.getRows();
936 dev 342
 
1249 dev 343
    Arrays.sort(children, branch.getFileNameComparator());
344
    branch.getMetaInfos().clear();           // FIXME do this more intelligent (?)
936 dev 345
 
1242 dev 346
    // the pages list
347
    pages.clear();
1249 dev 348
    for(int i = 0; i < (int)Math.ceil((double)children.length / branch.getColumns() / branch.getRows()); i++) {
1242 dev 349
      pages.add(new PageItem(i, i == page));
350
    }
351
 
352
    // the main table
353
    table.clear();
1249 dev 354
    while(pos < children.length && pos < (page+1) * branch.getColumns() * branch.getRows()) {
936 dev 355
      List row    = new ArrayList();
356
      int  rowPos = 0;
357
 
1242 dev 358
      table.add(row);
936 dev 359
 
1249 dev 360
      while(rowPos < branch.getColumns() && pos < children.length) {
1250 dev 361
        String path  = getPath(branch, children[pos]);
936 dev 362
        String title = children[pos].getName();
363
        int[]  size;
364
 
365
        if(children[pos].isDirectory()) {
1249 dev 366
          size  = branch.getThumbnailer().getDirSize(children[pos]);
936 dev 367
        }
368
        else {
1249 dev 369
          size  = branch.getThumbnailer().getSmallSize(children[pos]);
936 dev 370
          title = FileUtils.extractFileName(title);
371
        }
372
 
1242 dev 373
        IndexEntry entry = new IndexEntry(children[pos],
936 dev 374
          URLEncoder.encode(path, URL_ENCODING),
1242 dev 375
          title, children[pos].isDirectory(), size[0], size[1]);
376
 
1250 dev 377
        MetaInfoItem meta = findMetaInfo(branch, branch.getImagesRoot(), children[pos]);
1242 dev 378
        if(meta != null) {
379
          if(meta.getTitle() != null) {
380
            entry.setTitle(meta.getTitle());
381
          }
382
          if(meta.getSubtitle() != null) {
383
            entry.setSubtitle(meta.getSubtitle());
384
            entry.setSubtitleMime(meta.getSubtitleMime());
385
          }
386
          if(meta.getComment() != null) {
387
            entry.setComment(meta.getComment());
388
            entry.setCommentMime(meta.getCommentMime());
389
          }
390
        }
391
 
392
        row.add(entry);
936 dev 393
        rowPos++;
394
        pos++;
395
      }
396
 
1249 dev 397
      while(rowPos < branch.getColumns()) {
936 dev 398
        row.add(null);
399
        rowPos++;
400
      }
401
    }
402
 
1242 dev 403
    return true;
936 dev 404
  }
405
 
1249 dev 406
  protected String getPath(Branch branch, File file)
936 dev 407
    throws IOException
408
  {
409
    String path     = file.getCanonicalPath();
1249 dev 410
    String rootPath = branch.getImagesRoot().getCanonicalPath();
936 dev 411
 
412
    if(path.equals(rootPath)) return "";
413
    if(!rootPath.endsWith(File.separator)) rootPath += File.separator;
414
 
415
    if(!path.startsWith(rootPath))
416
      return null;
417
 
418
    return path.substring(rootPath.length());
419
  }
420
 
421
  protected static final Logic instance = new Logic();
422
 
423
  public static Logic getLogic()
424
  {
425
    return instance;
426
  }
427
 
428
  /**
429
   * checks if given file is really under the parent directory
430
   */
431
  protected void securePath(File parentDir, File file)
432
    throws IOException, LogicException
433
  {
434
    if(parentDir == null || file == null) return;
435
 
436
    File partFile = file.getCanonicalFile();
437
 
438
    parentDir = parentDir.getCanonicalFile();
439
    while(partFile != null) {
440
      if(partFile.equals(parentDir)) return;
441
      partFile = partFile.getParentFile();
442
    }
443
 
444
    throw new LogicSecurityException(
445
      "[" + file.getCanonicalPath() + "] is outside of directory ["
446
      + parentDir.getCanonicalPath() + "]");
447
  }
448
}