KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > phoenix > components > configuration > FileSystemPersistentConfigurationRepository


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.phoenix.components.configuration;
9
10 import java.io.File JavaDoc;
11 import java.io.IOException JavaDoc;
12
13 import org.apache.avalon.excalibur.i18n.ResourceManager;
14 import org.apache.avalon.excalibur.i18n.Resources;
15 import org.apache.avalon.excalibur.io.FileUtil;
16 import org.apache.avalon.excalibur.property.PropertyException;
17 import org.apache.avalon.excalibur.property.PropertyUtil;
18 import org.apache.avalon.framework.CascadingRuntimeException;
19 import org.apache.avalon.framework.activity.Initializable;
20 import org.apache.avalon.framework.configuration.Configurable;
21 import org.apache.avalon.framework.configuration.Configuration;
22 import org.apache.avalon.framework.configuration.ConfigurationException;
23 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
24 import org.apache.avalon.framework.configuration.DefaultConfigurationSerializer;
25 import org.apache.avalon.framework.context.Context;
26 import org.apache.avalon.framework.context.ContextException;
27 import org.apache.avalon.framework.context.Contextualizable;
28 import org.apache.avalon.framework.logger.AbstractLogEnabled;
29 import org.apache.avalon.phoenix.interfaces.ConfigurationRepository;
30 import org.apache.avalon.phoenix.interfaces.ConfigurationRepositoryMBean;
31 import org.apache.excalibur.configuration.ConfigurationUtil;
32 import org.apache.excalibur.configuration.merged.ConfigurationMerger;
33 import org.apache.excalibur.configuration.merged.ConfigurationSplitter;
34
35 import org.xml.sax.SAXException JavaDoc;
36
37 /**
38  * <p>
39  * A ConfigurationRepository that will store partial configurations on disk.
40  * </p><p>
41  * When a Configuration is retrieved from the repository, the configuration from disk is
42  * <i>merged</i> with the configuration from the SAR. This merge is accompilished via
43  * {@link ConfigurationMerger#merge}.
44  * </p><p>
45  * When a Configuration is stored in the repository, if there is no <i>transient</i>, that is,
46  * configuration from the SAR, Configuration information, the first store is that. Subsequent
47  * calls to storeConfiguration will persist the difference between the <i>transient</i>
48  * Configuration and the passed configuration to disk. The differences are computed via
49  * {@link ConfigurationSplitter#split}
50  * </p>
51  *
52  * @author <a HREF="mailto:proyal@apache.org">Peter Royal</a>
53  * @see org.apache.excalibur.configuration.merged.ConfigurationMerger
54  * @see org.apache.excalibur.configuration.merged.ConfigurationSplitter
55  */

56 public class FileSystemPersistentConfigurationRepository extends AbstractLogEnabled
57     implements ConfigurationRepository, Contextualizable, Configurable, Initializable,
58     ConfigurationRepositoryMBean
59 {
60     private static final Resources REZ =
61         ResourceManager.getPackageResources( FileSystemPersistentConfigurationRepository.class );
62
63     private final DefaultConfigurationRepository m_persistedConfigurations =
64         new DefaultConfigurationRepository();
65     private final DefaultConfigurationRepository
66         m_transientConfigurations = new DefaultConfigurationRepository();
67     private final DefaultConfigurationRepository
68         m_mergedConfigurations = new DefaultConfigurationRepository();
69
70     private Context m_context;
71
72     private File JavaDoc m_storageDirectory;
73
74     public void contextualize( Context context )
75         throws ContextException
76     {
77         m_context = context;
78     }
79
80     public void configure( final Configuration configuration ) throws ConfigurationException
81     {
82         this.m_storageDirectory = new File JavaDoc( constructStoragePath( configuration ) );
83
84         try
85         {
86             FileUtil.forceMkdir( this.m_storageDirectory );
87         }
88         catch( IOException JavaDoc e )
89         {
90             final String JavaDoc message = REZ.getString( "config.error.dir.invalid",
91                                                   this.m_storageDirectory );
92
93             throw new ConfigurationException( message, e );
94
95         }
96     }
97
98     private String JavaDoc constructStoragePath( final Configuration configuration )
99         throws ConfigurationException
100     {
101         final String JavaDoc path =
102             configuration.getChild( "storage-directory" ).getValue( "${phoenix.home}/conf/apps" );
103
104         try
105         {
106             final Object JavaDoc opath = PropertyUtil.resolveProperty( path, m_context, false );
107
108             if( opath instanceof String JavaDoc )
109             {
110                 return FileUtil.normalize( ( String JavaDoc ) opath );
111             }
112             else
113             {
114                 final String JavaDoc message = REZ.getString( "config.error.nonstring",
115                                                       opath.getClass().getName() );
116
117                 throw new ConfigurationException( message );
118             }
119         }
120         catch( PropertyException e )
121         {
122             final String JavaDoc message = REZ.getString( "config.error.missingproperty",
123                                                   configuration.getLocation() );
124
125             throw new ConfigurationException( message, e );
126         }
127     }
128
129     public void initialize()
130         throws Exception JavaDoc
131     {
132         loadConfigurations();
133     }
134
135     private void loadConfigurations()
136         throws IOException JavaDoc, SAXException JavaDoc, ConfigurationException
137     {
138         final File JavaDoc[] apps = m_storageDirectory.listFiles( new ConfigurationDirectoryFilter() );
139
140         for( int i = 0; i < apps.length; i++ )
141         {
142             loadConfigurations( apps[i] );
143         }
144     }
145
146     private void loadConfigurations( File JavaDoc appPath )
147         throws IOException JavaDoc, SAXException JavaDoc, ConfigurationException
148     {
149         final DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
150         final String JavaDoc app = appPath.getName();
151         final File JavaDoc[] blocks = appPath.listFiles( new ConfigurationFileFilter() );
152
153         for( int i = 0; i < blocks.length; i++ )
154         {
155             final String JavaDoc block =
156                 blocks[i].getName().substring( 0, blocks[i].getName().indexOf( ".xml" ) );
157
158             m_persistedConfigurations.storeConfiguration( app,
159                                                           block,
160                                                           builder.buildFromFile( blocks[i] ) );
161
162             if( getLogger().isDebugEnabled() )
163                 getLogger().debug( "Loaded persistent configuration [app: " + app
164                                    + ", block: " + block + "]" );
165         }
166     }
167
168     private void persistConfiguration( final String JavaDoc application,
169                                        final String JavaDoc block,
170                                        final Configuration configuration )
171         throws SAXException JavaDoc, IOException JavaDoc, ConfigurationException
172     {
173         final DefaultConfigurationSerializer serializer = new DefaultConfigurationSerializer();
174         final File JavaDoc directory = new File JavaDoc( this.m_storageDirectory, application );
175
176         FileUtil.forceMkdir( directory );
177
178         if( getLogger().isDebugEnabled() )
179             getLogger().debug( "Serializing configuration to disk [app: " + application
180                                + ", block: " + block + "]" );
181
182         serializer.setIndent( true );
183         serializer.serializeToFile( new File JavaDoc( directory, block + ".xml" ), configuration );
184     }
185
186     public void removeConfiguration( String JavaDoc application, String JavaDoc block )
187         throws ConfigurationException
188     {
189         m_transientConfigurations.removeConfiguration( application, block );
190         m_mergedConfigurations.removeConfiguration( application, block );
191     }
192
193     public synchronized void storeConfiguration( final String JavaDoc application,
194                                                  final String JavaDoc block,
195                                                  final Configuration configuration )
196         throws ConfigurationException
197     {
198
199         if( m_transientConfigurations.hasConfiguration( application, block ) )
200         {
201             if( !ConfigurationUtil.equals( configuration, getConfiguration( application, block ) ) )
202             {
203                 final Configuration layer =
204                     ConfigurationSplitter.split( configuration,
205                                                  getConfiguration( application,
206                                                                    block,
207                                                                    m_transientConfigurations ) );
208
209                 m_persistedConfigurations.storeConfiguration( application, block, layer );
210                 m_mergedConfigurations.removeConfiguration( application, block );
211
212                 try
213                 {
214                     persistConfiguration( application, block, layer );
215                 }
216                 catch( SAXException JavaDoc e )
217                 {
218                     final String JavaDoc message =
219                         REZ.getString( "config.error.persist", application, block );
220
221                     throw new ConfigurationException( message, e );
222                 }
223                 catch( IOException JavaDoc e )
224                 {
225                     final String JavaDoc message =
226                         REZ.getString( "config.error.persist", application, block );
227
228                     throw new ConfigurationException( message, e );
229                 }
230             }
231         }
232         else
233         {
234             m_transientConfigurations.storeConfiguration( application, block, configuration );
235         }
236     }
237
238     public synchronized Configuration getConfiguration( final String JavaDoc application,
239                                                         final String JavaDoc block )
240         throws ConfigurationException
241     {
242         if( m_mergedConfigurations.hasConfiguration( application, block ) )
243         {
244             return m_mergedConfigurations.getConfiguration( application, block );
245         }
246         else
247         {
248             final Configuration configuration = createMergedConfiguration( application, block );
249
250             m_mergedConfigurations.storeConfiguration( application, block, configuration );
251
252             return configuration;
253         }
254     }
255
256     private Configuration createMergedConfiguration( final String JavaDoc application,
257                                                      final String JavaDoc block )
258         throws ConfigurationException
259     {
260         final Configuration t = getConfiguration( application, block, m_transientConfigurations );
261         final Configuration p = getConfiguration( application, block, m_persistedConfigurations );
262
263         if( null == t && p == null )
264         {
265             final String JavaDoc message = REZ.getString( "config.error.noconfig", block, application );
266
267             throw new ConfigurationException( message );
268         }
269         else if( null == t )
270         {
271             return p;
272         }
273         else if( null == p )
274         {
275             return t;
276         }
277         else
278         {
279             return ConfigurationMerger.merge( p, t );
280         }
281     }
282
283     private Configuration getConfiguration( final String JavaDoc application,
284                                             final String JavaDoc block,
285                                             final DefaultConfigurationRepository repository )
286     {
287         if( repository.hasConfiguration( application, block ) )
288         {
289             try
290             {
291                 return repository.getConfiguration( application, block );
292             }
293             catch( ConfigurationException e )
294             {
295                 final String JavaDoc message = REZ.getString( "config.error.noconfig", block, application );
296
297                 throw new CascadingRuntimeException( message, e );
298             }
299         }
300         else
301         {
302             return null;
303         }
304     }
305
306     public boolean hasConfiguration( String JavaDoc application, String JavaDoc block )
307     {
308         return m_mergedConfigurations.hasConfiguration( application, block )
309             || m_transientConfigurations.hasConfiguration( application, block )
310             || m_persistedConfigurations.hasConfiguration( application, block );
311     }
312 }
313
Popular Tags