/**
* JADE - Java Agent DEvelopment Framework is a framework to develop
* multi-agent systems in compliance with the FIPA specifications.
* Copyright (C) 2000 CSELT S.p.A.
*
* GNU Lesser General Public License
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation,
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/** Tests:
* java jade.Boot (with/without rmiregistry started): run a main-container
* java jade.Boot -host pippo.cselt.it
* java jade.Boot -host fbellif.cselt.it
* java jade.Boot -host fbellif.cselt.it -port 1200
* java jade.Boot -help
* java jade.Boot -gui
**/
package jade;
//#APIDOC_EXCLUDE_FILE
//#J2ME_EXCLUDE_FILE
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.File;
import java.io.PrintStream;
import java.util.Enumeration; // J2ME CLDC OK
import java.util.Vector; // J2ME CLDC OK
import jade.core.Runtime;
import jade.core.Profile;
//import jade.core.BootProfileImpl;
import jade.util.ExtendedProperties;
import jade.util.PropertiesException;
//import jade.security.SecurityFactory;
/**
* Boots <B><em>JADE</em></b> system, parsing command line arguments in the old (3.x) style.
* @author Giovanni Rimassa - Universita' di Parma
* @author Dick Cowan - HP Labs
* @version $Date: 2010-04-19 17:42:22 +0200 (lun, 19 apr 2010) $ $Revision: 6323 $
*/
public class Boot3 {
/** separator between the agent name and the agent class */
private static final String NAME2CLASS_SEPARATOR = ":";
private ExtendedProperties properties = null;
private BootProfileImpl profile = null;
/**
* Main entry point for invocation.
* @param args The command line arguments. These use the form key:value
* or -key (shorthand for key:true).
*/
public static void main(String args[]) {
new Boot3(args);
}
/**
* Constructor. Starts Jade with provided arguments.
* @param args The command line arguments. These use the form key:value
*/
public Boot3(String[] args) {
try {
profile = new BootProfileImpl(prepareArgs(args)); // qui adesso gli passa anche dbconf
} catch (PropertiesException pe) {
System.out.println(pe);
System.exit(-1);
}
if (profile.getParameter(Profile.IMTP, null) == null) {
profile.setParameter(Profile.IMTP, "jade.imtp.rmi.RMIIMTPManager");
}
if (profile.getParameter(Profile.STYLE_3_X, null) == null) {
profile.setParameter(Profile.STYLE_3_X, "true");
}
properties = profile.getArgProperties();
if (properties.getBooleanProperty(BootProfileImpl.DUMP_KEY, false)) {
listProperties(System.out);
}
if (properties.getBooleanProperty(BootProfileImpl.VERSION_KEY, false)) {
System.out.println(Runtime.getCopyrightNotice());
return;
}
if (properties.getBooleanProperty(BootProfileImpl.HELP_KEY, false)) {
usage(System.out);
return;
}
if (properties.getProperty(Profile.MAIN_HOST) == null) {
try {
properties.setProperty(Profile.MAIN_HOST, InetAddress.getLocalHost().getHostName());
} catch (UnknownHostException uhe) {
System.out.print("Unknown host exception in getLocalHost(): ");
System.out.println(" please use '-host' and/or '-port' options to setup JADE host and port");
System.exit(1);
}
}
if (properties.getBooleanProperty(BootProfileImpl.CONF_KEY, false)) {
new BootGUI(this);
if (properties.getBooleanProperty(BootProfileImpl.DUMP_KEY, false)) {
listProperties(System.out);
}
}
// --- initialize JVM-scoped Security Factory ---
// (the security settings contained into this profile
// will be used for all containers into this JVM in
// despite of settings into profile of other future containers)
//SecurityFactory sf = SecurityFactory.getSecurityFactory(profile);
try {
check();
// Exit the JVM when there are no more containers around
Runtime.instance().setCloseVM(true);
if (profile.getBooleanProperty(Profile.MAIN, true)) {
Runtime.instance().createMainContainer(profile);
}
else {
Runtime.instance().createAgentContainer(profile);
}
} catch (BootException be) {
System.err.println(be);
return;
}
}
/**
* Transform original style boot arguments to new form.
* <pre>
* In the following 'x' and 'y' denote arbitrary strings; 'n' an integer.
* Transformation Rules:
* Original New
* ------------------------------
* -host x host:x
* -owner x owner:x
* -name x name:x
* -port n port:n
* -mtp x mtp:x
* -aclcodec:x aclcodec:x
* -conf x import:x
* -conf -conf
* -container -container
* -gui -gui
* -version -version
* -v -version
* -help -help
* -h -help
* -nomtp -nomtp
* -nomobility -nomobility
* -y x y:x
* agent list agents:agent list
* </pre>
* If the arguments contain either import:x or agents:x
* we will assume that the arguments are already in the new
* format and leave them alone. For "import:" we test if
* what follows is a file name and in the event it isn't we
* assume that it was if there are any other "-x" options following.
* <p>
* You can't mix the old form with the new as this would make the
* distinction between foo:bar as meaning a property named foo with
* a value bar or an agent named foo implmented by class bar impossible.
* <p>
* @param args The command line arguments.
*/
protected String[] prepareArgs(String[] args) {
boolean printUsageInfo = false;
if ((args == null) || (args.length == 0)) {
// printUsageInfo = true;
} else {
boolean isNew = false;
boolean likely = false;
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("import:")) {
int j = args[i].indexOf(':');
isNew = ( (j < args[i].length()-1) && (isFileName(args[i].substring(j+1))) );
likely = !isNew; // in case malformed file name
} else
if (args[i].startsWith("agents:")) {
isNew = true;
} else
if (args[i].startsWith("-") && likely) {
isNew = true;
}
}
if (isNew) {
return args;
}
}
int n = 0;
boolean endCommand =
false; // true when there are no more options on the command line
Vector results = new Vector();
while ((n < args.length) &&!endCommand) {
String theArg = args[n];
if (theArg.equalsIgnoreCase("-conf")) {
if (++n == args.length) {
// no modifier
results.add(theArg);
} else {
// Use whatever is next as a candidate file name
String nextArg = args[n];
if (isFileName(nextArg)) {
// it was a file name
results.add("import:" + nextArg);
} else {
// its either an illformed file name or something else
results.add(theArg);
n--;
}
}
} else if (theArg.equalsIgnoreCase("-host")) {
if (++n == args.length) {
System.err.println("Missing host name ");
printUsageInfo = true;
} else {
results.add("host:" + args[n]);
}
}else if (theArg.equalsIgnoreCase("-owner")) {
if (++n == args.length) {
// "owner:password" not provided on command line
results.add("owner:" + ":");
} else {
results.add("owner:" + args[n]);
}
} else if (theArg.equalsIgnoreCase("-name")) {
if (++n == args.length) {
System.err.println("Missing platform name");
printUsageInfo = true;
} else {
results.add("name:" + args[n]);
}
} else if (theArg.equalsIgnoreCase("-imtp")) {
if (++n == args.length) {
System.err.println("Missing IMTP class");
printUsageInfo = true;
} else {
results.add("imtp:" + args[n]);
}
} else if (theArg.equalsIgnoreCase("-port")) {
if (++n == args.length) {
System.err.println("Missing port number");
printUsageInfo = true;
} else {
try {
Integer.parseInt(args[n]);
} catch (NumberFormatException nfe) {
System.err.println("Wrong int for the port number");
printUsageInfo = true;
}
results.add("port:" + args[n]);
}
} else if (theArg.equalsIgnoreCase("-container")) {
results.add(theArg);
} else if (theArg.equalsIgnoreCase("-backupmain")) {
results.add(theArg);
} else if (theArg.equalsIgnoreCase("-gui")) {
results.add(theArg);
} else if (theArg.equalsIgnoreCase("-version")
|| theArg.equalsIgnoreCase("-v")) {
results.add("-version");
} else if (theArg.equalsIgnoreCase("-help")
|| theArg.equalsIgnoreCase("-h")) {
results.add("-help");
} else if (theArg.equalsIgnoreCase("-nomtp")) {
results.add(theArg);
} else if(theArg.equalsIgnoreCase("-nomobility")){
results.add(theArg);
} else if (theArg.equalsIgnoreCase(
"-dump")) { // new form but useful for debugging
results.add(theArg);
} else if (theArg.equalsIgnoreCase("-mtp")) {
if (++n == args.length) {
System.err.println("Missing mtp specifiers");
printUsageInfo = true;
} else {
results.add("mtp:" + args[n]);
}
} else if (theArg.equalsIgnoreCase("-aclcodec")) {
if (++n == args.length) {
System.err.println("Missing aclcodec specifiers");
printUsageInfo = true;
} else {
results.add("aclcodec:" + args[n]);
}
} else if (theArg.startsWith("-") && n+1 < args.length) {
// Generic option
results.add(theArg.substring(1)+":"+args[++n]);
} else {
endCommand = true; //no more options on the command line
}
n++; // go to the next argument
} // end of while
// all options, but the list of Agents, have been parsed
if (endCommand) { // parse the list of agents, now
--n; // go to the previous argument
StringBuffer sb = new StringBuffer();
for (int i = n; i < args.length; i++) {
sb.append(args[i] + " ");
}
results.add("agents:" + sb.toString());
}
if (printUsageInfo) {
results.add("-help");
}
String[] newArgs = new String[results.size()];
for (int i = 0; i < newArgs.length; i++) {
newArgs[i] = (String) results.elementAt(i);
}
return newArgs;
}
/**
* Test if an argument actually references a file.
* @param arg The argument to test.
* @return True if it does, false otherwise.
*/
protected boolean isFileName(String arg) {
File testFile = new File(arg);
return testFile.exists();
}
/**
* Show usage information.
* @param out The print stream to output to.
*/
public void usage(PrintStream out) {
out.println("Usage: java jade.Boot [options] [agent specifiers]");
out.println("");
out.println("where options are:");
out.println(" -host <host name>\tHost where RMI registry for the platform is located");
out.println(" -port <port number>\tThe port where RMI registry for the platform resides");
out.println(" -gui\t\t\tIf specified, a new Remote Management Agent is created.");
out.println(" -container\t\tIf specified, a new Agent Container is added to an existing platform");
out.println(" \t\t\tOtherwise a new Agent Platform is created");
out.println(" -conf\t\t\tShows the gui to set the configuration properties to start JADE.");
out.println(" -conf <file name>\tStarts JADE using the configuration properties read in the specified file.");
out.println(" -dump\t\t\tIf specified, lists boot's current properties.");
out.println(" -version\t\tIf specified, current JADE version number and build date is printed.");
out.println(" -mtp\t\t\tSpecifies a list, separated by ';', of external Message Transport Protocols to be activated.");
out.println(" \t\t\tBy default the HTTP-MTP is activated on the main-container and no MTP is activated on the other containers.");
out.println(" -nomtp\t\tHas precedence over -mtp and overrides it.");
out.println(" \t\t\tIt should be used to override the default behaviour of the main-container (by default the -nomtp option unselected).");
out.println(" -aclcodec\t\tSpecifies a list, separated by ';', of ACLCodec to use. By default the string codec is used.");
out.println(" -name <platform name>\tThe symbolic platform name specified only for the main container.");
out.println(" -owner <username:password>\tThe owner of a container or platform.");
out.println(" -nomobility\t\tIf specified, disables the mobility and cloning support for the container.");
out.println(" -auth <Simple|Unix|NT|Kerberos>\tThe user authentication module to be used.");
out.println(" -help\t\t\tPrints out usage informations.");
out.println(" -<key> <value>\t\tApplication specific options.");
out.println("");
out.print("An agent specifier is composed of an agent name and an agent class, separated by \"");
out.println(NAME2CLASS_SEPARATOR + "\"");
out.println("");
out.println("Take care that the specified agent name represents only the local name of the agent.");
out.println("Its guid (globally unique identifier) is instead assigned by the AMS after concatenating");
out.println("the home agent platform identifier (e.g. john@foo.cselt.it:1099/JADE)");
out.println("");
out.println("Examples:");
out.println(" Connect to default platform, starting an agent named 'peter'");
out.println(" implemented in 'myAgent' class:");
out.println(" \tjava jade.Boot -container peter:myAgent");
out.println("");
out.println(" Connect to a platform on host zork.zot.za, on port 1100,");
out.println(" starting two agents");
out.println(" java jade.Boot -container -host zork.zot.za -port 1100 peter:heAgent paula:sheAgent");
out.println("");
out.println(" Create an Agent Platform and starts an agent on the local Agent Container");
out.println(" \tjava jade.Boot Willy:searchAgent");
out.println("");
System.exit(0);
}
/**
* List boot properties to provided print stream.
* @param out PrintStream to list properties to.
*/
public void listProperties(PrintStream out) {
out.println("---------- Jade Boot property values ----------");
for (Enumeration e = properties.sortedKeys(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
out.println(key + "=" + properties.getProperty(key));
}
out.println("-----------------------------------------------");
}
/**
* Get boot properties.
* @return ExtendedProperties Boot properties.
*/
public ExtendedProperties getProperties() {
return properties;
}
/**
* Set boot properties. Copies provided properties over existing ones.
* @param updates Properties to be copied.
*/
public void setProperties(ExtendedProperties updates) throws BootException {
properties.copyProperties(updates);
profile.setArgProperties(properties);
}
/**
* This method verifies the configuration properties and eventually correct them.
* It checks if the port number is a number greater than 0 otherwise it throws a BootException,
* and if the -nomtp has been set, then delete some other mtp wrongly set.
* If the user wants to start a platform the host
* must be the local host so if a different name is speficied it
* will be corrected and an exception will be thrown.
* @throws BootException if anything is found to be inconsistent.
*/
protected void check() throws BootException {
try {
Integer.parseInt(profile.getParameter(Profile.MAIN_PORT, Integer.toString(BootProfileImpl.DEFAULT_PORT)));
} catch (NumberFormatException nfe) {
throw new BootException("Malformed port number");
}
// Remove the MTP list if '-nomtp' is specified
if (profile.getBooleanProperty(BootProfileImpl.NOMTP_KEY, false)) {
if (profile.getParameter(BootProfileImpl.MTP_KEY, null) != null) {
throw new BootException("Error: If noMTP is set, you can't specify MTPs.");
}
}
// Check that the local-host is actually local
String localHost = profile.getParameter(Profile.LOCAL_HOST, null);
if (localHost != null && !Profile.isLocalHost(localHost)) {
throw new BootException("Error: Not possible to launch JADE a remote host ("+properties.getProperty(Profile.LOCAL_HOST)+"). Check the -host and -local-host options.");
}
}
}