001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu, jcarsique 018 */ 019package org.nuxeo.runtime.deployment.preprocessor; 020 021import java.io.File; 022import java.io.FileInputStream; 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.Collection; 026 027import javax.xml.parsers.DocumentBuilder; 028import javax.xml.parsers.DocumentBuilderFactory; 029import javax.xml.parsers.ParserConfigurationException; 030 031import org.apache.commons.io.FileUtils; 032import org.apache.commons.lang.StringUtils; 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.nuxeo.common.utils.ZipUtils; 036import org.nuxeo.launcher.config.ConfigurationException; 037import org.nuxeo.launcher.config.ConfigurationGenerator; 038import org.w3c.dom.Document; 039import org.w3c.dom.Element; 040import org.w3c.dom.Node; 041import org.w3c.dom.NodeList; 042import org.xml.sax.SAXException; 043 044/** 045 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 046 */ 047public class PackZip { 048 049 private static Log log = LogFactory.getLog(PackZip.class); 050 051 public static final String ORDER_PREPROCESSING = "preprocessing"; 052 053 public static final String ORDER_PACKAGING = "packaging"; 054 055 protected File nuxeoEar; 056 057 protected File deployerJar; 058 059 protected File deployDir; 060 061 protected File jbossLib; 062 063 protected File dsFile; 064 065 protected File target; 066 067 public PackZip(File nuxeoEar, File target) { 068 if (!nuxeoEar.isDirectory()) { 069 throw new IllegalArgumentException("Invalid build - no exploded nuxeo.ear found at " 070 + nuxeoEar.getAbsolutePath()); 071 } 072 if (!target.isDirectory()) { 073 throw new IllegalArgumentException("Invalid configuration - no target directory found at " 074 + nuxeoEar.getAbsolutePath()); 075 } 076 this.nuxeoEar = nuxeoEar; 077 this.target = target; 078 this.deployDir = nuxeoEar.getParentFile(); 079 this.jbossLib = new File(deployDir.getParentFile(), "lib"); 080 this.dsFile = new File(deployDir, "nuxeo-ds.xml"); 081 File deployers = new File(deployDir.getParentFile(), "deployers"); 082 String[] names = deployers.list(); 083 if (names == null) { 084 throw new IllegalArgumentException( 085 "Invalid nuxeo.ear location - no nuxeo jboss deployer JAR found in deployers directory"); 086 } 087 for (String name : names) { 088 if (name.startsWith("nuxeo-jboss-deployer") && name.endsWith(".jar")) { 089 deployerJar = new File(deployers, name); 090 } 091 } 092 if (deployerJar == null) { 093 throw new IllegalArgumentException( 094 "Invalid build - no nuxeo jboss deployer JAR found in deployers directory"); 095 } 096 } 097 098 protected void executePreprocessing() throws ConfigurationException, IOException { 099 // configure from templates 100 new ConfigurationGenerator().run(); 101 // run preprocessor 102 runPreprocessor(); 103 } 104 105 protected void executePackaging() throws IOException, SAXException, ParserConfigurationException { 106 // move non ejb jars to nuxeo.ear/lib 107 moveNonEjbsToLib(nuxeoEar); 108 // replace nuxeo-structure.xml with nuxeo-structure-zip.xml 109 replaceStructureFile(); 110 // move libs in jboss/lib to nuxeo.ear/lib 111 moveJarsFromJbossLib(); 112 // move nuxeo jboss deployer to nuxeo.ear/lib 113 FileUtils.moveFile(deployerJar, new File(nuxeoEar, "lib" + File.separator + deployerJar.getName())); 114 // zip the ear into target directory 115 ZipUtils.zip(nuxeoEar.listFiles(), new File(target, "nuxeo.ear")); 116 // copy nuxeo-ds.xml to target dir 117 FileUtils.copyFileToDirectory(dsFile, target); 118 } 119 120 public void execute(String order) throws ConfigurationException, IOException, ParserConfigurationException, 121 SAXException { 122 if (ORDER_PREPROCESSING.equals(order) || StringUtils.isBlank(order)) { 123 executePreprocessing(); 124 } 125 if (ORDER_PACKAGING.equals(order) || StringUtils.isBlank(order)) { 126 executePackaging(); 127 } 128 if (!(ORDER_PREPROCESSING.equals(order) || StringUtils.isBlank(order) || ORDER_PACKAGING.equals(order))) { 129 fail("Order param should be " + ORDER_PREPROCESSING + " or " + ORDER_PACKAGING); 130 } 131 } 132 133 protected void runPreprocessor() throws IOException { 134 DeploymentPreprocessor.main(new String[] { nuxeoEar.getAbsolutePath() }); 135 } 136 137 protected void replaceStructureFile() throws IOException { 138 File oldf = new File(nuxeoEar, "META-INF" + File.separator + "nuxeo-structure.xml"); 139 File newf = new File(nuxeoEar, "META-INF" + File.separator + "nuxeo-structure-zip.xml"); 140 if (oldf.exists() && !FileUtils.deleteQuietly(oldf)) { 141 log.warn("Cannot delete " + oldf.getName() + ", it may not replace it with the new file."); 142 } 143 FileUtils.moveFile(newf, oldf); 144 } 145 146 protected void moveJarsFromJbossLib() { 147 } 148 149 protected void moveNonEjbsToLib(File wd) throws ParserConfigurationException, SAXException, IOException { 150 File file = new File(wd, "META-INF" + File.separator + "application.xml"); 151 if (!file.isFile()) { 152 log.error("You should run this tool from a preprocessed nuxeo.ear folder"); 153 } 154 DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 155 FileInputStream in = new FileInputStream(file); 156 Document doc = docBuilder.parse(in); 157 Element root = doc.getDocumentElement(); 158 NodeList list = root.getElementsByTagName("module"); 159 Collection<String> paths = new ArrayList<String>(); 160 for (int i = 0; i < list.getLength(); i++) { 161 Element el = (Element) list.item(i); 162 Node n = el.getFirstChild(); 163 while (n != null) { 164 if (n.getNodeType() == Node.ELEMENT_NODE) { 165 Element mtype = ((Element) n); 166 String type = n.getNodeName().toLowerCase(); 167 if (!"web".equals(type)) { 168 String path = mtype.getTextContent().trim(); 169 paths.add(path); 170 } 171 } 172 n = n.getNextSibling(); 173 } 174 } 175 176 File ejbs = new File(wd, "tmp-ejbs"); 177 ejbs.mkdirs(); 178 for (String path : paths) { 179 log.info("Move EAR module " + path + " to " + ejbs.getName()); 180 File f = new File(wd, path); 181 if (f.getName().endsWith(".txt")) { 182 continue; 183 } 184 FileUtils.moveToDirectory(f, ejbs, false); 185 } 186 File lib = new File(wd, "lib"); 187 File[] files = new File(wd, "bundles").listFiles(); 188 if (files != null) { 189 for (File f : files) { 190 if (f.getName().endsWith(".txt")) { 191 continue; 192 } 193 log.info("Move POJO bundle " + f.getName() + " to lib"); 194 FileUtils.moveToDirectory(f, lib, false); 195 } 196 } 197 File bundles = new File(wd, "bundles"); 198 files = ejbs.listFiles(); 199 if (files != null) { 200 for (File f : files) { 201 if (f.getName().endsWith(".txt")) { 202 continue; 203 } 204 log.info("Move back EAR module " + f.getName() + " to bundles"); 205 FileUtils.moveToDirectory(f, bundles, false); 206 } 207 } 208 } 209 210 protected static void fail(String message) { 211 log.error(message); 212 System.exit(1); 213 } 214 215 public static void main(String[] args) throws IOException, ConfigurationException, ParserConfigurationException, 216 SAXException { 217 if (args.length < 2) { 218 fail("Usage: PackZip nuxeo_ear_directory target_directory [order]"); 219 } 220 String v = args[0]; 221 File ear = new File(v); 222 if (!ear.isDirectory()) { 223 fail("Invalid build - no exploded nuxeo.ear found at " + ear.getAbsolutePath()); 224 } 225 v = args[1]; 226 File target = new File(v); 227 ear = ear.getCanonicalFile(); 228 target = target.getCanonicalFile(); 229 if (target.exists()) { 230 FileUtils.deleteDirectory(target); 231 } 232 target.mkdirs(); 233 if (!target.isDirectory()) { 234 fail("Invalid target directory: " + v + ". Not a directory or directory could not be created"); 235 } 236 237 log.info("Packing nuxeo.ear at " + ear.getAbsolutePath() + " into " + target.getAbsolutePath()); 238 239 PackZip pack = new PackZip(ear, target); 240 if (args.length >= 3) { 241 pack.execute(args[2]); 242 } else { 243 pack.execute(null); 244 } 245 } 246}