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