1 17 package org.apache.geronimo.system.configuration; 18 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.OutputStream ; 24 import java.net.MalformedURLException ; 25 import java.util.ArrayList ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.SortedSet ; 29 import java.util.Set ; 30 import java.util.jar.JarFile ; 31 import java.util.zip.ZipEntry ; 32 import java.util.zip.ZipOutputStream ; 33 import javax.management.ObjectName ; 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 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 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 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 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 , InvalidConfigException { 89 if(!configId.isResolved()) { 90 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 91 } 92 File 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 serFile = new File (location, "META-INF"); 102 serFile = new File (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 in = new FileInputStream (serFile); 113 try { 114 configurationData = ConfigurationUtil.readConfigurationData(in); 115 } finally { 116 IOUtil.close(in); 117 } 118 } else { 119 JarFile jarFile = new JarFile (location); 120 InputStream in = null; 121 try { 122 ZipEntry 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 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 location) { 144 return !location.exists() || !location.canRead(); 145 } 146 147 public boolean containsConfiguration(Artifact configId) { 148 if(!configId.isResolved()) { 149 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 150 } 151 File location = repository.getLocation(configId); 152 if (location.isDirectory()) { 153 location = new File (location, "META-INF"); 154 location = new File (location, "config.ser"); 155 return location.isFile() && location.canRead(); 156 } else { 157 JarFile jarFile = null; 158 try { 159 jarFile = new JarFile (location); 160 ZipEntry entry = jarFile.getEntry("META-INF/config.ser"); 161 return entry != null && !entry.isDirectory(); 162 } catch (IOException e) { 163 return false; 164 } finally { 165 IOUtil.close(jarFile); 166 } 167 } 168 } 169 170 public File createNewConfigurationDir(Artifact configId) throws ConfigurationAlreadyExistsException { 171 if(!configId.isResolved()) { 172 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 173 } 174 File 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 resolve(Artifact configId, String moduleName, String path) throws NoSuchConfigException, MalformedURLException { 186 if(!configId.isResolved()) { 187 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 188 } 189 File location = repository.getLocation(configId); 190 if (location.isDirectory()) { 191 File inPlaceLocation = null; 192 try { 193 inPlaceLocation = inPlaceConfUtil.readInPlaceLocation(location); 194 } catch (IOException e) { 195 } 196 if (null != inPlaceLocation) { 197 location = inPlaceLocation; 198 } 199 200 if (moduleName != null) { 201 location = new File (location, moduleName); 202 } 203 204 if (location.isDirectory()) { 205 Set matches = IOUtil.search(location, path); 206 return matches; 207 } else { 208 Set matches = IOUtil.search(location, path); 209 return matches; 210 } 211 } else { 212 Set matches = IOUtil.search(location, moduleName + "/" +path); 213 return matches; 214 } 215 } 216 217 public void exportConfiguration(Artifact configId, OutputStream output) throws IOException , NoSuchConfigException { 218 if(!configId.isResolved()) { 219 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 220 } 221 File dir = repository.getLocation(configId); 222 if (dir == null) { 223 throw new NoSuchConfigException(configId); 224 } 225 if (existsReadable(dir)) { 226 throw new IOException ("Cannot read config store directory for " + configId + " (" + dir.getAbsolutePath() + ")"); 227 } 228 ZipOutputStream out = new ZipOutputStream (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 dir, ZipOutputStream out, String prefix, byte[] buf) throws IOException { 241 File [] all = dir.listFiles(); 242 for (int i = 0; i < all.length; i++) { 243 File file = all[i]; 244 if (file.isDirectory()) { 245 writeToZip(file, out, prefix + file.getName() + "/", buf); 246 } else { 247 ZipEntry entry = new ZipEntry (prefix + file.getName()); 248 out.putNextEntry(entry); 249 writeToZipStream(file, out, buf); 250 } 251 } 252 } 253 254 private void writeToZipStream(File file, OutputStream out, byte[] buf) throws IOException { 255 FileInputStream in = new FileInputStream (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 in, int size, Artifact configId, FileWriteMonitor fileWriteMonitor) throws IOException { 267 try { 268 repository.copyToRepository(in, size, configId, fileWriteMonitor); 269 } catch (IOException e) { 270 throw e; 271 } finally { 272 IOUtil.close(in); 273 } 274 } 275 276 public boolean isInPlaceConfiguration(Artifact configId) throws NoSuchConfigException, IOException { 277 if(!configId.isResolved()) { 278 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 279 } 280 File 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 , InvalidConfigException { 289 File 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 Artifact configId = configurationData.getId(); 299 File destination = repository.getLocation(configId); 300 301 if (!source.equals(destination)) { 303 if (destination.exists()) { 304 throw new ConfigurationAlreadyExistsException(configId.toString()); 305 } 306 307 if (source.isFile()) { 308 repository.copyToRepository(source, configId, null); 311 } else if (source.isDirectory()) { 312 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 inPlaceConfUtil.writeInPlaceLocation(configurationData, destination); 323 } 324 325 public void uninstall(Artifact configId) throws NoSuchConfigException, IOException { 326 if(!configId.isResolved()) { 327 throw new IllegalArgumentException ("Artifact "+configId+" is not fully resolved"); 328 } 329 ConfigurationInfo configurationInfo = null; 330 try { 331 configurationInfo = loadConfigurationInfo(configId); 332 } catch (IOException e) { 333 } 335 File location = repository.getLocation(configId); 336 IOUtil.recursiveDelete(location); 337 int dirDepth = 0; 339 340 boolean m2repo = true; 344 if(m2repo) { 345 dirDepth = 3; 347 } 348 349 File temp = location; 350 for(int i = 0; i < dirDepth; ++i) { 351 if((temp = temp.getParentFile()).listFiles().length == 0) { 352 temp.delete(); 354 } else { 355 break; 357 } 358 } 359 360 try { 361 PersistentConfigurationList configList = (PersistentConfigurationList) kernel.getGBean(PersistentConfigurationList.class); 363 if(!configList.hasGBeanAttributes(configId)) configList.removeConfiguration(configId); 364 } catch (Exception e) { 365 log.warn("Unable to remove configuration from persistent configurations. id = "+configId, e); 366 } 367 368 if (configurationInfo != null) { 369 IOException ioException = null; 370 for (Iterator iterator = configurationInfo.getOwnedConfigurations().iterator(); iterator.hasNext();) { 371 Artifact ownedConfiguration = (Artifact) iterator.next(); 372 try { 373 uninstall(ownedConfiguration); 374 } catch (NoSuchConfigException e) { 375 } catch (IOException 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 listConfigurations() { 389 SortedSet artifacts = repository.list(); 390 391 List configs; 392 synchronized (this) { 393 configs = new ArrayList (); 394 for (Iterator i = artifacts.iterator(); i.hasNext();) { 395 Artifact configId = (Artifact) i.next(); 396 File dir = repository.getLocation(configId); 397 File meta = new File (dir, "META-INF"); 398 if(!meta.isDirectory() || !meta.canRead()) { 399 continue; 400 } 401 File ser = new File (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 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 { 419 File location = repository.getLocation(configId); 420 421 if (!location.exists() && !location.canRead()) { 422 throw new NoSuchConfigException(configId); 423 } 424 425 File inPlaceLocation = inPlaceConfUtil.readInPlaceLocation(location); 426 427 ConfigurationInfo configurationInfo; 428 if (location.isDirectory()) { 429 File infoFile = new File (location, "META-INF"); 430 infoFile = new File (infoFile, "config.info"); 431 432 InputStream in = new FileInputStream (infoFile); 433 try { 434 configurationInfo = ConfigurationUtil.readConfigurationInfo(in, getAbstractName(), inPlaceLocation); 435 } finally { 436 IOUtil.close(in); 437 } 438 } else { 439 JarFile jarFile = new JarFile (location); 440 InputStream in = null; 441 try { 442 ZipEntry 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 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 .class, false); 533 builder.addReference("Repository", WritableListableRepository.class, "Repository"); 534 builder.setConstructor(new String []{"kernel", "objectName", "Repository"}); 535 GBEAN_INFO = builder.getBeanInfo(); 536 } 537 } 538 | Popular Tags |