1 17 18 package org.apache.geronimo.system.configuration; 19 20 import java.io.BufferedInputStream ; 21 import java.io.BufferedOutputStream ; 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.ObjectInputStream ; 29 import java.io.ObjectOutputStream ; 30 import java.io.OutputStream ; 31 import java.net.URI ; 32 import java.net.URL ; 33 import java.util.ArrayList ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Properties ; 37 import java.util.zip.ZipEntry ; 38 import java.util.zip.ZipInputStream ; 39 import javax.management.MalformedObjectNameException ; 40 import javax.management.ObjectName ; 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 64 public class LocalConfigStore implements ConfigurationStore, GBeanLifecycle { 65 private static final String INDEX_NAME = "index.properties"; 66 private static final String BACKUP_NAME = "index.backup"; 67 private final Kernel kernel; 68 private final ObjectName objectName; 69 private final URI root; 70 private final ServerInfo serverInfo; 71 private final Properties index = new Properties (); 72 private final Log log; 73 private File rootDir; 74 private int maxId; 75 76 79 public LocalConfigStore(File 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 objectName, URI root, ServerInfo serverInfo) throws MalformedObjectNameException { 89 this.kernel = kernel; 90 this.objectName = new ObjectName (objectName); 91 this.root = root; 92 this.serverInfo = serverInfo; 93 log = LogFactory.getLog("LocalConfigStore:"+root.toString()); 94 } 95 96 public String getObjectName() { 97 return objectName.toString(); 98 } 99 100 public synchronized void doStart() throws FileNotFoundException , IOException { 101 if (rootDir == null) { 103 if (serverInfo == null) { 104 rootDir = new File (root); 105 } else { 106 rootDir = new File (serverInfo.resolve(root)); 107 } 108 if (!rootDir.isDirectory()) { 109 throw new FileNotFoundException ("Store root does not exist or is not a directory: " + rootDir); 110 } 111 } 112 113 index.clear(); 114 File indexfile = new File (rootDir, INDEX_NAME); 115 try { 116 index.load(new BufferedInputStream (new FileInputStream (indexfile))); 117 for (Iterator i = index.values().iterator(); i.hasNext();) { 118 String id = (String ) i.next(); 119 maxId = Math.max(maxId, Integer.parseInt(id)); 120 } 121 } catch (FileNotFoundException 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 { 133 File indexFile = new File (rootDir, INDEX_NAME); 135 File backupFile = new File (rootDir, BACKUP_NAME); 136 if (backupFile.exists()) { 137 backupFile.delete(); 138 } 139 indexFile.renameTo(backupFile); 140 141 FileOutputStream fos = new FileOutputStream (indexFile); 142 try { 143 BufferedOutputStream os = new BufferedOutputStream (fos); 144 index.store(os, null); 145 os.close(); 146 fos = null; 147 } catch (IOException 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 createNewConfigurationDir() { 158 File configurationDir; 163 do { 164 String newId; 165 synchronized (this) { 166 newId = Integer.toString(++maxId); 167 } 168 configurationDir = new File (rootDir, newId); 169 } while (configurationDir.exists()); 170 configurationDir.mkdir(); 171 return configurationDir; 172 } 173 174 public URI install(URL source) throws IOException , InvalidConfigException { 175 File configurationDir = createNewConfigurationDir(); 176 177 InputStream is = source.openStream(); 178 try { 179 unpack(configurationDir, is); 180 } catch (IOException e) { 181 delete(configurationDir); 182 throw e; 183 } finally { 184 is.close(); 185 } 186 187 URI configId; 188 try { 189 GBeanData config = loadConfig(configurationDir); 190 configId = (URI ) config.getAttribute("id"); 191 index.setProperty(configId.toString(), configurationDir.getName()); 192 } catch (Exception 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 source) throws IOException , 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 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 configID) throws NoSuchConfigException, IOException { 225 String id = configID.toString(); 226 File configDir; 227 synchronized(this) { 228 String storeID = index.getProperty(id); 229 if (storeID == null) { 230 throw new NoSuchConfigException(); 231 } 232 configDir = new File (rootDir, storeID); 233 File tempDir = new File (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 loadConfiguration(URI configId) throws NoSuchConfigException, IOException , InvalidConfigException { 245 GBeanData config = loadConfig(getRoot(configId)); 246 247 ObjectName name; 248 try { 249 name = Configuration.getConfigurationObjectName(configId); 250 } catch (MalformedObjectNameException 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 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 e) { 264 try { 265 kernel.unloadGBean(name); 266 } catch (Exception ignored) { 267 } 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 { 277 File root = getRoot(configurationData.getId()); 278 File stateFile = new File (root, "META-INF/state.ser"); 279 try { 280 FileOutputStream fos = new FileOutputStream (stateFile); 281 ObjectOutputStream oos; 282 try { 283 oos = new ObjectOutputStream (fos); 284 GBeanData configurationGBeanData = ExecutableConfigurationUtil.getConfigurationGBeanData(configurationData); 285 configurationGBeanData.writeExternal(oos); 286 oos.flush(); 287 } finally { 288 fos.close(); 289 } 290 } catch (Exception e) { 291 log.error("state store failed", e); 292 stateFile.delete(); 293 throw e; 294 } 295 } 296 297 public List listConfiguations() { 298 List configs; 299 synchronized (this) { 300 configs = new ArrayList (index.size()); 301 for (Iterator i = index.keySet().iterator(); i.hasNext();) { 302 URI configId = URI.create((String ) i.next()); 303 try { 304 ObjectName configName = Configuration.getConfigurationObjectName(configId); 305 State state; 306 if (kernel.isLoaded(configName)) { 307 try { 308 state = State.fromInt(kernel.getGBeanState(configName)); 309 } catch (Exception e) { 310 state = null; 311 } 312 } else { 313 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 e) { 323 log.info("Unable get configuration info for configuration " + configId, e); 325 } 326 } 327 } 328 return configs; 329 } 330 331 public synchronized boolean containsConfiguration(URI configID) { 332 return index.getProperty(configID.toString()) != null; 333 } 334 335 private synchronized File getRoot(URI configID) throws NoSuchConfigException { 336 String id = index.getProperty(configID.toString()); 337 if (id == null) { 338 throw new NoSuchConfigException("No such config: " + configID); 339 } 340 return new File (rootDir, id); 341 } 342 343 private GBeanData loadConfig(File configRoot) throws IOException , InvalidConfigException { 344 File file = new File (configRoot, "META-INF/state.ser"); 345 if (!file.isFile()) { 346 file = new File (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 fis = new FileInputStream (file); 353 try { 354 ObjectInputStream ois = new ObjectInputStream (new BufferedInputStream (fis)); 355 GBeanData config = new GBeanData(); 356 try { 357 config.readExternal(ois); 358 } catch (ClassNotFoundException e) { 359 throw new InvalidConfigException("Unable to read attribute ", e); 361 } catch (Exception 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 to, InputStream from) throws IOException { 372 ZipInputStream zis = new ZipInputStream (from); 373 try { 374 ZipEntry entry; 375 byte[] buffer = new byte[4096]; 376 while ((entry = zis.getNextEntry()) != null) { 377 File out = new File (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 os = new FileOutputStream (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 e) { 397 delete(to); 398 throw e; 399 } 400 } 401 402 private static void delete(File root) throws IOException { 403 File [] files = root.listFiles(); 404 if ( null == files ) { 405 return; 406 } 407 for (int i = 0; i < files.length; i++) { 408 File 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"); 425 infoFactory.addAttribute("kernel", Kernel.class, false); 426 infoFactory.addAttribute("objectName", String .class, false); 427 infoFactory.addAttribute("root", URI .class, true); 428 infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean"); 429 infoFactory.addInterface(ConfigurationStore.class); 430 431 infoFactory.setConstructor(new String []{"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 |