001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.system.configuration; 018 019 import java.io.File; 020 import java.io.FileInputStream; 021 import java.io.FileOutputStream; 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.io.OutputStream; 025 import java.io.OutputStreamWriter; 026 import java.io.PrintWriter; 027 import java.io.FileWriter; 028 import java.io.Writer; 029 import java.net.URI; 030 import java.util.Collection; 031 import java.util.Collections; 032 import java.util.Iterator; 033 import java.util.LinkedList; 034 import java.util.Arrays; 035 import java.util.jar.JarOutputStream; 036 import java.util.jar.Manifest; 037 import java.util.zip.ZipEntry; 038 039 import org.apache.geronimo.kernel.config.ConfigurationData; 040 import org.apache.geronimo.kernel.config.ConfigurationUtil; 041 042 /** 043 * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $ 044 */ 045 public final class ExecutableConfigurationUtil { 046 private static final String META_INF = "META-INF"; 047 private static final String CONFIG_SER = "config.ser"; 048 private static final String CONFIG_INFO = "config.info"; 049 private static final String META_INF_STARTUP_JAR = META_INF + "/startup-jar"; 050 private static final String META_INF_CONFIG_SER = META_INF + "/" + CONFIG_SER; 051 private static final String META_INF_CONFIG_SER_SHA1 = META_INF_CONFIG_SER + ".sha1"; 052 private static final String META_INF_CONFIG_INFO = META_INF + "/" + CONFIG_INFO; 053 054 private static final Collection EXCLUDED = Arrays.asList(new String[] {META_INF_STARTUP_JAR, META_INF_CONFIG_SER, META_INF_CONFIG_SER_SHA1, META_INF_CONFIG_INFO}); 055 056 private ExecutableConfigurationUtil() { 057 } 058 059 public static void createExecutableConfiguration(ConfigurationData configurationData, Manifest manifest, File destinationFile) throws IOException { 060 File configurationDir = configurationData.getConfigurationDir(); 061 062 // ensure parent directories have been created 063 File parent = destinationFile.getParentFile(); 064 if (parent != null && !parent.exists()) parent.mkdirs(); 065 066 FileOutputStream fos = null; 067 JarOutputStream out = null; 068 try { 069 byte[] buffer = new byte[4096]; 070 071 fos = new FileOutputStream(destinationFile, false); 072 073 if (manifest != null) { 074 out = new JarOutputStream(fos, manifest); 075 076 // add the startup file which allows us to locate the startup directory 077 out.putNextEntry(new ZipEntry(META_INF_STARTUP_JAR)); 078 // intentionally empty ZipEntry 079 out.closeEntry(); 080 } else { 081 out = new JarOutputStream(fos); 082 } 083 084 // write the configurationData 085 ExecutableConfigurationUtil.writeConfiguration(configurationData, out); 086 087 URI baseURI = configurationDir.getAbsoluteFile().toURI(); 088 Collection files = listRecursiveFiles(configurationDir); 089 for (Iterator iterator = files.iterator(); iterator.hasNext();) { 090 File file = (File) iterator.next(); 091 String relativePath = baseURI.relativize(file.toURI()).getPath(); 092 if (!EXCLUDED.contains(relativePath)) { 093 InputStream in = new FileInputStream(file); 094 try { 095 out.putNextEntry(new ZipEntry(relativePath)); 096 try { 097 int count; 098 while ((count = in.read(buffer)) > 0) { 099 out.write(buffer, 0, count); 100 } 101 } finally { 102 out.closeEntry(); 103 } 104 } finally { 105 close(in); 106 } 107 } 108 } 109 } finally { 110 close(out); 111 close(fos); // do this in case JarOutputStream contructor threw an exception 112 } 113 } 114 115 public static void writeConfiguration(ConfigurationData configurationData, JarOutputStream out) throws IOException { 116 // save the persisted form in the source directory 117 out.putNextEntry(new ZipEntry(META_INF_CONFIG_SER)); 118 ConfigurationStoreUtil.ChecksumOutputStream sumOut = null; 119 try { 120 sumOut = new ConfigurationStoreUtil.ChecksumOutputStream(out); 121 ConfigurationUtil.writeConfigurationData(configurationData, sumOut); 122 } finally { 123 out.closeEntry(); 124 } 125 126 // write the checksum file 127 out.putNextEntry(new ZipEntry(META_INF_CONFIG_SER_SHA1)); 128 try { 129 OutputStreamWriter writer = new OutputStreamWriter(out); 130 writer.write(sumOut.getChecksum()); 131 writer.flush(); 132 } finally { 133 out.closeEntry(); 134 } 135 136 // write the info file 137 out.putNextEntry(new ZipEntry(META_INF_CONFIG_INFO)); 138 try { 139 PrintWriter writer = new PrintWriter(new OutputStreamWriter(out)); 140 ConfigurationUtil.writeConfigInfo(writer, configurationData); 141 writer.flush(); 142 } finally { 143 out.closeEntry(); 144 } 145 } 146 147 public static void writeConfiguration(ConfigurationData configurationData, File source) throws IOException { 148 // save the persisted form in the source directory 149 File metaInf = new File(source, META_INF); 150 metaInf.mkdirs(); 151 File configSer = new File(metaInf, CONFIG_SER); 152 153 OutputStream out = new FileOutputStream(configSer); 154 try { 155 ConfigurationUtil.writeConfigurationData(configurationData, out); 156 } finally { 157 flush(out); 158 close(out); 159 } 160 161 // write the check sum file 162 ConfigurationStoreUtil.writeChecksumFor(configSer); 163 164 // write the info file 165 PrintWriter writer = null; 166 try { 167 writer = new PrintWriter(new FileWriter(new File(metaInf, CONFIG_INFO))); 168 ConfigurationUtil.writeConfigInfo(writer, configurationData); 169 } finally { 170 flush(writer); 171 close(writer); 172 } 173 } 174 175 private static Collection listRecursiveFiles(File file) { 176 LinkedList list = new LinkedList(); 177 listRecursiveFiles(file, list); 178 return Collections.unmodifiableCollection(list); 179 } 180 181 private static void listRecursiveFiles(File file, Collection collection) { 182 File[] files = file.listFiles(); 183 if (null == files) { 184 return; 185 } 186 for (int i = 0; i < files.length; i++) { 187 if (files[i].isDirectory()) { 188 listRecursiveFiles(files[i], collection); 189 } else { 190 collection.add(files[i]); 191 } 192 } 193 } 194 195 private static void flush(OutputStream thing) { 196 if (thing != null) { 197 try { 198 thing.flush(); 199 } catch (Exception ignored) { 200 } 201 } 202 } 203 204 private static void flush(Writer thing) { 205 if (thing != null) { 206 try { 207 thing.flush(); 208 } catch (Exception ignored) { 209 } 210 } 211 } 212 213 private static void close(InputStream thing) { 214 if (thing != null) { 215 try { 216 thing.close(); 217 } catch (Exception ignored) { 218 } 219 } 220 } 221 222 private static void close(OutputStream thing) { 223 if (thing != null) { 224 try { 225 thing.close(); 226 } catch (Exception ignored) { 227 } 228 } 229 } 230 231 private static void close(Writer thing) { 232 if (thing != null) { 233 try { 234 thing.close(); 235 } catch (Exception ignored) { 236 } 237 } 238 } 239 }