001: // JigKill.java
002: // $Id: JigKill.java,v 1.4 2000/08/16 21:37:33 ylafon Exp $
003: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005: package org.w3c.jigsaw.admin;
006:
007: import java.net.URL;
008: import java.net.MalformedURLException;
009:
010: import java.util.Vector;
011:
012: import org.w3c.www.http.HttpCredential;
013: import org.w3c.www.http.HttpFactory;
014:
015: import org.w3c.tools.codec.Base64Encoder;
016:
017: /**
018: * Simple class used to save and/or kill Jigsaw.
019: *
020: * <DL>
021: * <DT><B>Options:</B>
022: * <DD><CODE>-u username</CODE> User name (defaults to "admin")
023: * <DD><CODE>-p password</CODE> Password (required)
024: * <DD><CODE>--username username</CODE> Same as <CODE>-u</CODE>
025: * <DD><CODE>--password password</CODE> Same as <CODE>-p</CODE>
026: * <DD><CODE>--save</CODE> Save configuration of all servers</DD>
027: * <DD><CODE>--stop</CODE> Stop all servers</DD>
028: * <DD><CODE>--ping</CODE> check if servers are reachable</DL>
029: * (The last argument is assumed to be the URL to the Admin server,
030: * see Usage examples below...)
031: * <P>
032: * <DL>
033: * <DT><B>Example usage:</B>
034: * <DD>(be sure that jigsaw's <CODE>*.jar</CODE> file is in CLASSPATH,
035: * e.g. <CODE>export CLASSPATH=~/Jigsaw/classes/jigsaw.zip:
036: * ${CLASSPATH}</CODE>)</DD>
037: * <DL><DT>- Save and exit the server
038: * http://gyros.informatik.med.uni-giessen.de:
039: * <DD><CODE>java org.w3c.jigsaw.admin.JigKill -u admin -p for#8pj
040: * http://gyros.informatik.med.uni-giessen.de:8009/</CODE></DD>
041: *
042: * <DD>OR (using explicit options)</DD>
043: *
044: * <DD><CODE>java org.w3c.jigsaw.admin.JigKill -u admin -p for#8pj
045: * --save --stop http://gyros.informatik.med.uni-giessen.de:8009/</CODE></DL>
046: *
047: * <DL><DT>- Stop a server (as fast as possible, e.g. for system shutdown):
048: * <DD><CODE>java org.w3c.jigsaw.admin.JigKill -u admin -p for#8pj
049: * --stop http://gyros.informatik.med.uni-giessen.de:8009/</CODE></DL>
050: *
051: * <DL><DT>- Save the servers current configuration:
052: * <DD><CODE>java org.w3c.jigsaw.admin.JigKill -u admin -p for#8pj
053: * --save http://gyros.informatik.med.uni-giessen.de:8009/</CODE></DL>
054: *
055: * <DL><DT>- Check if a server is still alive:
056: * <DD><CODE>java org.w3c.jigsaw.admin.JigKill -u admin -p for#8pj
057: * --ping http://gyros.informatik.med.uni-giessen.de:8009/</CODE></DL></DL>
058: * <P>
059: * <DL>
060: * <DT><B>Changes from V1.1 to 1.2:</B>
061: * <DD>- Added <CODE>--stop</CODE> option: Simply stop jigsaw quick&savely.
062: * </DD>
063: * <DD>- Added <CODE>--save</CODE> option: Snapshot the current config
064: * (something for a daily crontab job).</DD>
065: * <DD>- Added <CODE>--ping</CODE> option to see if the server is still
066: * running (usefull for scripts).</DD>
067: * <DD>- Added <CODE>--username</CODE> and <CODE>--password</CODE> options
068: * as aliases for <CODE>-u</CODE> and <CODE>-p</CODE>.</DD></DL>
069: *
070: * <DD>- JigKill now returns 0 for success and non-0 for failure
071: * (of the requested operation) EVERYTIMES
072: * (except the JVM cores) to make script-processing as much as easy.</DD>
073: * <DD>- <CODE>-u</CODE> option now defaults to "admin", as jigsaw's
074: * default config does.</DD>
075: * <DD>- JigKill now saves all servers first before stopping them all
076: * (first backup, then destroy...).</DD></DL>
077: * <P>
078: * <DL>
079: * <DT><B>ToDo:</B>
080: * <DD>- Adding a <CODE>--restart</CODE> option.</DD></DL>
081: *
082: * @version $Revision: 1.4 $
083: * @author Benoît Mahé (bmahe@w3.org)
084: * @author Roland Mainz (Roland.Mainz@informatik.med.uni-giessen.de)
085: */
086: public class JigKill {
087: // the following variables are equivalents to ANSI-C's <stdlib.h> defines
088: /**
089: * Exit value of the JVM on success of the requested operation.
090: */
091: final protected static int EXIT_SUCCESS = 0;
092: // JigKill has done it's operation successfull
093: /**
094: * Exit value of the JVM on failure of the requested operation.
095: */
096: final protected static int EXIT_FAILURE = 1;
097: // JigKill failed to do it's work
098:
099: /* object instance variables */
100: protected RemoteResource adminServer = null;
101: protected RemoteResource ctrls[] = null;
102:
103: /**
104: * Print usage description and exit with exit status
105: * {@link #EXIT_FAILURE EXIT_FAILURE}
106: * @see #main(String[])
107: */
108: protected static void usage() {
109: System.err.println("Usage:\n"
110: + "\tjava org.w3c.jigsaw.admin.JigKill "
111: + "-u <username> -p <password> [--save] "
112: + "[--stop] [--ping] <admin server url>\n");
113: System.exit(EXIT_FAILURE);
114: }
115:
116: /**
117: * Get all the server's ControlResource.
118: * @param admin the admin server (a RemoteResource)
119: * @return an array of RemoteResource
120: * @exception RemoteAccessException if any remote error occurs.
121: */
122: protected RemoteResource[] getControls(RemoteResource admin)
123: throws RemoteAccessException {
124: String names[] = admin.enumerateResourceIdentifiers();
125: Vector vcontrols = new Vector(2);
126:
127: for (int i = 0; i < names.length; i++) {
128: if ((!names[i].equals("control"))
129: && (!names[i].equals("realms"))) {
130: RemoteResource srr = admin.loadResource(names[i]);
131:
132: // load the control node
133: RemoteResource control = srr.loadResource("control");
134: vcontrols.addElement(control);
135: }
136: }
137:
138: RemoteResource controls[] = new RemoteResource[vcontrols.size()];
139: vcontrols.copyInto(controls);
140:
141: return controls;
142: }
143:
144: /**
145: * Save the configuration of the servers and the admin server
146: * and then kill all servers (including the admin server).
147: * @exception RemoteAccessException if any remote error occurs.
148: * @see #save()
149: * @see #stop()
150: */
151: public void kill() throws RemoteAccessException {
152: // first save all servers...
153: save();
154:
155: // ...then stop/kill them all
156: stop();
157: }
158:
159: /**
160: * Stop the servers and the admin server.
161: * @exception RemoteAccessException if any remote error occurs.
162: * @see #doLoadResource(String)
163: * @see #kill()
164: * @since JigKill 1.2
165: */
166: public void stop() throws RemoteAccessException {
167: // stop all servers
168: doLoadResource("stop");
169: }
170:
171: /**
172: * Save the configuration of the servers and the admin server.
173: * @exception RemoteAccessException if any remote error occurs.
174: * @see #doLoadResource(String)
175: * @see #kill()
176: * @since JigKill 1.2
177: */
178: public void save() throws RemoteAccessException {
179: // save all servers
180: doLoadResource("save");
181: }
182:
183: /**
184: * Send a "command" to all servers and the admin server.
185: * @param cmd name of the resource to load.
186: * @exception RemoteAccessException if any remote error occurs.
187: * @see #save()
188: * @see #stop()
189: * @since JigKill 1.2
190: */
191: protected void doLoadResource(String cmd)
192: throws RemoteAccessException {
193: // servers
194: for (int i = 0; i < ctrls.length; i++) {
195: ctrls[i].loadResource(cmd);
196: }
197:
198: // admin servers
199: RemoteResource ctrl = adminServer.loadResource("control");
200: ctrl.loadResource(cmd);
201:
202: //done
203: }
204:
205: /**
206: * Contructor.
207: * @param adminURL the admin server URL
208: * @param username the username
209: * @param password the password
210: */
211: public JigKill(URL adminURL, String username, String password)
212: throws RemoteAccessException {
213: AdminContext ctxt = new AdminContext(adminURL);
214: HttpCredential credential = HttpFactory.makeCredential("Basic");
215: Base64Encoder encoder = new Base64Encoder(username + ":"
216: + password);
217:
218: credential.setAuthParameter("cookie", encoder.processString());
219: ctxt.setCredential(credential);
220: ctxt.initialize();
221:
222: adminServer = ctxt.getAdminResource();
223: ctrls = getControls(adminServer);
224: }
225:
226: /**
227: * Main program entry.
228: * This method exits the JVM with either
229: * {@link #EXIT_SUCCESS EXIT_SUCCESS} or
230: * {@link #EXIT_FAILURE EXIT_FAILURE} for the requested operation.
231: * @param args program arguments
232: * @see #usage()
233: */
234: public static void main(String args[]) {
235: // options
236: String username = "admin";
237: String password = null;
238: String url = null;
239: boolean doSave = false;
240: boolean doStop = false;
241: boolean doPing = false;
242:
243: boolean doKill = true;
244: // not an option, but a flag:
245: // If none of the --save, --stop, --ping switches are given,
246: // kill the server (e.g. set --save, --stop options)
247:
248: try {
249: for (int i = 0; i < args.length; i++) {
250: if (args[i].equals("-u")
251: || args[i].equals("--username"))
252: username = args[++i];
253: else if (args[i].equals("-p")
254: || args[i].equals("--password"))
255: password = args[++i];
256: else if (args[i].equals("--save")) {
257: doSave = true;
258: doKill = false;
259: } else if (args[i].equals("--stop")) {
260: doStop = true;
261: doKill = false;
262: } else if (args[i].equals("--ping")) {
263: doPing = true;
264: doKill = false;
265: } else {
266: url = args[i];
267: }
268: }
269: } catch (ArrayIndexOutOfBoundsException exc) {
270: // ignore this...
271: }
272:
273: // check for required arguments...
274: if ((username == null) || (password == null) || (url == null))
275: usage();
276:
277: // the default action is (e.g. none of the --save,
278: // --stop, --ping option set is to KILL)
279: if (doKill) {
280: doSave = doStop = true;
281: }
282:
283: // process URL
284: URL adminURL = null;
285: try {
286: adminURL = new URL(url);
287: } catch (MalformedURLException ex) {
288: System.err.println("Invalid URL : " + url);
289: System.exit(EXIT_FAILURE);
290: }
291:
292: // and now: EXECUTE !
293: try {
294: JigKill jigk = new JigKill(adminURL, username, password);
295:
296: if (doPing) {
297: System.out.println("Servers are alive.");
298: }
299:
300: if (doSave) {
301: jigk.save();
302: System.out.println("Servers saved.");
303: }
304:
305: if (doStop) {
306: jigk.stop();
307: System.out.println("Servers killed.");
308: }
309:
310: // success :-)
311: System.exit(EXIT_SUCCESS);
312: } catch (RemoteAccessException ex) {
313: // catch RemoteAccessException (problems lile wrong login,
314: //server not found etc.)
315: String msg = ex.getMessage();
316:
317: if (msg.equals("Unauthorized"))
318: System.err.println("Invalid username/password.");
319: else
320: System.err.println("Error : " + msg);
321:
322: System.exit(EXIT_FAILURE);
323: } catch (Exception exc) {
324: // catch ANY other exception which may occur...
325: System.err.println("Unexcepted fatal error:");
326: exc.printStackTrace();
327: }
328:
329: // for all cases (except the only one above) return
330: // failure for usage by the underlying scripts
331: System.exit(EXIT_FAILURE);
332: }
333: }
|