KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > mailrepository > filepair > AbstractFileRepository


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.mailrepository.filepair;
19
20 import java.io.File JavaDoc;
21 import java.io.FileInputStream JavaDoc;
22 import java.io.FileOutputStream JavaDoc;
23 import java.io.FilenameFilter JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import org.apache.avalon.cornerstone.services.store.Repository;
30 import org.apache.avalon.excalibur.io.ExtensionFileFilter;
31 import org.apache.avalon.framework.activity.Initializable;
32 import org.apache.avalon.framework.configuration.Configurable;
33 import org.apache.avalon.framework.configuration.Configuration;
34 import org.apache.avalon.framework.configuration.ConfigurationException;
35 import org.apache.avalon.framework.context.Context;
36 import org.apache.avalon.framework.context.Contextualizable;
37 import org.apache.avalon.framework.logger.AbstractLogEnabled;
38 import org.apache.avalon.framework.service.ServiceException;
39 import org.apache.avalon.framework.service.ServiceManager;
40 import org.apache.avalon.framework.service.Serviceable;
41 import org.apache.avalon.phoenix.BlockContext;
42
43 /**
44  * This an abstract class implementing functionality for creating a file-store.
45  *
46  */

47 public abstract class AbstractFileRepository
48     extends AbstractLogEnabled
49     implements Repository, Contextualizable, Serviceable, Configurable, Initializable
50 {
51     protected static final boolean DEBUG = false;
52
53     protected static final String JavaDoc HANDLED_URL = "file://";
54     protected static final int BYTE_MASK = 0x0f;
55     protected static final char[] HEX_DIGITS = new char[]
56     {
57         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
58     };
59
60     protected String JavaDoc m_path;
61     protected String JavaDoc m_destination;
62     protected String JavaDoc m_extension;
63     protected String JavaDoc m_name;
64     protected FilenameFilter JavaDoc m_filter;
65     protected File JavaDoc m_baseDirectory;
66
67     protected ServiceManager m_serviceManager;
68     protected BlockContext m_context;
69
70     protected abstract String JavaDoc getExtensionDecorator();
71
72     public void contextualize( final Context context )
73     {
74         final BlockContext blockContext = (BlockContext) context;
75         m_baseDirectory = blockContext.getBaseDirectory();
76     }
77
78     public void service( final ServiceManager serviceManager )
79         throws ServiceException
80     {
81         m_serviceManager = serviceManager;
82     }
83
84     public void configure( final Configuration configuration )
85         throws ConfigurationException
86     {
87         if( null == m_destination )
88         {
89             final String JavaDoc destination = configuration.getAttribute( "destinationURL" );
90             setDestination( destination );
91         }
92     }
93
94     public void initialize()
95         throws Exception JavaDoc
96     {
97         getLogger().info( "Init " + getClass().getName() + " Store" );
98
99         m_name = RepositoryManager.getName();
100         String JavaDoc m_postfix = getExtensionDecorator();
101         m_extension = "." + m_name + m_postfix;
102         m_filter = new ExtensionFileFilter(m_extension);
103         //m_filter = new NumberedRepositoryFileFilter(getExtensionDecorator());
104

105         final File JavaDoc directory = new File JavaDoc( m_path );
106         directory.mkdirs();
107
108         getLogger().info( getClass().getName() + " opened in " + m_path );
109
110         //We will look for all numbered repository files in this
111
// directory and rename them to non-numbered repositories,
112
// logging all the way.
113

114         FilenameFilter JavaDoc num_filter = new NumberedRepositoryFileFilter(getExtensionDecorator());
115         final String JavaDoc[] names = directory.list( num_filter );
116
117         try {
118             for( int i = 0; i < names.length; i++ ) {
119                 String JavaDoc origFilename = names[i];
120
121                 //This needs to handle (skip over) the possible repository numbers
122
int pos = origFilename.length() - m_postfix.length();
123                 while (pos >= 1 && Character.isDigit(origFilename.charAt(pos - 1))) {
124                     pos--;
125                 }
126                 pos -= ".".length() + m_name.length();
127                 String JavaDoc newFilename = origFilename.substring(0, pos) + m_extension;
128
129                 File JavaDoc origFile = new File JavaDoc(directory, origFilename);
130                 File JavaDoc newFile = new File JavaDoc(directory, newFilename);
131
132                 if (origFile.renameTo(newFile)) {
133                     getLogger().info("Renamed " + origFile + " to " + newFile);
134                 } else {
135                     getLogger().info("Unable to rename " + origFile + " to " + newFile);
136                 }
137             }
138         } catch (Exception JavaDoc e) {
139             throw e;
140         }
141
142     }
143
144     protected void setDestination( final String JavaDoc destination )
145         throws ConfigurationException
146     {
147         if( !destination.startsWith( HANDLED_URL ) )
148         {
149             throw new ConfigurationException( "cannot handle destination " + destination );
150         }
151
152         m_path = destination.substring( HANDLED_URL.length() );
153
154         File JavaDoc directory;
155
156         // Check for absolute path
157
if( m_path.startsWith( "/" ) )
158         {
159             directory = new File JavaDoc( m_path );
160         }
161         else
162         {
163             directory = new File JavaDoc( m_baseDirectory, m_path );
164         }
165
166         try
167         {
168             directory = directory.getCanonicalFile();
169         }
170         catch( final IOException JavaDoc ioe )
171         {
172             throw new ConfigurationException( "Unable to form canonical representation of " +
173                                               directory );
174         }
175
176         m_path = directory.toString();
177
178         m_destination = destination;
179     }
180
181     protected AbstractFileRepository createChildRepository()
182         throws Exception JavaDoc
183     {
184         return (AbstractFileRepository) getClass().newInstance();
185     }
186
187     public Repository getChildRepository( final String JavaDoc childName )
188     {
189         AbstractFileRepository child = null;
190
191         try
192         {
193             child = createChildRepository();
194         }
195         catch( final Exception JavaDoc e )
196         {
197             throw new RuntimeException JavaDoc( "Cannot create child repository " +
198                                         childName + " : " + e );
199         }
200
201         try
202         {
203             child.service( m_serviceManager );
204         }
205         catch( final ServiceException cme )
206         {
207             throw new RuntimeException JavaDoc( "Cannot service child " +
208                                         "repository " + childName +
209                                         " : " + cme );
210         }
211
212         try
213         {
214             child.setDestination( m_destination + File.pathSeparatorChar +
215                                   childName + File.pathSeparator );
216         }
217         catch( final ConfigurationException ce )
218         {
219             throw new RuntimeException JavaDoc( "Cannot set destination for child child " +
220                                         "repository " + childName +
221                                         " : " + ce );
222         }
223
224         try
225         {
226             child.initialize();
227         }
228         catch( final Exception JavaDoc e )
229         {
230             throw new RuntimeException JavaDoc( "Cannot initialize child " +
231                                         "repository " + childName +
232                                         " : " + e );
233         }
234
235         if( DEBUG )
236         {
237             getLogger().debug( "Child repository of " + m_name + " created in " +
238                                m_destination + File.pathSeparatorChar +
239                                childName + File.pathSeparator );
240         }
241
242         return child;
243     }
244
245     protected File JavaDoc getFile( final String JavaDoc key )
246         throws IOException JavaDoc
247     {
248         return new File JavaDoc( encode( key ) );
249     }
250
251     protected InputStream JavaDoc getInputStream( final String JavaDoc key )
252         throws IOException JavaDoc
253     {
254         return new FileInputStream JavaDoc( getFile( key ) );
255     }
256
257     protected OutputStream JavaDoc getOutputStream( final String JavaDoc key )
258         throws IOException JavaDoc
259     {
260         return new FileOutputStream JavaDoc( getFile( key ) );
261     }
262
263     /**
264      * Remove the object associated to the given key.
265      */

266     public synchronized void remove( final String JavaDoc key )
267     {
268         try
269         {
270             final File JavaDoc file = getFile( key );
271             file.delete();
272             if( DEBUG ) getLogger().debug( "removed key " + key );
273         }
274         catch( final Exception JavaDoc e )
275         {
276             throw new RuntimeException JavaDoc( "Exception caught while removing" +
277                                         " an object: " + e );
278         }
279     }
280
281     /**
282      * Indicates if the given key is associated to a contained object.
283      */

284     public synchronized boolean containsKey( final String JavaDoc key )
285     {
286         try
287         {
288             final File JavaDoc file = getFile( key );
289             if( DEBUG ) getLogger().debug( "checking key " + key );
290             return file.exists();
291         }
292         catch( final Exception JavaDoc e )
293         {
294             throw new RuntimeException JavaDoc( "Exception caught while searching " +
295                                         "an object: " + e );
296         }
297     }
298
299     /**
300      * Returns the list of used keys.
301      */

302     public Iterator JavaDoc list()
303     {
304         final File JavaDoc storeDir = new File JavaDoc( m_path );
305         final String JavaDoc[] names = storeDir.list( m_filter );
306         final ArrayList JavaDoc list = new ArrayList JavaDoc();
307
308         for( int i = 0; i < names.length; i++ )
309         {
310             String JavaDoc decoded = decode(names[i]);
311             list.add(decoded);
312         }
313
314         return list.iterator();
315     }
316
317     /**
318      * Returns a String that uniquely identifies the object.
319      * <b>Note:</b> since this method uses the Object.toString()
320      * method, it's up to the caller to make sure that this method
321      * doesn't change between different JVM executions (like
322      * it may normally happen). For this reason, it's highly recommended
323      * (even if not mandated) that Strings be used as keys.
324      */

325     protected String JavaDoc encode( final String JavaDoc key )
326     {
327         final byte[] bytes = key.getBytes();
328         final char[] buffer = new char[ bytes.length << 1 ];
329
330         for( int i = 0, j = 0; i < bytes.length; i++ )
331         {
332             final int k = bytes[ i ];
333             buffer[ j++ ] = HEX_DIGITS[ ( k >>> 4 ) & BYTE_MASK ];
334             buffer[ j++ ] = HEX_DIGITS[ k & BYTE_MASK ];
335         }
336
337         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
338         result.append( m_path );
339         result.append( File.separator );
340         result.append( buffer );
341         result.append( m_extension );
342         return result.toString();
343     }
344
345     /**
346      * Inverse of encode exept it do not use path.
347      * So decode(encode(s) - m_path) = s.
348      * In other words it returns a String that can be used as key to retive
349      * the record contained in the 'filename' file.
350      */

351     protected String JavaDoc decode( String JavaDoc filename )
352     {
353         filename = filename.substring( 0, filename.length() - m_extension.length() );
354         final int size = filename.length();
355         final byte[] bytes = new byte[ size >>> 1 ];
356
357         for( int i = 0, j = 0; i < size; j++ )
358         {
359             bytes[ j ] = Byte.parseByte( filename.substring( i, i + 2 ), 16 );
360             i +=2;
361         }
362
363         return new String JavaDoc( bytes );
364     }
365 }
366
Popular Tags