View Javadoc

1   /*
2    * Copyright (c) 2005-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.mercury.maildir.file;
14  
15  import java.io.IOException;
16  import java.util.HashSet;
17  import java.util.Iterator;
18  import java.util.Set;
19  
20  import javax.mail.internet.SharedInputStream;
21  
22  
23  /**
24   * Pool of shared input stream instance. Since each instance uses RandomAccessFile from
25   * java.io package it is important managing these resources.
26   *
27   * @author Daniel Sendula
28   */
29  public class SharedInputStreamPool {
30  
31      /** Pool default instance */
32      protected static SharedInputStreamPool defaultInstance = new SharedInputStreamPool();
33  
34      /** Set of opened <code>SharedInputStreamImpl</code>s */
35      protected Set<SharedInputStream> files = new HashSet<SharedInputStream>();
36  
37      /** Maximum number of files */
38      protected int maxFiles = 200;
39  
40      /** Timeout for removing not closed files */
41      protected int timeout = 1000; // one secs
42  
43      /**
44       * Default constructor.
45       */
46      public SharedInputStreamPool() {
47      }
48  
49      /**
50       * This method returns default instance
51       * @return default instance
52       */
53      public static SharedInputStreamPool getDefaultInstance() {
54          return defaultInstance;
55      }
56  
57      /**
58       * This method creates new <code>SharedInputStreamImpl</code> instance.
59       *
60       * @param fileProvider file provider
61       * @param start start of the stream
62       * @param len end of the stream
63       * @return new <code>SharedInputStreamImpl</code> instance
64       */
65      public SharedInputStreamImpl newStream(FileProvider fileProvider, long start, long len) {
66          return new SharedInputStreamImpl(this, fileProvider, start, len);
67      }
68  
69      /**
70       * This is callback method used by <code>SharedInputStreamImpl</code> to register
71       * that stream is now opened. This is called each time <code>RandomAccessFile</code>
72       * is created over the stream. It is possible for stream to be implicitly &quot;clsoed&quot;
73       * and (re)opened several times.
74       *
75       * @param stream stream that is opened
76       */
77      protected synchronized void opened(SharedInputStreamImpl stream) {
78          files.add(stream);
79          int size = files.size();
80          if (size > maxFiles) {
81              int removed = 0;
82              int timeout = this.timeout * (size/maxFiles) * 2;
83              Iterator<SharedInputStream> it = files.iterator();
84              long now = System.currentTimeMillis();
85              SharedInputStreamImpl oldest = stream;
86              SharedInputStreamImpl s = null;
87              while (it.hasNext()) {
88                  s = (SharedInputStreamImpl)it.next();
89                  if ((now - stream.lastAccessed) < timeout) {
90                      try {
91                          s.closeImpl();
92                      } catch (IOException ignore) {
93                      }
94                      it.remove();
95                      removed++;
96                  } else if ((removed == 0) && (s.lastAccessed <= oldest.lastAccessed)) {
97                      oldest = stream;
98                  }
99              } // while
100             if (removed == 0) {
101                 closed(oldest);
102             }
103         }
104     }
105 
106     /**
107      * This is callback method used by <code>SharedInputStreamImpl</code>
108      * to register that stream is now closed.
109      * This is called each time <code>RandomAccessFile</code> used by the stream is released.
110      * It is possible for stream to be implicitly &quot;clsoed&quot;
111      * and (re)opened several times.
112      * @param stream stream that is closed
113      */
114     protected synchronized void closed(SharedInputStreamImpl stream) {
115         files.remove(stream);
116     }
117 
118     /**
119      * Method that implicitly releases all <code>RandomAccessFile</code>s from all
120      * streams that use given <code>FileProvider</code>
121      * @param provider file provider whos <code>SharedInputStreamImpl</code> belongs to
122      */
123     public synchronized void closeWithProvider(FileProvider provider) {
124         Iterator<SharedInputStream> it = files.iterator();
125         SharedInputStreamImpl s = null;
126         while (it.hasNext()) {
127             s = (SharedInputStreamImpl)it.next();
128             if (s.fileProvider == provider) {
129                 try {
130                     s.closeImpl();
131                 } catch (IOException ignore) {
132                 }
133                 it.remove();
134             }
135         } // while
136     }
137 }