提交 9e5c20f6 编写于 作者: K kohsuke

Modified to use args4j.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@17243 71c3de6d-444a-0410-be80-ed276b4c234a
上级 9b4f60ec
...@@ -121,8 +121,8 @@ THE SOFTWARE. ...@@ -121,8 +121,8 @@ THE SOFTWARE.
<dependency> <dependency>
<groupId>args4j</groupId> <groupId>args4j</groupId>
<artifactId>args4j</artifactId> <artifactId>args4j</artifactId>
<version>2.0.10</version> <version>2.0.13</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
...@@ -27,6 +27,9 @@ import hudson.remoting.Channel.Mode; ...@@ -27,6 +27,9 @@ import hudson.remoting.Channel.Mode;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.CmdLineException;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
...@@ -60,6 +63,8 @@ import java.util.concurrent.ExecutorService; ...@@ -60,6 +63,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;
/** /**
* Entry point for running a {@link Channel}. This is the main method of the slave JVM. * Entry point for running a {@link Channel}. This is the main method of the slave JVM.
...@@ -71,120 +76,104 @@ import java.security.cert.CertificateException; ...@@ -71,120 +76,104 @@ import java.security.cert.CertificateException;
* @author Kohsuke Kawaguchi * @author Kohsuke Kawaguchi
*/ */
public class Launcher { public class Launcher {
public static void main(String[] args) throws Exception { public Mode mode = Mode.BINARY;
Mode m = Mode.BINARY;
boolean ping = true;
URL slaveJnlpURL = null;
File tcpPortFile = null;
InetSocketAddress connectionTarget=null;
for(int i=0; i<args.length; i++) {
String arg = args[i];
if(arg.equals("-text")) {
System.out.println("Running in text mode");
m = Mode.TEXT;
continue;
}
if(arg.equals("-ping")) { // no-op, but left for backward compatibility
ping = true;
continue;
}
if(arg.equals("-jnlpUrl")) {
if(i+1==args.length) {
System.err.println("The -jnlpUrl option is missing a URL parameter");
System.exit(1);
}
slaveJnlpURL = new URL(args[++i]);
continue;
}
if(arg.equals("-cp") || arg.equals("-classpath")) {
if(i+1==args.length) {
System.err.println("The -cp option is missing a path parameter");
System.exit(1);
}
Method $addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); // no-op, but left for backward compatibility
$addURL.setAccessible(true); @Option(name="-ping")
public boolean ping = true;
String pathList = args[++i]; @Option(name="-text",usage="encode communication with the master with base64. " +
for(String token : pathList.split(File.pathSeparator)) "Useful for running slave over 8-bit unsafe protocol like telnet")
$addURL.invoke(ClassLoader.getSystemClassLoader(),new File(token).toURI().toURL()); public void setTextMode(boolean b) {
mode = b?Mode.TEXT:Mode.BINARY;
System.out.println("Running in "+mode.name().toLowerCase()+" mode");
}
// fix up the system.class.path to pretend that those jar files @Option(name="-jnlpUrl",usage="instead of talking to the master via stdin/stdout, " +
// are given through CLASSPATH or something. "emulate a JNLP client by making a TCP connection to the master. " +
// some tools like JAX-WS RI and Hadoop relies on this. "Connection parameters are obtained by parsing the JNLP file.")
System.setProperty("java.class.path",System.getProperty("java.class.path")+File.pathSeparatorChar+pathList); public URL slaveJnlpURL = null;
continue; @Option(name="-cp",aliases="-classpath",metaVar="PATH",
} usage="add the given classpath elements to the system classloader.")
if(arg.equals("-tcp")) { public void addClasspath(String pathList) throws Exception {
if(i+1==args.length) { Method $addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
System.err.println("The -tcp option is missing a file name parameter"); $addURL.setAccessible(true);
System.exit(1);
} for(String token : pathList.split(File.pathSeparator))
tcpPortFile = new File(args[++i]); $addURL.invoke(ClassLoader.getSystemClassLoader(),new File(token).toURI().toURL());
continue;
} // fix up the system.class.path to pretend that those jar files
if(arg.equals("-connectTo")) { // are given through CLASSPATH or something.
if(i+1==args.length) { // some tools like JAX-WS RI and Hadoop relies on this.
System.err.println("The -connectTo option is missing ADDRESS:PORT parameter"); System.setProperty("java.class.path",System.getProperty("java.class.path")+File.pathSeparatorChar+pathList);
System.exit(1); }
}
String[] tokens = args[++i].split(":"); @Option(name="-tcp",usage="instead of talking to the master via stdin/stdout, " +
if(tokens.length!=2) { "listens to a random local port, write that port number to the given file, " +
System.err.println("Illegal parameter: "+args[i-1]); "then wait for the master to connect to that port.")
System.exit(1); public File tcpPortFile=null;
}
connectionTarget = new InetSocketAddress(tokens[0],Integer.valueOf(tokens[1])); public InetSocketAddress connectionTarget = null;
continue;
} @Option(name="-connectTo",usage="make a TCP connection to the given host and port, then start communication.",metaVar="HOST:PORT")
if(arg.equals("-noCertificateCheck")) { public void setConnectTo(String target) {
// bypass HTTPS security check by using free-for-all trust manager String[] tokens = target.split(":");
System.out.println("Skipping HTTPS certificate checks altoghether. Note that this is not secure at all."); if(tokens.length!=2) {
SSLContext context = SSLContext.getInstance("TLS"); System.err.println("Illegal parameter: "+target);
context.init(null, new TrustManager[]{new NoCheckTrustManager()}, new java.security.SecureRandom()); System.exit(1);
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
// bypass host name check, too.
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
continue;
}
System.err.println("Invalid option: "+arg);
System.err.println(
"java -jar slave.jar [options...]\n" +
" -text : encode communication with the master with base64. Useful for\n" +
" running slave over 8-bit unsafe protocol like telnet.\n" +
" -jnlpUrl <url> : instead of talking to the master via stdin/stdout, emulate a JNLP client\n" +
" by making a TCP connection to the master. Connection parameters\n" +
" are obtained by parsing the JNLP file.\n" +
" -cp paths : add the given classpath elements to the system classloader\n" +
" -noCertificateCheck :\n" +
" bypass HTTPS certificate checks altogether.\n" +
" -connectTo <host>:<port> :\n" +
" make a TCP connection to the given host and port, then start communication.\n" +
" -tcp <file> : instead of talking to the master via stdin/stdout, listens to a random\n" +
" local port, write that port number to the given file, then wait for the\n" +
" master to connect to that port.\n");
System.exit(-1);
} }
connectionTarget = new InetSocketAddress(tokens[0],Integer.valueOf(tokens[1]));
}
/**
* Bypass HTTPS security check by using free-for-all trust manager.
*
* @param _
* This is ignored.
*/
@Option(name="-noCertificateCheck")
public void setNoCertificateCheck(boolean _) throws NoSuchAlgorithmException, KeyManagementException {
System.out.println("Skipping HTTPS certificate checks altoghether. Note that this is not secure at all.");
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{new NoCheckTrustManager()}, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
// bypass host name check, too.
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
}
public static void main(String[] args) throws Exception {
Launcher launcher = new Launcher();
CmdLineParser parser = new CmdLineParser(launcher);
try {
parser.parseArgument(args);
launcher.run();
} catch (CmdLineException e) {
System.err.println(e.getMessage());
System.err.println("java -jar slave.jar [options...]");
parser.printUsage(System.err);
System.err.println();
}
}
public void run() throws Exception {
if(connectionTarget!=null) { if(connectionTarget!=null) {
runAsTcpClient(connectionTarget,m,ping); runAsTcpClient();
System.exit(0); System.exit(0);
} else } else
if(slaveJnlpURL!=null) { if(slaveJnlpURL!=null) {
List<String> jnlpArgs = parseJnlpArguments(slaveJnlpURL); List<String> jnlpArgs = parseJnlpArguments();
hudson.remoting.jnlp.Main.main(jnlpArgs.toArray(new String[jnlpArgs.size()])); hudson.remoting.jnlp.Main.main(jnlpArgs.toArray(new String[jnlpArgs.size()]));
} else } else
if(tcpPortFile!=null) { if(tcpPortFile!=null) {
runAsTcpServer(tcpPortFile,m,ping); runAsTcpServer();
System.exit(0); System.exit(0);
} else { } else {
runWithStdinStdout(m, ping); runWithStdinStdout();
System.exit(0); System.exit(0);
} }
} }
...@@ -192,7 +181,7 @@ public class Launcher { ...@@ -192,7 +181,7 @@ public class Launcher {
/** /**
* Parses the connection arguments from JNLP file given in the URL. * Parses the connection arguments from JNLP file given in the URL.
*/ */
private static List<String> parseJnlpArguments(URL slaveJnlpURL) throws ParserConfigurationException, SAXException, IOException, InterruptedException { private List<String> parseJnlpArguments() throws ParserConfigurationException, SAXException, IOException, InterruptedException {
while (true) { while (true) {
try { try {
URLConnection con = slaveJnlpURL.openConnection(); URLConnection con = slaveJnlpURL.openConnection();
...@@ -257,14 +246,14 @@ public class Launcher { ...@@ -257,14 +246,14 @@ public class Launcher {
* Listens on an ephemeral port, record that port number in a port file, * Listens on an ephemeral port, record that port number in a port file,
* then accepts one TCP connection. * then accepts one TCP connection.
*/ */
private static void runAsTcpServer(File portFile, Mode m, boolean ping) throws IOException, InterruptedException { private void runAsTcpServer() throws IOException, InterruptedException {
// if no one connects for too long, assume something went wrong // if no one connects for too long, assume something went wrong
// and avoid hanging foreever // and avoid hanging foreever
ServerSocket ss = new ServerSocket(0,1); ServerSocket ss = new ServerSocket(0,1);
ss.setSoTimeout(30*1000); ss.setSoTimeout(30*1000);
// write a port file to report the port number // write a port file to report the port number
FileWriter w = new FileWriter(portFile); FileWriter w = new FileWriter(tcpPortFile);
w.write(String.valueOf(ss.getLocalPort())); w.write(String.valueOf(ss.getLocalPort()));
w.close(); w.close();
...@@ -275,29 +264,29 @@ public class Launcher { ...@@ -275,29 +264,29 @@ public class Launcher {
s = ss.accept(); s = ss.accept();
ss.close(); ss.close();
} finally { } finally {
portFile.delete(); tcpPortFile.delete();
} }
runOnSocket(m, ping, s); runOnSocket(s);
} }
private static void runOnSocket(Mode m, boolean ping, Socket s) throws IOException, InterruptedException { private void runOnSocket(Socket s) throws IOException, InterruptedException {
main(new BufferedInputStream(new SocketInputStream(s)), main(new BufferedInputStream(new SocketInputStream(s)),
new BufferedOutputStream(new SocketOutputStream(s)),m,ping); new BufferedOutputStream(new SocketOutputStream(s)), mode,ping);
} }
/** /**
* Connects to the given TCP port and then start running * Connects to the given TCP port and then start running
*/ */
private static void runAsTcpClient(InetSocketAddress target, Mode m, boolean ping) throws IOException, InterruptedException { private void runAsTcpClient() throws IOException, InterruptedException {
// if no one connects for too long, assume something went wrong // if no one connects for too long, assume something went wrong
// and avoid hanging foreever // and avoid hanging foreever
Socket s = new Socket(target.getAddress(),target.getPort()); Socket s = new Socket(connectionTarget.getAddress(),connectionTarget.getPort());
runOnSocket(m, ping, s); runOnSocket(s);
} }
private static void runWithStdinStdout(Mode m, boolean ping) throws IOException, InterruptedException { private void runWithStdinStdout() throws IOException, InterruptedException {
// use stdin/stdout for channel communication // use stdin/stdout for channel communication
ttyCheck(); ttyCheck();
...@@ -305,7 +294,7 @@ public class Launcher { ...@@ -305,7 +294,7 @@ public class Launcher {
// and messing up the stream. // and messing up the stream.
OutputStream os = System.out; OutputStream os = System.out;
System.setOut(System.err); System.setOut(System.err);
main(System.in,os,m,ping); main(System.in,os, mode,ping);
} }
private static void ttyCheck() { private static void ttyCheck() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册