View Javadoc

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