001: /*
002: * <copyright>
003: *
004: * Copyright 2003-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.lib.aggagent.test;
028:
029: import java.io.BufferedReader;
030: import java.io.File;
031: import java.io.FileInputStream;
032: import java.io.FileOutputStream;
033: import java.io.IOException;
034: import java.io.InputStream;
035: import java.io.InputStreamReader;
036: import java.io.PrintStream;
037: import java.util.Iterator;
038: import java.util.LinkedList;
039: import java.util.List;
040:
041: /**
042: * <p>
043: * The Configurator is a utility for producing test configurations of
044: * arbitrary size. When run as a standalone application (which is the most
045: * likely scenario), this class requires an initialization file, which may be
046: * specified on the command line (or else the user will be prompted). The
047: * output, which is placed in the specified destination directory (see below),
048: * consists of directories named cfgAggregator and cfgNode<it>n</it>, where
049: * <it>n</it> ranges from 0 to one less than the number of specified source
050: * Nodes. The former contains the AggregationAgent Node config., and each of
051: * the latter is a source Node configuration. All of these nodes should be
052: * executed as part of a single society for purposes of testing.
053: * </p><p>
054: * The format of the initialization file is as a sequence of parameters given
055: * as "<name>=<value>" pairs. Lines in the file not containing
056: * "=" or starting with "#" are presumed to be comments and are ignored.
057: * Following are the parameters currently recognized by the interpreter:
058: * <ul>
059: * <li>
060: * destination -- the directory into which the output is to be written
061: * </li>
062: * <li>
063: * aggagentCp -- path to the aggagent.jar file or the compiled aggagent
064: * class files.
065: * </li>
066: * <li>
067: * nameServer -- the host of the name server. At least one node should
068: * be executed on this host.
069: * </li>
070: * <li>
071: * windows -- provide support for windows-style run scripts. The value
072: * "yes" indicates that windows scripts should be produced, and any other
073: * value is equivalent to "no". Presently, only windows is supported, and
074: * this parameter is ignored.
075: * </li>
076: * <li>
077: * linux -- provide support for linux-style run scripts. The value "yes"
078: * indicates that linux scripts should be produced, and any other value is
079: * equivalent to "no". Presently, only windows is supported, and this
080: * parameter is ignored.
081: * </li>
082: * <li>
083: * shellPath -- in case linux support is turned on, this value is the
084: * path to the script interpreter, e.g., "/bin/csh".
085: * </li>
086: * <li>
087: * nodes -- the number of Node configurations to be generated
088: * </li>
089: * <li>
090: * clustersPerNode -- the number of clusters operating on each node
091: * </li>
092: * <li>
093: * pauseInterval -- a parameter that regulates the amount of work
094: * performed by each Cluster. Literally, this is the amount of time that
095: * the EffortWaster Plugin pauses between updates of the blackboard state.
096: * </li>
097: * <li>
098: * maxCycles -- another workload regulator. This is the maximum number of
099: * objects to be managed by the EffortWaster Plugin on each Cluster, and
100: * consequently also the number of things that must be transmitted to the
101: * </li>
102: * </ul>
103: * </p>
104: */
105: public class Configurator {
106:
107: // - - - - - - - Static Configuration - - - - - - - - - - - - - - - - - - - - -
108: private static List sourcePsps = new LinkedList();
109: private static List aggNames = new LinkedList();
110: private static List aggPlugins = new LinkedList();
111: private static List aggPsps = new LinkedList();
112: private static List jarFiles = new LinkedList();
113: private static List sysFiles = new LinkedList();
114:
115: static {
116: // sourcePsps.add(new Psp(
117: // "org.cougaar.lib.aggagent.plugin.GenericPSP", "test/generic.psp"));
118:
119: aggNames.add("Aggregator");
120:
121: aggPlugins
122: .add("org.cougaar.lib.aggagent.servlet.AggregationComponent(/aggregator)");
123: aggPlugins
124: .add("org.cougaar.lib.aggagent.servlet.AggregationKeepAliveComponent(/aggregatorkeepalive)");
125: aggPlugins
126: .add("org.cougaar.lib.aggagent.plugin.AggregationPlugin");
127: aggPlugins.add("org.cougaar.lib.aggagent.plugin.AlertPlugin");
128:
129: jarFiles.add("bootstrap.jar");
130: jarFiles.add("util.jar");
131: jarFiles.add("core.jar");
132: jarFiles.add("webserver.jar");
133: jarFiles.add("webtomcat.jar");
134: sysFiles.add("tomcat_33.jar");
135: sysFiles.add("servlet.jar");
136: sysFiles.add("xerces.jar");
137: sysFiles.add("silk.jar");
138: sysFiles.add("jpython.jar");
139: sysFiles.add("jsse.jar");
140: sysFiles.add("log4j.jar");
141: }
142:
143: // - - - - - - - Instance Configuration - - - - - - - - - - - - - - - - - - - -
144: private ConfigSpec config = null;
145:
146: // - - - - - - - End of Configuration - - - - - - - - - - - - - - - - - - - - -
147:
148: private void writeCluster(File f, String name, List plugIns)
149: throws IOException {
150: PrintStream out = new PrintStream(new FileOutputStream(f));
151: out.println("[ Cluster ]");
152: out.println("uic = UIC/" + name);
153: out.println();
154: out.println("[ Plugins ]");
155:
156: for (Iterator i = plugIns.iterator(); i.hasNext();)
157: out.println("plugin = " + i.next());
158:
159: out.println();
160: out.println("[ Policies ]");
161: out.println();
162: out.println("[ Permission ]");
163: out.println();
164: out.println("[ AuthorizedOperation ]");
165: out.close();
166: }
167:
168: private void writeNode(File f, List clusters) throws IOException {
169: PrintStream out = new PrintStream(new FileOutputStream(f));
170: out.println("# $id$");
171: out.println("[ Clusters ]");
172: out.println();
173:
174: // insert clusters
175: for (Iterator i = clusters.iterator(); i.hasNext();)
176: out.println("cluster = " + i.next());
177:
178: out.println();
179: out.println("[ AlpProcess ]");
180: out.println();
181: out.println("[ Policies ]");
182: out.println();
183: out.println("[ Permission ]");
184: out.println();
185: out.println("[ AuthorizedOperation ]");
186: out.close();
187: }
188:
189: private static class Psp {
190: private String className = null;
191: private String lookupName = null;
192:
193: public Psp(String c, String n) {
194: className = c;
195: lookupName = n;
196: }
197:
198: public void printout(PrintStream out) {
199: out
200: .println(" <element type=\"org.cougaar.lib.planserver.NamedPSP\">");
201: out.println(" <Classname>" + className + "</Classname>");
202: out.println(" <PSPName>" + lookupName + "</PSPName>");
203: out.println(" </element>");
204: }
205: }
206:
207: private void writePspFile(File f, List psps) throws IOException {
208: PrintStream out = new PrintStream(new FileOutputStream(f));
209: out.println("<object type=\"java.util.Vector\">");
210:
211: for (Iterator i = psps.iterator(); i.hasNext();)
212: ((Psp) i.next()).printout(out);
213:
214: out.println("</object>");
215: out.close();
216: }
217:
218: private void writeDosRunScript(File f, String nodeName)
219: throws IOException {
220: PrintStream out = new PrintStream(new FileOutputStream(f));
221: out.println("@echo off");
222: out.println();
223: out.println("setlocal");
224: out.println();
225: out.println("set NODE=" + nodeName);
226: out.println();
227: out.println("set EXECLASS=org.cougaar.core.node.Node");
228: out
229: .println("set PROPERTIES=-Dorg.cougaar.useBootstrapper=false");
230: out
231: .println("set PROPERTIES=%PROPERTIES% -Dorg.cougaar.core.servlet.enable=true");
232: out
233: .println("set PROPERTIES=%PROPERTIES% -Dorg.cougaar.lib.web.https.port=-1");
234: out
235: .println("set PROPERTIES=%PROPERTIES% -Dorg.cougaar.install.path=%COUGAAR_INSTALL_PATH%");
236: out.println("set NODEARGS=-c -n %NODE%");
237: out.println();
238: out.println("set BJPATH=" + config.aggagentCp);
239: out.println("set LIB=%COUGAAR_INSTALL_PATH%\\lib");
240: out.println("set SYS=%COUGAAR_INSTALL_PATH%\\sys");
241:
242: out.println();
243: out.println("set CPATH=");
244: out.println("set CPATH=%CPATH%;%BJPATH%");
245: for (Iterator i = jarFiles.iterator(); i.hasNext();)
246: out.println("set CPATH=%CPATH%;%LIB%\\" + i.next());
247: for (Iterator i = sysFiles.iterator(); i.hasNext();)
248: out.println("set CPATH=%CPATH%;%SYS%\\" + i.next());
249:
250: out.println();
251: out
252: .println("java -cp %CPATH% %PROPERTIES% %EXECLASS% %NODEARGS%");
253: out.println();
254: out.println("@echo on");
255: out.close();
256: }
257:
258: private void writeAlpReg(File f, String host) throws IOException {
259: PrintStream out = new PrintStream(new FileOutputStream(f));
260: out.println("[ Registry ]");
261: out.println("address=" + host);
262: out.println("alias=AlpFDS");
263: out.println("port=8003");
264: out.close();
265: }
266:
267: private void deleteContents(File f) {
268: File[] list = f.listFiles();
269: for (int i = 0; i < list.length; i++) {
270: File cf = list[i];
271: if (cf.isDirectory())
272: recursiveDelete(cf);
273: else
274: cf.delete();
275: }
276: }
277:
278: private void recursiveDelete(File f) {
279: deleteContents(f);
280: f.delete();
281: }
282:
283: private List genClusterNames(int nodeNumber) {
284: List ret = new LinkedList();
285: String prefix = "Source";
286: String separator = "_";
287: for (int i = 0; i < config.clustersPerNode; i++)
288: ret.add(prefix + nodeNumber + separator + i);
289:
290: return ret;
291: }
292:
293: private List genSourcePlugins() {
294: List ret = new LinkedList();
295: //ret.add(
296: // "org.cougaar.lib.planserver.PlanServerPlugin(file=source.psps.xml)");
297: ret.add("org.cougaar.lib.aggagent.test.EffortWaster(maxCycles="
298: + config.maxCycles + ",pauseInterval="
299: + config.pauseInterval + ")");
300: ret
301: .add("org.cougaar.lib.aggagent.plugin.RemoteSubscriptionPlugin");
302:
303: return ret;
304: }
305:
306: private void prepareSourceNode(int nodeNum, List plugIns)
307: throws IOException {
308: prepareNode("cfgNode" + nodeNum, "SourceNode" + nodeNum,
309: "source.psps.xml", sourcePsps,
310: genClusterNames(nodeNum), plugIns);
311: }
312:
313: private void prepareAggNode() throws IOException {
314: prepareNode("cfgAggregator", "AggNode", "aggregator.psps.xml",
315: aggPsps, aggNames, aggPlugins);
316: }
317:
318: private void prepareNode(String dirName, String name,
319: String pspFile, List psps, List clusters, List plugIns)
320: throws IOException {
321: File dir = new File(config.destination, dirName);
322: dir.mkdir();
323:
324: File textFile = new File(dir, "alpreg.ini");
325: writeAlpReg(textFile, config.nameServer);
326:
327: textFile = new File(dir, pspFile);
328: writePspFile(textFile, psps);
329:
330: if (config.windows) {
331: textFile = new File(dir, "run.bat");
332: writeDosRunScript(textFile, name);
333: }
334:
335: textFile = new File(dir, name + ".ini");
336: writeNode(textFile, clusters);
337:
338: for (Iterator i = clusters.iterator(); i.hasNext();) {
339: String clusterName = i.next().toString();
340: textFile = new File(dir, clusterName + ".ini");
341: writeCluster(textFile, clusterName, plugIns);
342: }
343: }
344:
345: private void prepareDestination(File f) throws IOException {
346: if (!f.exists())
347: f.mkdirs();
348: else if (!f.isDirectory())
349: throw new IllegalStateException("Non-directory \"" + f
350: + "\" exists");
351: else
352: deleteContents(f);
353: }
354:
355: public void execute() {
356: if (config == null) {
357: System.out
358: .println("This Configurator has no initialization spec");
359: return;
360: }
361:
362: try {
363: prepareDestination(config.destination);
364:
365: prepareAggNode();
366:
367: List plugIns = genSourcePlugins();
368:
369: // loop over the number of Nodes and create a directory for each
370: for (int i = 0; i < config.nodes; i++)
371: prepareSourceNode(i, plugIns);
372: } catch (Exception e) {
373: e.printStackTrace();
374: }
375: }
376:
377: private static class ConfigSpec {
378: // pragmatics
379: public File destination = null;
380: public String aggagentCp = null;
381:
382: // gross configurations
383: public String nameServer = null;
384: public String shellPath = null;
385: public boolean windows = false;
386: public boolean linux = false;
387:
388: // distribution and load
389: public int nodes = 0;
390: public int clustersPerNode = 0;
391: public long pauseInterval = 0;
392: public int maxCycles = 0;
393:
394: public void setDestination(String s) {
395: destination = new File(s);
396: }
397:
398: public void setBlackjackCp(String s) {
399: aggagentCp = s;
400: }
401:
402: public void setNameServer(String s) {
403: nameServer = s;
404: }
405:
406: public void setShellPath(String s) {
407: shellPath = s;
408: }
409:
410: public void setWindows(String s) {
411: windows = "yes".equals(s);
412: }
413:
414: public void setLinux(String s) {
415: linux = "yes".equals(s);
416: }
417:
418: private static int parseInt(String s, String hist) {
419: try {
420: return Integer.parseInt(s);
421: } catch (NumberFormatException nfe) {
422: System.out.println("Bad number format for \"" + hist
423: + "\": \"" + s + "\"");
424: }
425: return 0;
426: }
427:
428: public void setNodes(String s) {
429: nodes = parseInt(s, "nodes");
430: }
431:
432: public void setClustersPerNode(String s) {
433: clustersPerNode = parseInt(s, "clustersPerNode");
434: }
435:
436: public void setPauseInterval(String s) {
437: pauseInterval = parseInt(s, "pauseInterval");
438: }
439:
440: public void setMaxCycles(String s) {
441: maxCycles = parseInt(s, "maxCycles");
442: }
443:
444: public ConfigSpec(InputStream in) throws IOException,
445: IllegalStateException {
446: BufferedReader bufr = new BufferedReader(
447: new InputStreamReader(in));
448: String line = null;
449: while ((line = bufr.readLine()) != null) {
450: if (line.startsWith("#"))
451: continue;
452:
453: int k = line.indexOf('=');
454: if (k == -1)
455: continue;
456:
457: String name = line.substring(0, k);
458: String value = line.substring(k + 1);
459:
460: if (name.equals("destination"))
461: setDestination(value);
462: else if (name.equals("aggagentCp"))
463: setBlackjackCp(value);
464: else if (name.equals("nameServer"))
465: setNameServer(value);
466: else if (name.equals("shellPath"))
467: setShellPath(value);
468: else if (name.equals("windows"))
469: setWindows(value);
470: else if (name.equals("linux"))
471: setLinux(value);
472: else if (name.equals("nodes"))
473: setNodes(value);
474: else if (name.equals("clustersPerNode"))
475: setClustersPerNode(value);
476: else if (name.equals("pauseInterval"))
477: setPauseInterval(value);
478: else if (name.equals("maxCycles"))
479: setMaxCycles(value);
480: else
481: System.err.println("Unrecognized parameter name \""
482: + name + "\"");
483: }
484: }
485: }
486:
487: public void parseConfigFile(File infile) throws IOException {
488: InputStream in = new FileInputStream(infile);
489: config = new ConfigSpec(in);
490: in.close();
491: }
492:
493: private static File checkFile(String s) {
494: File ret = new File(s);
495: if (!ret.exists()) {
496: System.out.println("File \"" + s + "\" does not exist.");
497: return null;
498: }
499:
500: if (!ret.isFile()) {
501: if (ret.isDirectory())
502: System.out.println("\"" + s + "\" is a directory.");
503: else
504: System.out.println("\"" + s + "\" is not a file.");
505: return null;
506: }
507:
508: if (!ret.canRead()) {
509: System.out.println("File \"" + s + "\" is not readable.");
510: return null;
511: }
512:
513: return ret;
514: }
515:
516: private static BufferedReader bufr = new BufferedReader(
517: new InputStreamReader(System.in));
518:
519: private static String promptUser(String prompt) {
520: try {
521: System.out.print(prompt);
522: System.out.flush();
523: return bufr.readLine();
524: } catch (IOException eek) {
525: System.out.println("Hosed.");
526: }
527:
528: return null;
529: }
530:
531: public static void main(String[] argv) {
532: File configFile = null;
533: if (argv.length > 0)
534: configFile = checkFile(argv[0]);
535: while (configFile == null) {
536: String input = promptUser("Enter config file path: ");
537: if (input == null || input.equalsIgnoreCase("exit"))
538: System.exit(0);
539: if (input.length() == 0)
540: continue;
541: configFile = checkFile(input);
542: }
543:
544: try {
545: Configurator gen = new Configurator();
546: gen.parseConfigFile(configFile);
547: gen.execute();
548: } catch (IOException ioe) {
549: System.out.println("Error reading file \""
550: + configFile.toString() + "\"--" + ioe);
551: ioe.printStackTrace();
552: } catch (IllegalStateException ise) {
553: System.out.println("Invalid configuration--" + ise);
554: }
555: }
556: }
|