![JAR search and dependency download from the Maven repository](/logo.png)
org.simplericity.jettyconsole.creator.DefaultCreator Maven / Gradle / Ivy
package org.simplericity.jettyconsole.creator;
import org.apache.commons.io.IOUtils;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.taskdefs.Manifest;
import org.apache.tools.ant.taskdefs.ManifestException;
import org.apache.tools.ant.types.FileSet;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* Created by IntelliJ IDEA. User: bjorsnos Date: Dec 28, 2008 Time: 12:40:54 AM To change this template use File | Settings | File Templates.
*/
public class DefaultCreator implements Creator {
private File workingDirectory;
private File sourceWar;
private File sourceWarDirectory;
private URL backgroundImage;
private File destinationWar;
private String consoleDirectory = "META-INF/jettyconsole";
private String name;
private List additionalDependencies;
private static final String NOT_FOUND_FILTER_CLASSFILE = "org/simplericity/jettyconsole/filter/NotFoundFilter.class";
private static final String NOT_FOUND_FILTER_CLASSNAME = NOT_FOUND_FILTER_CLASSFILE.replace('/', '.').substring(0, NOT_FOUND_FILTER_CLASSFILE.lastIndexOf("."));
private static final String MAIN_CLASS = "JettyConsoleBootstrapMainClass";
private URL coreDependencyUrl;
private String properties;
private Map manifestEntries;
public void setWorkingDirectory(File workingDirectory) {
this.workingDirectory = workingDirectory;
}
public void setSourceWar(File file) {
this.sourceWar = file;
}
public void setBackgroundImage(URL url) {
this.backgroundImage = url;
}
public void setDestinationWar(File destinationFile) {
this.destinationWar = destinationFile;
}
public void setSourceWarDirectory(File sourceWarDirectory) {
this.sourceWarDirectory = sourceWarDirectory;
}
public void setName(String name) {
this.name = name;
}
public void setCoreDependency(URL coreDependencyUrl) {
this.coreDependencyUrl = coreDependencyUrl;
}
public void setProperties(String properties) {
this.properties = properties;
}
public void setManifestEntries(Map manifestEntries) {
this.manifestEntries = manifestEntries;
}
public void setAdditionalDependecies(List additionalDependencies) {
this.additionalDependencies = additionalDependencies;
}
public void create() throws CreatorExecutionException {
// Make sure the working directory exists
workingDirectory.mkdirs();
File consoleDir = new File(workingDirectory, consoleDirectory);
consoleDir.mkdirs();
//
// We assume here that the user already has an exploded WAR structure. In my particular case I am using
// the maven-dependency-plugin to retrieve a runtime bundle that embeds a WAR that I want to pull out, augment
// with a console and deploy.
//
if (sourceWarDirectory != null) {
workingDirectory = sourceWarDirectory;
} else {
extractWar(sourceWar);
}
copyBackgroundImage();
writePathDescriptor(consoleDir, copyAdditionalDependencies());
writeDescriptor(consoleDir);
rewriteWebXml();
packageConsole();
}
/**
* Write a txt file with one line for each unpacked class or resource from dependencies.
*/
private void writePathDescriptor(File consoleDir, Set paths) {
try {
PrintWriter writer = new PrintWriter(new FileOutputStream(new File(consoleDir, "jettyconsolepaths.txt")));
for (String path : paths) {
writer.println(path);
}
writer.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
private void packageConsole() throws CreatorExecutionException {
try {
Jar jarArchiver = new Jar();
jarArchiver.setProject(new Project());
jarArchiver.setDestFile(destinationWar);
final FileSet fileSet = new FileSet();
fileSet.setDir(workingDirectory);
jarArchiver.addFileset(fileSet);
jarArchiver.addConfiguredManifest(createManifest());
jarArchiver.execute();
} catch (ManifestException e) {
throw new CreatorExecutionException(e.getMessage(), e);
}
}
private Manifest createManifest() throws ManifestException {
Manifest manifest = new Manifest();
manifest.addConfiguredAttribute(new Manifest.Attribute("Main-Class", MAIN_CLASS));
for (Map.Entry entry : manifestEntries.entrySet())
manifest.addConfiguredAttribute(new Manifest.Attribute(entry.getKey(), entry.getValue()));
return manifest;
}
private Set copyAdditionalDependencies() throws CreatorExecutionException {
File libDirectory = new File(workingDirectory, "META-INF/jettyconsole/lib");
libDirectory.mkdirs();
Set libPaths = new HashSet();
for (URL url : additionalDependencies) {
copyIntoLib(url, libDirectory, libPaths);
}
copyIntoLib(coreDependencyUrl, libDirectory, libPaths);
unpackMainClassAndFilter(coreDependencyUrl);
return libPaths;
}
private void copyIntoLib(URL url, File libDirectory, Set libPaths) throws CreatorExecutionException {
String name = url.getPath().substring(url.getPath().lastIndexOf("/"));
File ourLibDir = new File(libDirectory, name);
ourLibDir.mkdirs();
try {
JarInputStream in = new JarInputStream(url.openStream());
java.util.jar.Manifest manifest = in.getManifest();
if (manifest != null) {
File manifestFile = new File(ourLibDir, "META-INF/MANIFEST.MF");
manifestFile.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(manifestFile);
manifest.write(fos);
fos.close();
}
while (true) {
JarEntry entry = in.getNextJarEntry();
if (entry == null) {
break;
}
// Skip signature files in libraries
if (entry.getName().startsWith("META-INF/") && entry.getName().endsWith(".SF")) {
continue;
}
File destFile = new File(ourLibDir, entry.getName());
destFile.getParentFile().mkdirs();
if (entry.isDirectory()) {
destFile.mkdirs();
} else {
libPaths.add(name + "/" + entry.getName());
final FileOutputStream fileOutputStream = new FileOutputStream(destFile);
try {
IOUtils.copy(in, fileOutputStream);
} finally {
fileOutputStream.close();
}
}
}
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void unpackMainClassAndFilter(URL coredep) {
try {
JarInputStream in = new JarInputStream(coredep.openStream());
while (true) {
JarEntry entry = in.getNextJarEntry();
if (entry == null) {
break;
}
if (entry.getName().startsWith(MAIN_CLASS) && entry.getName().endsWith(".class")) {
IOUtils.copy(in, new FileOutputStream(new File(workingDirectory, entry.getName().substring(entry.getName().lastIndexOf("/") + 1))));
} else if (entry.getName().equals(NOT_FOUND_FILTER_CLASSFILE)) {
File destFile = new File(new File(workingDirectory, "WEB-INF/classes"), NOT_FOUND_FILTER_CLASSFILE);
destFile.getParentFile().mkdirs();
IOUtils.copy(in, new FileOutputStream(destFile));
}
}
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void copyBackgroundImage() throws CreatorExecutionException {
try {
if (backgroundImage == null) {
final URL resource = getClass().getClassLoader().getResource("default-background-image.jpg");
setBackgroundImage(resource);
}
File backgroundImageFile = new File(new File(workingDirectory, "META-INF"), "background-image.jpg");
if(backgroundImageFile.getParentFile().exists() == false) {
backgroundImageFile.getParentFile().mkdirs();
}
IOUtils.copy(backgroundImage.openStream(), new FileOutputStream(backgroundImageFile));
} catch (IOException e) {
throw new CreatorExecutionException("Cannot copy background image '" + backgroundImage + "'", e);
}
}
private void extractWar(File file) throws CreatorExecutionException {
Project project = new Project();
Expand unArchiver = new Expand();
unArchiver.setProject(project);
unArchiver.setSrc(file);
unArchiver.setDest(workingDirectory);
unArchiver.execute();
}
private void writeDescriptor(File consoleDir) throws CreatorExecutionException {
try {
PrintWriter writer = new PrintWriter(new FileOutputStream(new File(consoleDir, "jettyconsole.properties")));
writer.println("name=" + name);
if (properties != null && properties.trim().length() > 0) {
try {
Properties p = new Properties();
p.load(new ByteArrayInputStream(properties.getBytes()));
writer.println(properties);
} catch (IOException e) {
throw new CreatorExecutionException("Can't parse properties: [" + properties + "]", e);
}
}
writer.close();
} catch (FileNotFoundException e) {
throw new CreatorExecutionException("Cannot write to descriptor file", e);
}
}
private void rewriteWebXml() throws CreatorExecutionException {
File webXml = new File(workingDirectory, "WEB-INF/web.xml");
Set beforeFilter = new HashSet();
beforeFilter.add("icon");
beforeFilter.add("display-name");
beforeFilter.add("description");
beforeFilter.add("distributable");
beforeFilter.add("context-param");
if (webXml.exists()) {
try {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String s, String s1) throws SAXException, IOException {
String file = s1.substring(s1.lastIndexOf("/"));
String resource = "/javax/servlet/resources" + file;
final InputStream stream = getClass().getResourceAsStream(resource);
return new InputSource(stream);
}
});
Document document = builder.parse(webXml);
{
final NodeList childElems = document.getDocumentElement().getChildNodes();
for (int i = 0; i < childElems.getLength(); i++) {
if (childElems.item(i) instanceof Element) {
Element e = (Element) childElems.item(i);
if (!beforeFilter.contains(e.getNodeName())) {
Element filterElement = document.createElement("filter");
Element filterNameElement = document.createElement("filter-name");
filterNameElement.appendChild(document.createTextNode(NOT_FOUND_FILTER_CLASSNAME));
Element filterClassElement = document.createElement("filter-class");
filterClassElement.appendChild(document.createTextNode(NOT_FOUND_FILTER_CLASSNAME));
filterElement.appendChild(filterNameElement);
filterElement.appendChild(filterClassElement);
document.getDocumentElement().insertBefore(filterElement, e);
break;
}
}
}
}
beforeFilter.add("filter");
{
final NodeList childElems = document.getDocumentElement().getChildNodes();
for (int i = 0; i < childElems.getLength(); i++) {
if (childElems.item(i) instanceof Element) {
Element e = (Element) childElems.item(i);
if (!beforeFilter.contains(e.getNodeName())) {
Element filterMappingElement = document.createElement("filter-mapping");
Element filterNameElement = document.createElement("filter-name");
filterNameElement.appendChild(document.createTextNode(NOT_FOUND_FILTER_CLASSNAME));
Element urlPatternElement = document.createElement("url-pattern");
urlPatternElement.appendChild(document.createTextNode("/" + MAIN_CLASS + ".class"));
filterMappingElement.appendChild(filterNameElement);
filterMappingElement.appendChild(urlPatternElement);
document.getDocumentElement().insertBefore(filterMappingElement, e);
break;
}
}
}
}
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(webXml));
} catch (ParserConfigurationException e) {
throw new CreatorExecutionException("Exception modifying web.xml", e);
} catch (SAXException e) {
throw new CreatorExecutionException("Exception modifying web.xml", e);
} catch (IOException e) {
throw new CreatorExecutionException("Exception modifying web.xml", e);
} catch (TransformerException e) {
throw new CreatorExecutionException("Exception modifying web.xml", e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy