source: contrib/MailArchiver/sources/vendor/mime4j/apache-mime4j-0.7-SNAPSHOT-20110327.010440-17/storage/src/main/java/org/apache/james/mime4j/storage/MultiReferenceStorage.java @ 6785

Revision 6785, 4.6 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
1/****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one   *
3 * or more contributor license agreements.  See the NOTICE file *
4 * distributed with this work for additional information        *
5 * regarding copyright ownership.  The ASF licenses this file   *
6 * to you under the Apache License, Version 2.0 (the            *
7 * "License"); you may not use this file except in compliance   *
8 * with the License.  You may obtain a copy of the License at   *
9 *                                                              *
10 *   http://www.apache.org/licenses/LICENSE-2.0                 *
11 *                                                              *
12 * Unless required by applicable law or agreed to in writing,   *
13 * software distributed under the License is distributed on an  *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15 * KIND, either express or implied.  See the License for the    *
16 * specific language governing permissions and limitations      *
17 * under the License.                                           *
18 ****************************************************************/
19
20package org.apache.james.mime4j.storage;
21
22import java.io.IOException;
23import java.io.InputStream;
24
25/**
26 * <p>
27 * A wrapper around another {@link Storage} that also maintains a reference
28 * counter. The inner storage gets deleted only if the reference counter reaches
29 * zero.
30 * </p>
31 * <p>
32 * Reference counting is used to delete the storage when it is no longer needed.
33 * So, any users of this class should note:
34 * </p>
35 * <ul>
36 * <li>The reference count is set up one on construction. In all other cases,
37 * {@link #addReference()} should be called when the storage is shared.</li>
38 * <li>The caller of {@link #addReference()} should ensure that
39 * {@link #delete()} is called once and only once.</li>
40 * <li>Sharing the {@link Storage} instance passed into
41 * {@link #MultiReferenceStorage(Storage)} may lead to miscounting and premature
42 * deletion</li>
43 * </ul>
44 */
45public class MultiReferenceStorage implements Storage {
46
47    private final Storage storage;
48    private int referenceCounter;
49
50    /**
51     * Creates a new <code>MultiReferenceStorage</code> instance for the given
52     * back-end. The reference counter is initially set to one so the caller
53     * does not have to call {@link #addReference()} after this constructor.
54     *
55     * @param storage
56     *            storage back-end that should be reference counted.
57     * @throws IllegalArgumentException
58     *             when storage is null
59     */
60    public MultiReferenceStorage(Storage storage) {
61        if (storage == null)
62            throw new IllegalArgumentException();
63
64        this.storage = storage;
65        this.referenceCounter = 1; // caller holds first reference
66    }
67
68    /**
69     * Increments the reference counter.
70     *
71     * @throws IllegalStateException
72     *             if the reference counter is zero which implies that the
73     *             backing storage has already been deleted.
74     */
75    public void addReference() {
76        incrementCounter();
77    }
78
79    /**
80     * Decrements the reference counter and deletes the inner
81     * <code>Storage</code> object if the reference counter reaches zero.
82     * <p>
83     * A client that holds a reference to this object must make sure not to
84     * invoke this method a second time.
85     *
86     * @throws IllegalStateException
87     *             if the reference counter is zero which implies that the
88     *             backing storage has already been deleted.
89     */
90    public void delete() {
91        if (decrementCounter()) {
92            storage.delete();
93        }
94    }
95
96    /**
97     * Returns the input stream of the inner <code>Storage</code> object.
98     *
99     * @return an input stream.
100     */
101    public InputStream getInputStream() throws IOException {
102        return storage.getInputStream();
103    }
104
105    /**
106     * Synchronized increment of reference count.
107     *
108     * @throws IllegalStateException
109     *             when counter is already zero
110     */
111    private synchronized void incrementCounter() {
112        if (referenceCounter == 0)
113            throw new IllegalStateException("storage has been deleted");
114
115        referenceCounter++;
116    }
117
118    /**
119     * Synchronized decrement of reference count.
120     *
121     * @return true when counter has reached zero, false otherwise
122     * @throws IllegalStateException
123     *             when counter is already zero
124     */
125    private synchronized boolean decrementCounter() {
126        if (referenceCounter == 0)
127            throw new IllegalStateException("storage has been deleted");
128
129        return --referenceCounter == 0;
130    }
131}
Note: See TracBrowser for help on using the repository browser.