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