View Javadoc

1   /*
2    * Copyright 2008-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.maven.issues.cache;
17  
18  import java.io.BufferedInputStream;
19  import java.io.BufferedOutputStream;
20  import java.io.Closeable;
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.eclipse.mylyn.tasks.core.data.TaskData;
32  
33  /**
34   * Base implementation of the {@link TaskDataStore} interface that writes the
35   * task data to individual files.
36   *
37   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
38   * @version $Revision:591 $
39   */
40  public abstract class AbstractFileTaskDataStore implements TaskDataStore
41  {
42    // ********************************* Fields *********************************
43  
44    // --- constants ------------------------------------------------------------
45  
46    /**
47     * Reference to the logger for this class.
48     */
49    private static final Log LOG = LogFactory
50        .getLog(AbstractFileTaskDataStore.class);
51  
52    // --- members --------------------------------------------------------------
53  
54    /**
55     * The reference to the directory to store the individual task files.
56     */
57    protected final File persistentStoreDirectory;
58  
59    /**
60     * The extension to append to the created files. This extension usually
61     * includes the dot, may be empty, but must not be <code>null</code>.
62     */
63    protected final String fileNameExtension;
64  
65    // ****************************** Initializer *******************************
66  
67    // ****************************** Constructors ******************************
68  
69    /**
70     * Default constructor.
71     *
72     * @param persistentStoreDirectory the reference to the directory to store the
73     *          individual task files.
74     * @param fileNameExtension the extension to append to the created files.
75     */
76    protected AbstractFileTaskDataStore(final File persistentStoreDirectory,
77        final String fileNameExtension)
78    {
79      this.persistentStoreDirectory = persistentStoreDirectory;
80      this.fileNameExtension = fileNameExtension;
81    }
82  
83    // ****************************** Inner Classes *****************************
84  
85    // ********************************* Methods ********************************
86  
87    // --- init -----------------------------------------------------------------
88  
89    // --- get&set --------------------------------------------------------------
90  
91    // --- business -------------------------------------------------------------
92  
93    /**
94     * {@inheritDoc}
95     */
96    public TaskData load(final String id) throws PersistenceException
97    {
98      final File file = createFile(id);
99      if (file.exists())
100     {
101       final TaskData task = readTask(file);
102       return task;
103     }
104     return null;
105   }
106 
107   /**
108    * Creates a file for the given identifier.
109    *
110    * @param id the identifier of the file to be created.
111    * @return a file with a name that is unique for the given unique identifier.
112    */
113   protected File createFile(final String id)
114   {
115     return new File(this.persistentStoreDirectory, id + fileNameExtension);
116   }
117 
118   /**
119    * Reads the task from the given file.
120    *
121    * @param file the file to read from.
122    * @return the task information read from the given file.
123    * @throws PersistenceException if the task data cannot be read from the given
124    *           file.
125    */
126   protected TaskData readTask(final File file) throws PersistenceException
127   {
128     InputStream in = null;
129     try
130     {
131       in = new BufferedInputStream(new FileInputStream(file));
132       final TaskData task = readTask(in);
133       return task;
134     }
135     catch (final Exception e)
136     {
137       final String message =
138           "Cannot read task from file '" + file.getAbsolutePath() + "'.";
139       LOG.warn(message);
140       throw new PersistenceException(message, e);
141     }
142     finally
143     {
144       close(file, in);
145     }
146   }
147 
148   /**
149    * Reads the task from the given input stream.
150    *
151    * @param inputStream the input stream to read from.
152    * @return the task information read from the given input stream.
153    * @throws PersistenceException if the task data cannot be read from the given
154    *           input stream.
155    */
156   protected abstract TaskData readTask(InputStream inputStream)
157     throws PersistenceException;
158 
159   /**
160    * {@inheritDoc}
161    */
162   public void persist(final TaskData task) throws PersistenceException
163   {
164     final String id = task.getTaskId();
165     final File file = createFile(id);
166     writeTask(file, task);
167   }
168 
169   /**
170    * Persists the task to the given file. If the file already exists, it will be
171    * overwritten.
172    *
173    * @param file the file to write to.
174    * @param task the task data to store.
175    * @throws PersistenceException if the task data cannot be written to the
176    *           given file.
177    */
178   protected void writeTask(final File file, final TaskData task)
179     throws PersistenceException
180   {
181     OutputStream out = null;
182     try
183     {
184       out = new BufferedOutputStream(new FileOutputStream(file));
185       writeTask(out, task);
186     }
187     catch (final FileNotFoundException e)
188     {
189       final String message =
190           "Cannot persist task data with ID '" + task.getTaskId()
191               + "' to file '" + file.getAbsolutePath() + "'.";
192       LOG.warn(message, e);
193       throw new PersistenceException(message, e);
194     }
195     finally
196     {
197       close(file, out);
198     }
199   }
200 
201   /**
202    * Closes the given closeable and logs problems at error level to the log.
203    *
204    * @param closeable the closeable to close.
205    */
206   protected static void close(final Closeable closeable)
207   {
208     close(null, closeable);
209   }
210 
211   /**
212    * Closes the given closeable and logs problems at error level to the log.
213    *
214    * @param file the name of the file for logging.
215    * @param closeable the closeable to close.
216    */
217   protected static void close(final File file, final Closeable closeable)
218   {
219     if (closeable != null)
220     {
221       try
222       {
223         closeable.close();
224       }
225       catch (final IOException e)
226       {
227         // Ignore
228         if (LOG.isErrorEnabled())
229         {
230           final String message =
231               file != null ? "Cannot close stream to file '" + file
232                              + "'. Continue..."
233                   : "Cannot close stream. Continue...";
234           LOG.error(message, e);
235         }
236       }
237     }
238   }
239 
240   /**
241    * Persists the task to the given output stream.
242    *
243    * @param outputStream the output stream to write to.
244    * @param task the task data to store.
245    * @throws PersistenceException if the task data cannot be written to the
246    *           given output stream.
247    */
248   protected abstract void writeTask(OutputStream outputStream, TaskData task)
249     throws PersistenceException;
250 
251   // --- object basics --------------------------------------------------------
252 
253 }