KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > system > configuration > LocalConfigStore


1 /**
2  *
3  * Copyright 2003-2004 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You 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 implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.geronimo.system.configuration;
19
20 import java.io.BufferedInputStream JavaDoc;
21 import java.io.BufferedOutputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileNotFoundException JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.ObjectInputStream JavaDoc;
29 import java.io.ObjectOutputStream JavaDoc;
30 import java.io.OutputStream JavaDoc;
31 import java.net.URI JavaDoc;
32 import java.net.URL JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Properties JavaDoc;
37 import java.util.zip.ZipEntry JavaDoc;
38 import java.util.zip.ZipInputStream JavaDoc;
39 import javax.management.MalformedObjectNameException JavaDoc;
40 import javax.management.ObjectName JavaDoc;
41
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.apache.geronimo.gbean.GBeanData;
45 import org.apache.geronimo.gbean.GBeanInfo;
46 import org.apache.geronimo.gbean.GBeanInfoBuilder;
47 import org.apache.geronimo.gbean.GBeanLifecycle;
48 import org.apache.geronimo.kernel.Kernel;
49 import org.apache.geronimo.kernel.management.State;
50 import org.apache.geronimo.kernel.config.Configuration;
51 import org.apache.geronimo.kernel.config.ConfigurationStore;
52 import org.apache.geronimo.kernel.config.InvalidConfigException;
53 import org.apache.geronimo.kernel.config.NoSuchConfigException;
54 import org.apache.geronimo.kernel.config.ConfigurationData;
55 import org.apache.geronimo.kernel.config.ConfigurationInfo;
56 import org.apache.geronimo.kernel.config.ConfigurationModuleType;
57 import org.apache.geronimo.system.serverinfo.ServerInfo;
58
59 /**
60  * Implementation of ConfigurationStore using the local filesystem.
61  *
62  * @version $Rev: 169154 $ $Date: 2005-05-08 12:35:23 -0700 (Sun, 08 May 2005) $
63  */

64 public class LocalConfigStore implements ConfigurationStore, GBeanLifecycle {
65     private static final String JavaDoc INDEX_NAME = "index.properties";
66     private static final String JavaDoc BACKUP_NAME = "index.backup";
67     private final Kernel kernel;
68     private final ObjectName JavaDoc objectName;
69     private final URI JavaDoc root;
70     private final ServerInfo serverInfo;
71     private final Properties JavaDoc index = new Properties JavaDoc();
72     private final Log log;
73     private File JavaDoc rootDir;
74     private int maxId;
75
76     /**
77      * Constructor is only used for direct testing with out a kernel.
78      */

79     public LocalConfigStore(File JavaDoc rootDir) {
80         kernel = null;
81         objectName = null;
82         serverInfo = null;
83         this.root = null;
84         this.rootDir = rootDir;
85         log = LogFactory.getLog("LocalConfigStore:"+rootDir.getName());
86     }
87
88     public LocalConfigStore(Kernel kernel, String JavaDoc objectName, URI JavaDoc root, ServerInfo serverInfo) throws MalformedObjectNameException JavaDoc {
89         this.kernel = kernel;
90         this.objectName = new ObjectName JavaDoc(objectName);
91         this.root = root;
92         this.serverInfo = serverInfo;
93         log = LogFactory.getLog("LocalConfigStore:"+root.toString());
94     }
95
96     public String JavaDoc getObjectName() {
97         return objectName.toString();
98     }
99
100     public synchronized void doStart() throws FileNotFoundException JavaDoc, IOException JavaDoc {
101         // resolve the root dir if not alredy resolved
102
if (rootDir == null) {
103             if (serverInfo == null) {
104                 rootDir = new File JavaDoc(root);
105             } else {
106                 rootDir = new File JavaDoc(serverInfo.resolve(root));
107             }
108             if (!rootDir.isDirectory()) {
109                 throw new FileNotFoundException JavaDoc("Store root does not exist or is not a directory: " + rootDir);
110             }
111         }
112
113         index.clear();
114         File JavaDoc indexfile = new File JavaDoc(rootDir, INDEX_NAME);
115         try {
116             index.load(new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(indexfile)));
117             for (Iterator JavaDoc i = index.values().iterator(); i.hasNext();) {
118                 String JavaDoc id = (String JavaDoc) i.next();
119                 maxId = Math.max(maxId, Integer.parseInt(id));
120             }
121         } catch (FileNotFoundException JavaDoc e) {
122             maxId = 0;
123         }
124     }
125
126     public void doStop() {
127     }
128
129     public void doFail() {
130     }
131
132     private void saveIndex() throws IOException JavaDoc {
133         // todo provide a backout mechanism
134
File JavaDoc indexFile = new File JavaDoc(rootDir, INDEX_NAME);
135         File JavaDoc backupFile = new File JavaDoc(rootDir, BACKUP_NAME);
136         if (backupFile.exists()) {
137             backupFile.delete();
138         }
139         indexFile.renameTo(backupFile);
140
141         FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(indexFile);
142         try {
143             BufferedOutputStream JavaDoc os = new BufferedOutputStream JavaDoc(fos);
144             index.store(os, null);
145             os.close();
146             fos = null;
147         } catch (IOException JavaDoc e) {
148             if (fos != null) {
149                 fos.close();
150             }
151             indexFile.delete();
152             backupFile.renameTo(indexFile);
153             throw e;
154         }
155     }
156
157     public File JavaDoc createNewConfigurationDir() {
158         // loop until we find a directory that doesn't alredy exist
159
// this can happen when a deployment fails (leaving an bad directory)
160
// and the server reboots without saving out the index.propreties file
161
// the is rare but we should check for it
162
File JavaDoc configurationDir;
163         do {
164             String JavaDoc newId;
165             synchronized (this) {
166                 newId = Integer.toString(++maxId);
167             }
168             configurationDir = new File JavaDoc(rootDir, newId);
169         } while (configurationDir.exists());
170         configurationDir.mkdir();
171         return configurationDir;
172     }
173
174     public URI JavaDoc install(URL JavaDoc source) throws IOException JavaDoc, InvalidConfigException {
175         File JavaDoc configurationDir = createNewConfigurationDir();
176
177         InputStream JavaDoc is = source.openStream();
178         try {
179             unpack(configurationDir, is);
180         } catch (IOException JavaDoc e) {
181             delete(configurationDir);
182             throw e;
183         } finally {
184             is.close();
185         }
186
187         URI JavaDoc configId;
188         try {
189             GBeanData config = loadConfig(configurationDir);
190             configId = (URI JavaDoc) config.getAttribute("id");
191             index.setProperty(configId.toString(), configurationDir.getName());
192         } catch (Exception JavaDoc e) {
193             delete(configurationDir);
194             throw new InvalidConfigException("Unable to get ID from downloaded configuration", e);
195         }
196
197         synchronized (this) {
198             saveIndex();
199         }
200
201         log.info("Installed configuration " + configId + " in location " + configurationDir.getName());
202         return configId;
203     }
204
205     public void install(ConfigurationData configurationData, File JavaDoc source) throws IOException JavaDoc, InvalidConfigException {
206         if (!source.isDirectory()) {
207             throw new InvalidConfigException("Source must be a directory: source=" + source);
208         }
209         if (!source.getParentFile().equals(rootDir)) {
210             throw new InvalidConfigException("Source must be within the config store: source=" + source + ", configStoreDir=" + rootDir);
211         }
212
213         ExecutableConfigurationUtil.writeConfiguration(configurationData, source);
214
215         // update the index
216
synchronized (this) {
217             index.setProperty(configurationData.getId().toString(), source.getName());
218             saveIndex();
219         }
220
221         log.info("Installed configuration " + configurationData.getId() + " in location " + source.getName());
222     }
223
224     public void uninstall(URI JavaDoc configID) throws NoSuchConfigException, IOException JavaDoc {
225         String JavaDoc id = configID.toString();
226         File JavaDoc configDir;
227         synchronized(this) {
228             String JavaDoc storeID = index.getProperty(id);
229             if (storeID == null) {
230                 throw new NoSuchConfigException();
231             }
232             configDir = new File JavaDoc(rootDir, storeID);
233             File JavaDoc tempDir = new File JavaDoc(rootDir, storeID + ".tmp");
234             if (configDir.renameTo(tempDir)) {
235                 configDir = tempDir;
236             }
237             index.remove(id);
238             saveIndex();
239         }
240         log.info("Uninstalled configuration " + configID);
241         delete(configDir);
242     }
243
244     public synchronized ObjectName JavaDoc loadConfiguration(URI JavaDoc configId) throws NoSuchConfigException, IOException JavaDoc, InvalidConfigException {
245         GBeanData config = loadConfig(getRoot(configId));
246
247         ObjectName JavaDoc name;
248         try {
249             name = Configuration.getConfigurationObjectName(configId);
250         } catch (MalformedObjectNameException JavaDoc e) {
251             throw new InvalidConfigException("Cannot convert id to ObjectName: ", e);
252         }
253         config.setName(name);
254
255         try {
256             kernel.loadGBean(config, Configuration.class.getClassLoader());
257         } catch (Exception JavaDoc e) {
258             throw new InvalidConfigException("Unable to register configuration", e);
259         }
260
261         try {
262             kernel.setAttribute(name, "baseURL", getRoot(configId).toURL());
263         } catch (Exception JavaDoc e) {
264             try {
265                 kernel.unloadGBean(name);
266             } catch (Exception JavaDoc ignored) {
267                 // ignore
268
}
269             throw new InvalidConfigException("Cannot set baseURL", e);
270         }
271         log.info("Loaded Configuration " + name);
272
273         return name;
274     }
275
276     public synchronized void updateConfiguration(ConfigurationData configurationData) throws NoSuchConfigException, Exception JavaDoc {
277         File JavaDoc root = getRoot(configurationData.getId());
278         File JavaDoc stateFile = new File JavaDoc(root, "META-INF/state.ser");
279         try {
280             FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(stateFile);
281             ObjectOutputStream JavaDoc oos;
282             try {
283                 oos = new ObjectOutputStream JavaDoc(fos);
284                 GBeanData configurationGBeanData = ExecutableConfigurationUtil.getConfigurationGBeanData(configurationData);
285                 configurationGBeanData.writeExternal(oos);
286                 oos.flush();
287             } finally {
288                 fos.close();
289             }
290         } catch (Exception JavaDoc e) {
291             log.error("state store failed", e);
292             stateFile.delete();
293             throw e;
294         }
295     }
296
297     public List JavaDoc listConfiguations() {
298         List JavaDoc configs;
299         synchronized (this) {
300             configs = new ArrayList JavaDoc(index.size());
301             for (Iterator JavaDoc i = index.keySet().iterator(); i.hasNext();) {
302                 URI JavaDoc configId = URI.create((String JavaDoc) i.next());
303                 try {
304                     ObjectName JavaDoc configName = Configuration.getConfigurationObjectName(configId);
305                     State state;
306                     if (kernel.isLoaded(configName)) {
307                         try {
308                             state = State.fromInt(kernel.getGBeanState(configName));
309                         } catch (Exception JavaDoc e) {
310                             state = null;
311                         }
312                     } else {
313                         // If the configuration is not loaded by the kernel
314
// and defined by the store, then it is stopped.
315
state = State.STOPPED;
316                     }
317
318                     GBeanData bean = loadConfig(getRoot(configId));
319                     ConfigurationModuleType type = (ConfigurationModuleType) bean.getAttribute("type");
320
321                     configs.add(new ConfigurationInfo(objectName, configId, state, type));
322                 } catch (Exception JavaDoc e) {
323                     // bad configuration in store - ignored for this purpose
324
log.info("Unable get configuration info for configuration " + configId, e);
325                 }
326             }
327         }
328         return configs;
329     }
330
331     public synchronized boolean containsConfiguration(URI JavaDoc configID) {
332         return index.getProperty(configID.toString()) != null;
333     }
334
335     private synchronized File JavaDoc getRoot(URI JavaDoc configID) throws NoSuchConfigException {
336         String JavaDoc id = index.getProperty(configID.toString());
337         if (id == null) {
338             throw new NoSuchConfigException("No such config: " + configID);
339         }
340         return new File JavaDoc(rootDir, id);
341     }
342
343     private GBeanData loadConfig(File JavaDoc configRoot) throws IOException JavaDoc, InvalidConfigException {
344         File JavaDoc file = new File JavaDoc(configRoot, "META-INF/state.ser");
345         if (!file.isFile()) {
346             file = new File JavaDoc(configRoot, "META-INF/config.ser");
347             if (!file.isFile()) {
348                 throw new InvalidConfigException("Configuration does not contain a META-INF/config.ser file");
349             }
350         }
351
352         FileInputStream JavaDoc fis = new FileInputStream JavaDoc(file);
353         try {
354             ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(new BufferedInputStream JavaDoc(fis));
355             GBeanData config = new GBeanData();
356             try {
357                 config.readExternal(ois);
358             } catch (ClassNotFoundException JavaDoc e) {
359                 //TODO more informative exceptions
360
throw new InvalidConfigException("Unable to read attribute ", e);
361             } catch (Exception JavaDoc e) {
362                 throw new InvalidConfigException("Unable to set attribute ", e);
363             }
364             config.setReferencePattern("ConfigurationStore", objectName);
365             return config;
366         } finally {
367             fis.close();
368         }
369     }
370
371     public static void unpack(File JavaDoc to, InputStream JavaDoc from) throws IOException JavaDoc {
372         ZipInputStream JavaDoc zis = new ZipInputStream JavaDoc(from);
373         try {
374             ZipEntry JavaDoc entry;
375             byte[] buffer = new byte[4096];
376             while ((entry = zis.getNextEntry()) != null) {
377                 File JavaDoc out = new File JavaDoc(to, entry.getName());
378                 if (entry.isDirectory()) {
379                     out.mkdirs();
380                 } else {
381                     if (!entry.getName().equals("META-INF/startup-jar")) {
382                         out.getParentFile().mkdirs();
383                         OutputStream JavaDoc os = new FileOutputStream JavaDoc(out);
384                         try {
385                             int count;
386                             while ((count = zis.read(buffer)) > 0) {
387                                 os.write(buffer, 0, count);
388                             }
389                         } finally {
390                             os.close();
391                         }
392                         zis.closeEntry();
393                     }
394                 }
395             }
396         } catch (IOException JavaDoc e) {
397             delete(to);
398             throw e;
399         }
400     }
401
402     private static void delete(File JavaDoc root) throws IOException JavaDoc {
403         File JavaDoc[] files = root.listFiles();
404         if ( null == files ) {
405             return;
406         }
407         for (int i = 0; i < files.length; i++) {
408             File JavaDoc file = files[i];
409             if (file.isDirectory()) {
410                 delete(file);
411             } else {
412                 if (!file.delete()) {
413                     file.deleteOnExit();
414                 };
415             }
416         }
417         root.delete();
418     }
419
420     public static final GBeanInfo GBEAN_INFO;
421
422     static {
423         GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(LocalConfigStore.class, "ConfigurationStore"); //NameFactory.CONFIGURATION_STORE
424

425         infoFactory.addAttribute("kernel", Kernel.class, false);
426         infoFactory.addAttribute("objectName", String JavaDoc.class, false);
427         infoFactory.addAttribute("root", URI JavaDoc.class, true);
428         infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
429         infoFactory.addInterface(ConfigurationStore.class);
430
431         infoFactory.setConstructor(new String JavaDoc[]{"kernel", "objectName", "root", "ServerInfo"});
432
433         GBEAN_INFO = infoFactory.getBeanInfo();
434     }
435
436     public static GBeanInfo getGBeanInfo() {
437         return GBEAN_INFO;
438     }
439 }
440
Popular Tags