提交 95d4f7b2 编写于 作者: K kohsuke

made more tweaks and added the first command

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@17592 71c3de6d-444a-0410-be80-ed276b4c234a
上级 2350c9b1
......@@ -24,10 +24,14 @@
package hudson.cli;
import hudson.remoting.Channel;
import hudson.remoting.RemoteOutputStream;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
/**
* CLI entry point to Hudson.
......@@ -35,7 +39,9 @@ import java.util.concurrent.Executors;
* @author Kohsuke Kawaguchi
*/
public class CLI {
public static void main(final String[] args) throws Exception {
public static void main(final String[] _args) throws Exception {
List<String> args = Arrays.asList(_args);
URL target = new URL("http://localhost:8080/cli");
FullDuplexHttpStream con = new FullDuplexHttpStream(target);
ExecutorService pool = Executors.newCachedThreadPool();
......@@ -46,7 +52,7 @@ public class CLI {
int r=-1;
try {
CliEntryPoint cli = (CliEntryPoint)channel.getRemoteProperty(CliEntryPoint.class.getName());
r = cli.main(args);
r = cli.main(args, new RemoteOutputStream(System.out), new RemoteOutputStream(System.err));
} finally {
channel.close();
pool.shutdown();
......
......@@ -23,6 +23,9 @@
*/
package hudson.cli;
import java.io.OutputStream;
import java.util.List;
/**
* Remotable interface for CLI entry point on the server side.
*
......@@ -32,5 +35,5 @@ public interface CliEntryPoint {
/**
* Just like the static main method.
*/
int main(String[] args);
int main(List<String> args, OutputStream stdout, OutputStream stderr);
}
......@@ -347,6 +347,11 @@ THE SOFTWARE.
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>args4j</groupId>
<artifactId>args4j</artifactId>
<version>2.0.13</version>
</dependency>
<dependency>
<groupId>org.jvnet.localizer</groupId>
<artifactId>localizer</artifactId>
......
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.cli;
import hudson.ExtensionPoint;
import hudson.Extension;
import hudson.ExtensionList;
import hudson.remoting.Channel;
import hudson.remoting.Callable;
import hudson.model.Hudson;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.CmdLineException;
import java.io.PrintStream;
import java.util.List;
/**
* Base class for Hudson CLI.
*
* <h2>How to implement a CLI command</h2>
* <p>
* CLI commands are defined on the server.
*
* <p>
* Use <a href="http://args4j.dev.java.net/">args4j</a> annotation on your implementation to define
* options and arguments (however, if you don't like that, you could override the {@link #main(List, PrintStream, PrintStream)} method
* directly.
*
* <p>
* Put {@link Extension} on your implementation to have it auto-registered.
*
* @author Kohsuke Kawaguchi
* @since 1.302
*/
public abstract class CLICommand implements ExtensionPoint, Cloneable {
/**
* Connected to stdout and stderr of the CLI agent that initiated the session.
* IOW, if you write to these streams, the person who launched the CLI command
* will see the messages in his terminal.
*
* (In contrast, calling {@code System.out.println(...)} would print out
* the message to the server log file, which is probably not what you want.
*/
protected PrintStream stdout,stderr;
/**
* {@link Channel} that represents the CLI JVM. You can use this to
* execute {@link Callable} on the CLI JVM, among other things.
*/
protected Channel channel;
/**
* Gets the command name.
*
* <p>
* For example, if the CLI is invoked as <tt>java -jar cli.jar foo arg1 arg2 arg4</tt>,
* on the server side {@link CLICommand} that returns "foo" from {@link #getName()}
* will be invoked.
*
* <p>
* By default, this method creates "foo-bar-zot" from "FooBarZotCommand".
*/
public String getName() {
String name = getClass().getName();
name = name.substring(name.lastIndexOf('.')+1); // short name
if(name.endsWith("Command"))
name = name.substring(0,name.length()-7); // trim off the command
// convert "FooBarZot" into "foo-bar-zot"
return name.replaceAll("([a-z0-9])([A-Z])","$1-$2").toLowerCase();
}
public int main(List<String> args, PrintStream stdout, PrintStream stderr) {
this.stdout = stdout;
this.stderr = stderr;
this.channel = Channel.current();
CmdLineParser p = new CmdLineParser(this);
try {
p.parseArgument(args.toArray(new String[args.size()]));
return run();
} catch (CmdLineException e) {
stderr.println(e.getMessage());
printUsage(stderr, p);
return -1;
}
}
/**
* Executes the command, and return the exit code.
*
* @return
* 0 to indicate a success, otherwise an error code.
*/
protected abstract int run();
protected void printUsage(PrintStream stderr, CmdLineParser p) {
stderr.println("java -jar hudson-cli.jar "+getName()+" args...");
p.printUsage(stderr);
}
/**
* Returns all the registered {@link CLICommand}s.
*/
public static ExtensionList<CLICommand> all() {
return Hudson.getInstance().getExtensionList(CLICommand.class);
}
/**
* Obtains a copy of the command for invocation.
*/
public static CLICommand clone(String name) {
for (CLICommand cmd : all()) {
if(name.equals(cmd.getName())) {
try {
return (CLICommand)cmd.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
}
return null;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.cli;
import hudson.Extension;
import hudson.model.Hudson;
/**
* Shows the version.
*
* @author Kohsuke Kawaguchi
*/
@Extension
public class VersionCommand extends CLICommand {
protected int run() {
stdout.println(Hudson.VERSION);
return 0;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Server-side CLI commands for Hudson.
*/
package hudson.cli;
......@@ -45,6 +45,7 @@ import hudson.ExtensionPoint;
import hudson.DescriptorExtensionList;
import hudson.ExtensionListView;
import hudson.cli.CliEntryPoint;
import hudson.cli.CLICommand;
import hudson.logging.LogRecorderManager;
import hudson.lifecycle.Lifecycle;
import hudson.model.Descriptor.FormException;
......@@ -149,6 +150,8 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.Serializable;
import java.io.PrintStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.SecureRandom;
import java.text.NumberFormat;
......@@ -2657,9 +2660,19 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* {@link CliEntryPoint} implementation exposed to the remote CLI.
*/
private final class CliManager implements CliEntryPoint, Serializable {
public int main(String[] args) {
System.out.println(Arrays.asList(args));
return 0;
public int main(List<String> args, OutputStream stdout, OutputStream stderr) {
PrintStream err = new PrintStream(stderr);
String subCmd = args.get(0);
CLICommand cmd = CLICommand.clone(subCmd);
if(cmd!=null)
return cmd.main(args.subList(1,args.size()),
new PrintStream(stdout), err);
err.println("No such command: "+subCmd);
for (CLICommand c : CLICommand.all())
err.println(" "+c.getName());
return -1;
}
private Object writeReplace() {
return Channel.current().export(CliEntryPoint.class,this);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册