提交 20c72b8a 编写于 作者: K kohsuke

moving executable war launcher to a separate module so that test code can use...

moving executable war launcher to a separate module so that test code can use this as a hook to find the war file.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@11537 71c3de6d-444a-0410-be80-ed276b4c234a
上级 b3128adb
......@@ -65,8 +65,15 @@
<configuration>
<tasks>
<mkdir dir="target/generated-resources" />
<!-- needs to be forked because Maven doesn't seem to put tools.jar in classpath -->
<javac srcdir="src/launcher/java" includes="*.java" source="1.4" target="1.4" destdir="target/generated-resources" fork="true" debug="on" />
<!-- put executable war header -->
<resolveArtifact artifactId="executable-war"
property="executable-war.jar"/>
<unjar src="${executable-war.jar}" dest="target/generated-resources">
<patternset>
<include name="*.class" />
</patternset>
</unjar>
<!-- dependencies that goes to unusual locations -->
<resolveArtifact artifactId="remoting"
......@@ -216,10 +223,20 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<!--
classes in this jar will be rebundled into the war.
marking it provided so that this won't show up in WEB-INF/lib
-->
<groupId>org.jvnet.hudson</groupId>
<artifactId>executable-war</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<!--
this dependency is just so that we can put winstone.jar in the war.
marking it provided so that other folks who depend on this war won't pick it up unnecessarily
marking it provided so that this won't show up in WEB-INF/lib
-->
<groupId>org.jvnet.hudson.winstone</groupId>
<artifactId>winstone</artifactId>
......
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
/**
* Launches <tt>hudson.war</tt> from JNLP.
*
* @author Kohsuke Kawaguchi
*/
public class JNLPMain {
public static void main(String[] args) throws Exception {
// don't know if this is really necessary, but jnlp-agent benefited from this,
// so I'm doing it here, too.
try {
System.setSecurityManager(null);
} catch (SecurityException e) {
// ignore and move on.
// some user reported that this happens on their JVM: http://d.hatena.ne.jp/tueda_wolf/20080723
}
boolean headlessMode = Boolean.getBoolean("hudson.webstart.headless");
if (!headlessMode) {
// launch GUI to display output
setUILookAndFeel();
new MainDialog().setVisible(true);
}
Main.main(args);
}
/**
* Sets to the platform native look and feel.
*
* see http://javaalmanac.com/egs/javax.swing/LookFeelNative.html
*/
public static void setUILookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (InstantiationException e) {
} catch (ClassNotFoundException e) {
} catch (UnsupportedLookAndFeelException e) {
} catch (IllegalAccessException e) {
}
}
}
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Context;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.JarURLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Iterator;
/**
* Launcher class for stand-alone execution of Hudson as
* <tt>java -jar hudson.war</tt>.
*
* @author Kohsuke Kawaguchi
*/
public class Main {
public static void main(String[] args) throws Exception {
// this is so that JFreeChart can work nicely even if we are launched as a daemon
System.setProperty("java.awt.headless","true");
File me = whoAmI();
// locate Winstone jar
URL jar = Main.class.getResource("winstone.jar");
// put this jar in a file system so that we can load jars from there
File tmpJar;
try {
tmpJar = File.createTempFile("winstone", "jar");
} catch (IOException e) {
String tmpdir = System.getProperty("java.io.tmpdir");
IOException x = new IOException("Hudson has failed to create a temporary file in " + tmpdir);
x.initCause(e);
throw x;
}
copyStream(jar.openStream(), new FileOutputStream(tmpJar));
tmpJar.deleteOnExit();
// clean up any previously extracted copy, since
// winstone doesn't do so and that causes problems when newer version of Hudson
// is deployed.
File tempFile = File.createTempFile("dummy", "dummy");
deleteContents(new File(tempFile.getParent(), "winstone/" + me.getName()));
tempFile.delete();
// locate the Winstone launcher
ClassLoader cl = new URLClassLoader(new URL[]{tmpJar.toURL()});
Class launcher = cl.loadClass("winstone.Launcher");
Method mainMethod = launcher.getMethod("main", new Class[]{String[].class});
// figure out the arguments
List arguments = new ArrayList(Arrays.asList(args));
arguments.add(0,"--warfile="+ me.getAbsolutePath());
if(!hasWebRoot(arguments))
// defaults to ~/.hudson/war since many users reported that cron job attempts to clean up
// the contents in the temporary directory.
arguments.add("--webroot="+new File(getHomeDir(),"war"));
// run
mainMethod.invoke(null,new Object[]{arguments.toArray(new String[0])});
}
private static boolean hasWebRoot(List arguments) {
for (Iterator itr = arguments.iterator(); itr.hasNext();) {
String s = (String) itr.next();
if(s.startsWith("--webroot="))
return true;
}
return false;
}
/**
* Figures out the URL of <tt>hudson.war</tt>.
*/
public static File whoAmI() throws IOException, URISyntaxException {
URL classFile = Main.class.getClassLoader().getResource("Main.class");
// JNLP returns the URL where the jar was originally placed (like http://hudson.dev.java.net/...)
// not the local cached file. So we need a rather round about approach to get to
// the local file name.
return new File(((JarURLConnection)classFile.openConnection()).getJarFile().getName());
}
private static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len;
while((len=in.read(buf))>0)
out.write(buf,0,len);
in.close();
out.close();
}
private static void deleteContents(File file) throws IOException {
if(file.isDirectory()) {
File[] files = file.listFiles();
if(files!=null) {// be defensive
for (int i = 0; i < files.length; i++)
deleteContents(files[i]);
}
}
file.delete();
}
/**
* Determines the home directory for Hudson.
*
* People makes configuration mistakes, so we are trying to be nice
* with those by doing {@link String#trim()}.
*/
private static File getHomeDir() {
// check JNDI for the home directory first
try {
InitialContext iniCtxt = new InitialContext();
Context env = (Context) iniCtxt.lookup("java:comp/env");
String value = (String) env.lookup("HUDSON_HOME");
if(value!=null && value.trim().length()>0)
return new File(value.trim());
// look at one more place. See issue #1314
value = (String) iniCtxt.lookup("HUDSON_HOME");
if(value!=null && value.trim().length()>0)
return new File(value.trim());
} catch (NamingException e) {
// ignore
}
// finally check the system property
String sysProp = System.getProperty("HUDSON_HOME");
if(sysProp!=null)
return new File(sysProp.trim());
// look at the env var next
try {
String env = System.getenv("HUDSON_HOME");
if(env!=null)
return new File(env.trim()).getAbsoluteFile();
} catch (Throwable _) {
// when this code runs on JDK1.4, this method fails
// fall through to the next method
}
// otherwise pick a place by ourselves
/* ServletContext not available yet
String root = event.getServletContext().getRealPath("/WEB-INF/workspace");
if(root!=null) {
File ws = new File(root.trim());
if(ws.exists())
// Hudson <1.42 used to prefer this before ~/.hudson, so
// check the existence and if it's there, use it.
// otherwise if this is a new installation, prefer ~/.hudson
return ws;
}
*/
// if for some reason we can't put it within the webapp, use home directory.
return new File(new File(System.getProperty("user.home")),".hudson");
}
}
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import java.awt.HeadlessException;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
/**
* Hudson console GUI.
*
* @author Kohsuke Kawaguchi
*/
class MainDialog extends JFrame {
private final JTextArea textArea = new JTextArea();
public MainDialog() throws HeadlessException, IOException {
super("Hudson Console");
JScrollPane pane = new JScrollPane(textArea);
pane.setMinimumSize(new Dimension(400,150));
pane.setPreferredSize(new Dimension(400,150));
add(pane);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationByPlatform(true);
PipedOutputStream out = new PipedOutputStream();
PrintStream pout = new PrintStream(out);
System.setErr(pout);
System.setOut(pout);
// this thread sets the text to JTextArea
final BufferedReader in = new BufferedReader(new InputStreamReader(new PipedInputStream(out)));
new Thread() {
public void run() {
try {
while(true) {
String line;
while((line=in.readLine())!=null) {
final String text = line;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(text+'\n');
scrollDown();
}
});
}
}
} catch (IOException e) {
throw new Error(e);
}
}
}.start();
pack();
}
/**
* Forces the scroll of text area.
*/
private void scrollDown() {
int pos = textArea.getDocument().getEndPosition().getOffset();
textArea.getCaret().setDot(pos);
textArea.requestFocus();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册