KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. 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 package org.apache.geronimo.system.configuration;
18
19 import java.io.File JavaDoc;
20 import java.io.FileInputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.net.MalformedURLException JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.SortedSet JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.util.jar.JarFile JavaDoc;
31 import java.util.zip.ZipEntry JavaDoc;
32 import java.util.zip.ZipOutputStream JavaDoc;
33 import javax.management.ObjectName JavaDoc;
34
35 import org.apache.geronimo.gbean.AbstractName;
36 import org.apache.geronimo.gbean.GBeanInfo;
37 import org.apache.geronimo.gbean.GBeanInfoBuilder;
38 import org.apache.geronimo.kernel.Kernel;
39 import org.apache.geronimo.kernel.ObjectNameUtil;
40 import org.apache.geronimo.kernel.config.ConfigurationAlreadyExistsException;
41 import org.apache.geronimo.kernel.config.ConfigurationData;
42 import org.apache.geronimo.kernel.config.ConfigurationInfo;
43 import org.apache.geronimo.kernel.config.ConfigurationStore;
44 import org.apache.geronimo.kernel.config.ConfigurationUtil;
45 import org.apache.geronimo.kernel.config.InvalidConfigException;
46 import org.apache.geronimo.kernel.config.NoSuchConfigException;
47 import org.apache.geronimo.kernel.config.IOUtil;
48 import org.apache.geronimo.kernel.config.PersistentConfigurationList;
49 import org.apache.geronimo.kernel.repository.Artifact;
50 import org.apache.geronimo.kernel.repository.FileWriteMonitor;
51 import org.apache.geronimo.kernel.repository.WritableListableRepository;
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54
55 /**
56  * Implementation of ConfigurationStore GBean that installs/loads Configurations from a
57  * repository.
58  *
59  * @version $Rev: 486815 $ $Date: 2006-12-13 14:45:10 -0500 (Wed, 13 Dec 2006) $
60  */

61 public class RepositoryConfigurationStore implements ConfigurationStore {
62     private final static Log log = LogFactory.getLog(RepositoryConfigurationStore.class);
63     private final Kernel kernel;
64     private final ObjectName JavaDoc objectName;
65     protected final WritableListableRepository repository;
66     private final InPlaceConfigurationUtil inPlaceConfUtil;
67
68     public RepositoryConfigurationStore(WritableListableRepository repository) {
69         this(null, null, repository);
70     }
71
72     public RepositoryConfigurationStore(Kernel kernel, String JavaDoc objectName, WritableListableRepository repository) {
73         this.kernel = kernel;
74         this.objectName = objectName == null ? null : ObjectNameUtil.getObjectName(objectName);
75         this.repository = repository;
76
77         inPlaceConfUtil = new InPlaceConfigurationUtil();
78     }
79
80     public String JavaDoc getObjectName() {
81         return objectName.getCanonicalName();
82     }
83
84     public AbstractName getAbstractName() {
85         return kernel == null? null:kernel.getAbstractNameFor(this);
86     }
87
88     public ConfigurationData loadConfiguration(Artifact configId) throws NoSuchConfigException, IOException JavaDoc, InvalidConfigException {
89         if(!configId.isResolved()) {
90             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
91         }
92         File JavaDoc location = repository.getLocation(configId);
93
94         if (existsReadable(location)) {
95             throw new NoSuchConfigException(configId);
96         }
97
98         ConfigurationData configurationData;
99         try {
100             if (location.isDirectory()) {
101                 File JavaDoc serFile = new File JavaDoc(location, "META-INF");
102                 serFile = new File JavaDoc(serFile, "config.ser");
103
104                 if (!serFile.exists()) {
105                     throw new InvalidConfigException("Configuration does not contain a META-INF/config.ser file: " + serFile);
106                 } else if (!serFile.canRead()) {
107                     throw new InvalidConfigException("Can not read configuration META-INF/config.ser file: " + serFile);
108                 }
109
110                 ConfigurationStoreUtil.verifyChecksum(serFile);
111
112                 InputStream JavaDoc in = new FileInputStream JavaDoc(serFile);
113                 try {
114                     configurationData = ConfigurationUtil.readConfigurationData(in);
115                 } finally {
116                     IOUtil.close(in);
117                 }
118             } else {
119                 JarFile JavaDoc jarFile = new JarFile JavaDoc(location);
120                 InputStream JavaDoc in = null;
121                 try {
122                     ZipEntry JavaDoc entry = jarFile.getEntry("META-INF/config.ser");
123                     in = jarFile.getInputStream(entry);
124                     configurationData = ConfigurationUtil.readConfigurationData(in);
125                 } finally {
126                     IOUtil.close(in);
127                     IOUtil.close(jarFile);
128                 }
129             }
130         } catch (ClassNotFoundException JavaDoc e) {
131             throw new InvalidConfigException("Unable to load class from config: " + configId, e);
132         }
133
134         configurationData.setConfigurationDir(location);
135         configurationData.setConfigurationStore(this);
136         if (kernel != null) {
137             configurationData.setNaming(kernel.getNaming());
138         }
139
140         return configurationData;
141     }
142
143     private boolean existsReadable(File JavaDoc location) {
144         return !location.exists() || !location.canRead();
145     }
146
147     public boolean containsConfiguration(Artifact configId) {
148         if(!configId.isResolved()) {
149             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
150         }
151         File JavaDoc location = repository.getLocation(configId);
152         if (location.isDirectory()) {
153             location = new File JavaDoc(location, "META-INF");
154             location = new File JavaDoc(location, "config.ser");
155             return location.isFile() && location.canRead();
156         } else {
157             JarFile JavaDoc jarFile = null;
158             try {
159                 jarFile = new JarFile JavaDoc(location);
160                 ZipEntry JavaDoc entry = jarFile.getEntry("META-INF/config.ser");
161                 return entry != null && !entry.isDirectory();
162             } catch (IOException JavaDoc e) {
163                 return false;
164             } finally {
165                 IOUtil.close(jarFile);
166             }
167         }
168     }
169
170     public File JavaDoc createNewConfigurationDir(Artifact configId) throws ConfigurationAlreadyExistsException {
171         if(!configId.isResolved()) {
172             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
173         }
174         File JavaDoc location = repository.getLocation(configId);
175         if (location.exists()) {
176             throw new ConfigurationAlreadyExistsException("Configuration already exists: " + configId);
177         }
178         location.mkdirs();
179         if (!location.exists()) {
180             throw new ConfigurationAlreadyExistsException("Could not create configuration directory: " + location);
181         }
182         return location;
183     }
184
185     public Set JavaDoc resolve(Artifact configId, String JavaDoc moduleName, String JavaDoc path) throws NoSuchConfigException, MalformedURLException JavaDoc {
186         if(!configId.isResolved()) {
187             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
188         }
189         File JavaDoc location = repository.getLocation(configId);
190         if (location.isDirectory()) {
191             File JavaDoc inPlaceLocation = null;
192             try {
193                 inPlaceLocation = inPlaceConfUtil.readInPlaceLocation(location);
194             } catch (IOException JavaDoc e) {
195             }
196             if (null != inPlaceLocation) {
197                 location = inPlaceLocation;
198             }
199
200             if (moduleName != null) {
201                 location = new File JavaDoc(location, moduleName);
202             }
203
204             if (location.isDirectory()) {
205                 Set JavaDoc matches = IOUtil.search(location, path);
206                 return matches;
207             } else {
208                 Set JavaDoc matches = IOUtil.search(location, path);
209                 return matches;
210             }
211         } else {
212             Set JavaDoc matches = IOUtil.search(location, moduleName + "/" +path);
213             return matches;
214         }
215     }
216
217     public void exportConfiguration(Artifact configId, OutputStream JavaDoc output) throws IOException JavaDoc, NoSuchConfigException {
218         if(!configId.isResolved()) {
219             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
220         }
221         File JavaDoc dir = repository.getLocation(configId);
222         if (dir == null) {
223             throw new NoSuchConfigException(configId);
224         }
225         if (existsReadable(dir)) {
226             throw new IOException JavaDoc("Cannot read config store directory for " + configId + " (" + dir.getAbsolutePath() + ")");
227         }
228         ZipOutputStream JavaDoc out = new ZipOutputStream JavaDoc(output);
229         byte[] buf = new byte[10240];
230         writeToZip(dir, out, "", buf);
231         if (inPlaceConfUtil.isInPlaceConfiguration(dir)) {
232             dir = inPlaceConfUtil.readInPlaceLocation(dir);
233             writeToZip(dir, out, "", buf);
234         }
235         out.closeEntry();
236         out.finish();
237         out.flush();
238     }
239
240     private void writeToZip(File JavaDoc dir, ZipOutputStream JavaDoc out, String JavaDoc prefix, byte[] buf) throws IOException JavaDoc {
241         File JavaDoc[] all = dir.listFiles();
242         for (int i = 0; i < all.length; i++) {
243             File JavaDoc file = all[i];
244             if (file.isDirectory()) {
245                 writeToZip(file, out, prefix + file.getName() + "/", buf);
246             } else {
247                 ZipEntry JavaDoc entry = new ZipEntry JavaDoc(prefix + file.getName());
248                 out.putNextEntry(entry);
249                 writeToZipStream(file, out, buf);
250             }
251         }
252     }
253
254     private void writeToZipStream(File JavaDoc file, OutputStream JavaDoc out, byte[] buf) throws IOException JavaDoc {
255         FileInputStream JavaDoc in = new FileInputStream JavaDoc(file);
256         int count;
257         try {
258             while ((count = in.read(buf, 0, buf.length)) > -1) {
259                 out.write(buf, 0, count);
260             }
261         } finally {
262             in.close();
263         }
264     }
265
266     public void install(InputStream JavaDoc in, int size, Artifact configId, FileWriteMonitor fileWriteMonitor) throws IOException JavaDoc {
267         try {
268             repository.copyToRepository(in, size, configId, fileWriteMonitor);
269         } catch (IOException JavaDoc e) {
270             throw e;
271         } finally {
272             IOUtil.close(in);
273         }
274     }
275
276     public boolean isInPlaceConfiguration(Artifact configId) throws NoSuchConfigException, IOException JavaDoc {
277         if(!configId.isResolved()) {
278             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
279         }
280         File JavaDoc location = repository.getLocation(configId);
281         if (location.isDirectory()) {
282             return inPlaceConfUtil.isInPlaceConfiguration(location);
283         } else {
284             return false;
285         }
286     }
287
288     public void install(ConfigurationData configurationData) throws IOException JavaDoc, InvalidConfigException {
289         // determine the source file/dir
290
File JavaDoc source = configurationData.getConfigurationDir();
291         if (!source.exists()) {
292             throw new InvalidConfigException("Source does not exist " + source);
293         } else if (!source.canRead()) {
294             throw new InvalidConfigException("Source is not readable " + source);
295         }
296
297         // determine the target location
298
Artifact configId = configurationData.getId();
299         File JavaDoc destination = repository.getLocation(configId);
300
301         // if directory in the correct place -- noop
302
if (!source.equals(destination)) {
303             if (destination.exists()) {
304                 throw new ConfigurationAlreadyExistsException(configId.toString());
305             }
306
307             if (source.isFile()) {
308                 // Assume this is a jar file
309
// copy it into the repository; repository should unpack it
310
repository.copyToRepository(source, configId, null);
311             } else if (source.isDirectory()) {
312                 // directory is in wrong place -- directory copy
313
IOUtil.recursiveCopy(source, destination);
314             } else {
315                 throw new InvalidConfigException("Unable to install configuration from " + source);
316             }
317         }
318
319         ExecutableConfigurationUtil.writeConfiguration(configurationData, destination);
320
321         // write in-place configuration config file, if need be.
322
inPlaceConfUtil.writeInPlaceLocation(configurationData, destination);
323     }
324
325     public void uninstall(Artifact configId) throws NoSuchConfigException, IOException JavaDoc {
326         if(!configId.isResolved()) {
327             throw new IllegalArgumentException JavaDoc("Artifact "+configId+" is not fully resolved");
328         }
329         ConfigurationInfo configurationInfo = null;
330         try {
331             configurationInfo = loadConfigurationInfo(configId);
332         } catch (IOException JavaDoc e) {
333             // don't really care
334
}
335         File JavaDoc location = repository.getLocation(configId);
336         IOUtil.recursiveDelete(location);
337         // Number of directory levels up, to check and delete empty parent directories in the repo
338
int dirDepth = 0;
339
340         // FIXME: Determine the repository type
341
// For now assume the repo is a Maven2Repository. This should not cause any harm even if it is an
342
// Maven1Repository, for it would be deleting the 'repository' directory if it happens to be empty.
343
boolean m2repo = true;
344         if(m2repo) {
345             // Check version, artifact and group directories, i.e. 3 levels up
346
dirDepth = 3;
347         }
348
349         File JavaDoc temp = location;
350         for(int i = 0; i < dirDepth; ++i) {
351             if((temp = temp.getParentFile()).listFiles().length == 0) {
352                 // Directory is empty. Remove it.
353
temp.delete();
354             } else {
355                 // Directory is not empty. No need to check any more parent directories
356
break;
357             }
358         }
359
360         try {
361             // Is this the right way to get hold of PersistentConfigurationList?
362
PersistentConfigurationList configList = (PersistentConfigurationList) kernel.getGBean(PersistentConfigurationList.class);
363             if(!configList.hasGBeanAttributes(configId)) configList.removeConfiguration(configId);
364         } catch (Exception JavaDoc e) {
365             log.warn("Unable to remove configuration from persistent configurations. id = "+configId, e);
366         }
367
368         if (configurationInfo != null) {
369             IOException JavaDoc ioException = null;
370             for (Iterator JavaDoc iterator = configurationInfo.getOwnedConfigurations().iterator(); iterator.hasNext();) {
371                 Artifact ownedConfiguration = (Artifact) iterator.next();
372                 try {
373                     uninstall(ownedConfiguration);
374                 } catch (NoSuchConfigException e) {
375                     // ignored - already deleted or never installed
376
} catch (IOException JavaDoc e) {
377                     if (ioException != null) {
378                         ioException = e;
379                     }
380                 }
381                 if (ioException != null) {
382                     throw ioException;
383                 }
384             }
385         }
386     }
387
388     public List JavaDoc listConfigurations() {
389         SortedSet JavaDoc artifacts = repository.list();
390
391         List JavaDoc configs;
392         synchronized (this) {
393             configs = new ArrayList JavaDoc();
394             for (Iterator JavaDoc i = artifacts.iterator(); i.hasNext();) {
395                 Artifact configId = (Artifact) i.next();
396                 File JavaDoc dir = repository.getLocation(configId);
397                 File JavaDoc meta = new File JavaDoc(dir, "META-INF");
398                 if(!meta.isDirectory() || !meta.canRead()) {
399                     continue;
400                 }
401                 File JavaDoc ser = new File JavaDoc(meta, "config.ser");
402                 if(!ser.isFile() || !ser.canRead() || ser.length() == 0) {
403                     continue;
404                 }
405                 try {
406                     ConfigurationInfo configurationInfo = loadConfigurationInfo(configId);
407                     configs.add(configurationInfo);
408                 } catch (NoSuchConfigException e) {
409                     log.error("Unexpected error: found META-INF/config.ser for "+configId+" but couldn't load ConfigurationInfo", e);
410                 } catch (IOException JavaDoc e) {
411                     log.error("Unable to load ConfigurationInfo for "+configId, e);
412                 }
413             }
414         }
415         return configs;
416     }
417
418     private ConfigurationInfo loadConfigurationInfo(Artifact configId) throws NoSuchConfigException, IOException JavaDoc {
419         File JavaDoc location = repository.getLocation(configId);
420
421         if (!location.exists() && !location.canRead()) {
422             throw new NoSuchConfigException(configId);
423         }
424
425         File JavaDoc inPlaceLocation = inPlaceConfUtil.readInPlaceLocation(location);
426
427         ConfigurationInfo configurationInfo;
428         if (location.isDirectory()) {
429             File JavaDoc infoFile = new File JavaDoc(location, "META-INF");
430             infoFile = new File JavaDoc(infoFile, "config.info");
431
432             InputStream JavaDoc in = new FileInputStream JavaDoc(infoFile);
433             try {
434                 configurationInfo = ConfigurationUtil.readConfigurationInfo(in, getAbstractName(), inPlaceLocation);
435             } finally {
436                 IOUtil.close(in);
437             }
438         } else {
439             JarFile JavaDoc jarFile = new JarFile JavaDoc(location);
440             InputStream JavaDoc in = null;
441             try {
442                 ZipEntry JavaDoc entry = jarFile.getEntry("META-INF/config.info");
443                 in = jarFile.getInputStream(entry);
444                 configurationInfo = ConfigurationUtil.readConfigurationInfo(in, getAbstractName(), inPlaceLocation);
445             } finally {
446                 IOUtil.close(in);
447                 IOUtil.close(jarFile);
448             }
449         }
450
451         return configurationInfo;
452     }
453
454 // /**
455
// * Thread to cleanup unused Config Store entries.
456
// * On Windows, open files can't be deleted. Until MultiParentClassLoaders
457
// * are GC'ed, we won't be able to delete Config Store directories/files.
458
// */
459
// class ConfigStoreReaper implements Runnable {
460
// private final int reaperInterval;
461
// private volatile boolean done = false;
462
//
463
// public ConfigStoreReaper(int reaperInterval) {
464
// this.reaperInterval = reaperInterval;
465
// }
466
//
467
// public void close() {
468
// this.done = true;
469
// }
470
//
471
// public void run() {
472
// log.debug("ConfigStoreReaper started");
473
// while (!done) {
474
// try {
475
// Thread.sleep(reaperInterval);
476
// } catch (InterruptedException e) {
477
// continue;
478
// }
479
// reap();
480
// }
481
// }
482
//
483
// /**
484
// * For every directory in the pendingDeletionIndex, attempt to delete all
485
// * sub-directories and files.
486
// */
487
// public void reap() {
488
// // return, if there's nothing to do
489
// if (pendingDeletionIndex.size() == 0)
490
// return;
491
// // Otherwise, attempt to delete all of the directories
492
// Enumeration list = pendingDeletionIndex.propertyNames();
493
// boolean dirDeleted = false;
494
// while (list.hasMoreElements()) {
495
// String dirName = (String) list.nextElement();
496
// File deleteFile = new File(dirName);
497
// try {
498
// delete(deleteFile);
499
// }
500
// catch (IOException ioe) { // ignore errors
501
// }
502
// if (!deleteFile.exists()) {
503
// String configName = pendingDeletionIndex.getProperty(dirName);
504
// pendingDeletionIndex.remove(dirName);
505
// dirDeleted = true;
506
// log.debug("Reaped configuration " + configName + " in directory " + dirName);
507
// }
508
// }
509
// // If we deleted any directories, persist the list of directories to disk...
510
// if (dirDeleted) {
511
// try {
512
// synchronized (pendingDeletionIndex) {
513
// saveDeleteIndex();
514
// }
515
// }
516
// catch (IOException ioe) {
517
// log.warn("Error saving " + DELETE_NAME + " file.", ioe);
518
// }
519
// }
520
// }
521
// }
522
//
523
public static final GBeanInfo GBEAN_INFO;
524
525     public static GBeanInfo getGBeanInfo() {
526         return GBEAN_INFO;
527     }
528
529     static {
530         GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(RepositoryConfigurationStore.class, "ConfigurationStore");
531         builder.addAttribute("kernel", Kernel.class, false);
532         builder.addAttribute("objectName", String JavaDoc.class, false);
533         builder.addReference("Repository", WritableListableRepository.class, "Repository");
534         builder.setConstructor(new String JavaDoc[]{"kernel", "objectName", "Repository"});
535         GBEAN_INFO = builder.getBeanInfo();
536     }
537 }
538
Popular Tags