Jetty embedding revisited
This commit is contained in:
31
bootstrap/pom.xml
Normal file
31
bootstrap/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.jeudego.pairgoth</groupId>
|
||||
<artifactId>engine-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<description>Simple Bootstrap for the Server UberJar (when packaged in a WAR)</description>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
<mainClass>jetty.bootstrap.JettyBootstrap</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
55
bootstrap/src/main/java/jetty/bootstrap/JettyBootstrap.java
Normal file
55
bootstrap/src/main/java/jetty/bootstrap/JettyBootstrap.java
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) Mort Bay Consulting Pty Ltd and others.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package jetty.bootstrap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
|
||||
public class JettyBootstrap
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
URL warLocation = JettyBootstrap.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
if (warLocation == null)
|
||||
{
|
||||
throw new IOException("JettyBootstrap not discoverable");
|
||||
}
|
||||
|
||||
LiveWarClassLoader clWar = new LiveWarClassLoader(warLocation);
|
||||
System.err.println("Using ClassLoader: " + clWar);
|
||||
Thread.currentThread().setContextClassLoader(clWar);
|
||||
|
||||
File warFile = new File(warLocation.toURI());
|
||||
System.setProperty("org.eclipse.jetty.livewar.LOCATION",warFile.toPath().toRealPath().toString());
|
||||
|
||||
Class<?> mainClass = Class.forName("org.jeudego.pairgoth.container.ServerMain",false,clWar);
|
||||
Method mainMethod = mainClass.getMethod("main",args.getClass());
|
||||
mainMethod.invoke(mainClass,new Object[] { args });
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace(System.err);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
171
bootstrap/src/main/java/jetty/bootstrap/LiveWarClassLoader.java
Normal file
171
bootstrap/src/main/java/jetty/bootstrap/LiveWarClassLoader.java
Normal file
@@ -0,0 +1,171 @@
|
||||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) Mort Bay Consulting Pty Ltd and others.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package jetty.bootstrap;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class LiveWarClassLoader extends ClassLoader implements Closeable
|
||||
{
|
||||
private static final String ID = LiveWarClassLoader.class.getSimpleName();
|
||||
private static final boolean DEBUG = Boolean.getBoolean("jetty.bootstrap.debug");
|
||||
private static final String CLASSES_BASE = "WEB-INF/jetty-server/";
|
||||
private final URI warFileUri;
|
||||
private JarFile warFile;
|
||||
|
||||
public LiveWarClassLoader(URL warFileUrl) throws URISyntaxException, IOException
|
||||
{
|
||||
this.warFileUri = warFileUrl.toURI();
|
||||
this.warFile = new JarFile(new File(warFileUri));
|
||||
}
|
||||
|
||||
public void close() throws IOException
|
||||
{
|
||||
warFile.close();
|
||||
}
|
||||
|
||||
private void debug(String format, Object... args)
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
System.err.printf('[' + ID + "] " + format + "%n",args);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
debug("findClass: %s",name);
|
||||
String path = name.replace('.','/').concat(".class");
|
||||
ZipEntry entry = findEntry(path);
|
||||
if (entry != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return loadClass(name,entry);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
private ZipEntry findEntry(String name)
|
||||
{
|
||||
StringBuilder path = new StringBuilder();
|
||||
path.append(CLASSES_BASE);
|
||||
if (name.charAt(0) == '/')
|
||||
{
|
||||
path.append(name.substring(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
path.append(name);
|
||||
}
|
||||
ZipEntry entry = warFile.getEntry(path.toString());
|
||||
debug("findEntry(%s) %s => %s",name,path,entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URL findResource(String name)
|
||||
{
|
||||
debug("findResource: %s",name);
|
||||
ZipEntry entry = findEntry(name);
|
||||
if (entry != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return URI.create("jar:" + this.warFileUri.toASCIIString() + "!/" + entry.getName()).toURL();
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Enumeration<URL> findResources(String name) throws IOException
|
||||
{
|
||||
debug("findResources: %s",name);
|
||||
List<URL> urls = new ArrayList<>();
|
||||
URL self = findResource(name);
|
||||
if (self != null)
|
||||
{
|
||||
urls.add(self);
|
||||
}
|
||||
|
||||
if (getParent() != null)
|
||||
{
|
||||
Enumeration<URL> parent = getParent().getResources(name);
|
||||
while (parent.hasMoreElements())
|
||||
{
|
||||
urls.add(parent.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.enumeration(urls);
|
||||
}
|
||||
|
||||
private Class<?> loadClass(String name, ZipEntry entry) throws IOException
|
||||
{
|
||||
try (InputStream in = warFile.getInputStream(entry); ByteArrayOutputStream out = new ByteArrayOutputStream())
|
||||
{
|
||||
int len = 0;
|
||||
int bufferSize = 4096;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
while (true)
|
||||
{
|
||||
len = in.read(buffer,0,bufferSize);
|
||||
if (len < 0)
|
||||
break;
|
||||
out.write(buffer,0,len);
|
||||
}
|
||||
byte[] classBytes = out.toByteArray();
|
||||
return defineClass(name,classBytes,0,classBytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[%s]",this.getClass().getName(),this.warFileUri);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user