0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 1997-2004 BBNT Solutions, LLC
0005: * under sponsorship of the Defense Advanced Research Projects
0006: * Agency (DARPA).
0007: *
0008: * You can redistribute this software and/or modify it under the
0009: * terms of the Cougaar Open Source License as published on the
0010: * Cougaar Open Source Website (www.cougaar.org).
0011: *
0012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023: *
0024: * </copyright>
0025: */
0026: package org.cougaar.glm.execution.eg;
0027:
0028: import org.cougaar.util.FilteredIterator;
0029: import org.cougaar.util.ThemeFactory;
0030: import org.cougaar.util.UnaryPredicate;
0031: import java.awt.BorderLayout;
0032: import java.awt.Color;
0033: import java.awt.Component;
0034: import java.awt.Container;
0035: import java.awt.Dimension;
0036: import java.awt.GridBagConstraints;
0037: import java.awt.GridBagLayout;
0038: import java.awt.Insets;
0039: import java.awt.LayoutManager;
0040: import java.awt.Point;
0041: import java.awt.Rectangle;
0042: import java.awt.event.ActionEvent;
0043: import java.awt.event.ActionListener;
0044: import java.awt.event.ComponentAdapter;
0045: import java.awt.event.ComponentEvent;
0046: import java.awt.event.MouseAdapter;
0047: import java.awt.event.MouseEvent;
0048: import java.awt.event.MouseListener;
0049: import java.awt.event.MouseMotionListener;
0050: import java.awt.event.WindowAdapter;
0051: import java.awt.event.WindowEvent;
0052: import java.io.BufferedReader;
0053: import java.io.FileInputStream;
0054: import java.io.FileOutputStream;
0055: import java.io.FileReader;
0056: import java.io.File;
0057: import java.io.IOException;
0058: import java.text.SimpleDateFormat;
0059: import java.util.ArrayList;
0060: import java.util.Collections;
0061: import java.util.Date;
0062: import java.util.Enumeration;
0063: import java.util.HashMap;
0064: import java.util.HashSet;
0065: import java.util.Hashtable;
0066: import java.util.Iterator;
0067: import java.util.List;
0068: import java.util.Properties;
0069: import java.util.StringTokenizer;
0070: import javax.swing.AbstractAction;
0071: import javax.swing.BorderFactory;
0072: import javax.swing.ButtonGroup;
0073: import javax.swing.Icon;
0074: import javax.swing.JCheckBox;
0075: import javax.swing.JComboBox;
0076: import javax.swing.JComponent;
0077: import javax.swing.JDialog;
0078: import javax.swing.JFileChooser;
0079: import javax.swing.JFrame;
0080: import javax.swing.JLabel;
0081: import javax.swing.JLayeredPane;
0082: import javax.swing.JMenu;
0083: import javax.swing.JMenuBar;
0084: import org.cougaar.util.OptionPane;
0085: import javax.swing.JPanel;
0086: import javax.swing.JRadioButtonMenuItem;
0087: import javax.swing.JRootPane;
0088: import javax.swing.JTabbedPane;
0089: import javax.swing.JTextField;
0090: import javax.swing.JToggleButton;
0091: import javax.swing.JToolBar;
0092: import javax.swing.SwingUtilities;
0093: import org.cougaar.glm.execution.common.*;
0094: import org.cougaar.mlm.ui.planviewer.ConnectionHelper;
0095:
0096: public class EventGenerator implements TimeGUI.Listener, TimeConstants {
0097: private ArrayList listeners = new ArrayList();
0098: private ArrayList scheduleManagers = new ArrayList();
0099: private HashMap clusters = new HashMap();
0100: private long theExecutionTime = -1;
0101: private double theExecutionRate = 1.0;
0102: private boolean isPaused = false;
0103: private TimeGUI theTimeGUI;
0104: private List timeScript = null;
0105: private int timeScriptCurrentIndex = -1;
0106: private boolean timeScriptSawHighRate = false;
0107: private long theSchedulingLookAhead = 10L * 60000L; // Look ahead ten minutes
0108: private InventoryReportManager theInventoryReportManager;
0109: private InventoryScheduleManager theInventoryScheduleManager;
0110: private FailureConsumptionReportManager theFailureConsumptionReportManager;
0111: private FailureConsumptionRateManager theFailureConsumptionRateManager;
0112: private TaskEventReportManager theTaskEventReportManager;
0113:
0114: private static class TimeScriptItem {
0115: long elapsedTime;
0116: long endTime;
0117:
0118: public TimeScriptItem(String line) {
0119: StringTokenizer tokens = new StringTokenizer(line, ";");
0120: endTime = new Date(tokens.nextToken().trim()).getTime();
0121: elapsedTime = Long.parseLong(tokens.nextToken().trim());
0122: }
0123:
0124: public TimeScriptItem(long endTime, long elapsedTime) {
0125: this .endTime = endTime;
0126: this .elapsedTime = elapsedTime;
0127: }
0128:
0129: public String toString() {
0130: return new Date(endTime).toString() + ";" + elapsedTime;
0131: }
0132: }
0133:
0134: public EventGenerator() {
0135: theInventoryReportManager = new InventoryReportManager(this );
0136: theInventoryScheduleManager = new InventoryScheduleManager(
0137: this , theInventoryReportManager);
0138: theFailureConsumptionReportManager = new FailureConsumptionReportManager(
0139: this );
0140: theFailureConsumptionRateManager = new FailureConsumptionRateManager(
0141: this , theFailureConsumptionReportManager);
0142: theTaskEventReportManager = new TaskEventReportManager(this );
0143: scheduleManagers.add(theInventoryScheduleManager);
0144: scheduleManagers.add(theInventoryReportManager);
0145: scheduleManagers.add(theFailureConsumptionRateManager);
0146: scheduleManagers.add(theFailureConsumptionReportManager);
0147: scheduleManagers.add(theTaskEventReportManager);
0148: }
0149:
0150: public void initialize() {
0151: initializeLogging();
0152: restore();
0153: String url = getContactURL(); // Get a toehold into the society
0154: try {
0155: getClusterInfo(url); // The all the clusters
0156: Object[] handlers = { new EGExecutionTimeStatusHandler(this ), };
0157: for (Iterator iter = clusters.values().iterator(); iter
0158: .hasNext();) {
0159: ClusterInfo clusterInfo = (ClusterInfo) iter.next();
0160: ExecutionListener listener = new ExecutionListener(
0161: clusterInfo, handlers);
0162: listener.addHandlers(theInventoryScheduleManager
0163: .getHandlers());
0164: listener.addHandlers(theInventoryReportManager
0165: .getHandlers());
0166: listener.addHandlers(theFailureConsumptionRateManager
0167: .getHandlers());
0168: listener.addHandlers(theFailureConsumptionReportManager
0169: .getHandlers());
0170: listener.addHandlers(theTaskEventReportManager
0171: .getHandlers());
0172: addListener(listener);
0173: }
0174: } catch (Exception re) {
0175: re.printStackTrace();
0176: displayErrorString(re.getMessage());
0177: System.exit(1);
0178: }
0179: }
0180:
0181: private void initializeLogging() {
0182: String prefix = new SimpleDateFormat("yyyyMMddHHmmss")
0183: .format(new Date());
0184: for (Iterator managers = scheduleManagers.iterator(); managers
0185: .hasNext();) {
0186: ScheduleManager manager = (ScheduleManager) managers.next();
0187: try {
0188: manager.enableLog(prefix); // Probably does nothing
0189: } catch (IOException ioe) {
0190: System.err.println("Failed to open log file for "
0191: + manager.getGUITitle());
0192: ioe.printStackTrace();
0193: }
0194: }
0195: }
0196:
0197: public void setTimeScript(List newScript) {
0198: if (newScript == null) {
0199: cancelTimeScript();
0200: } else {
0201: timeScript = newScript;
0202: timeScriptCurrentIndex = -1;
0203: timeScriptSawHighRate = false;
0204: getTimeGUI().enableControls();
0205: getTimeGUI().play();
0206: }
0207: }
0208:
0209: private void cancelTimeScript() {
0210: timeScript = null;
0211: getTimeGUI().disableControls();
0212: }
0213:
0214: private static class RatePair {
0215: public String theName;
0216: public double theRate;
0217:
0218: public RatePair(String aName, double aRate) {
0219: theName = aName;
0220: theRate = aRate;
0221: }
0222:
0223: public String toString() {
0224: return theName;
0225: }
0226: }
0227:
0228: private static final int DEFAULT_RATE = 1;
0229:
0230: private static final RatePair[] rates = {
0231: new RatePair("Paused", 0.0),
0232: new RatePair("Normal", 1.0),
0233: new RatePair("10X", 10.0),
0234: new RatePair("Hour/Minute", 60.0),
0235: new RatePair("Day/Minute", 24.0 * 60.0),
0236: new RatePair("Week/Minute", 7.0 * 24.0 * 60.0),
0237: new RatePair("Month/Minute", (365.24 / 12.0) * 24.0 * 60.0), };
0238:
0239: private JComboBox pauseButton = new JComboBox(rates);
0240: private JMenu executionRateMenu = new JMenu(
0241: "Execution Rate (Normal)");
0242:
0243: private static class AdvanceItem {
0244: String label;
0245: long advancement;
0246:
0247: public AdvanceItem(String label, long advancement) {
0248: this .label = label;
0249: this .advancement = advancement;
0250: }
0251: }
0252:
0253: private static AdvanceItem[] advancements = {
0254: new AdvanceItem("10 minutes", 10 * ONE_MINUTE),
0255: new AdvanceItem("1 hour", ONE_HOUR),
0256: new AdvanceItem("6 hours", 6 * ONE_HOUR),
0257: new AdvanceItem("1 day", ONE_DAY),
0258: new AdvanceItem("1 week", ONE_WEEK),
0259: new AdvanceItem("1 month", ONE_MONTH), };
0260:
0261: private class PauseButtonListener implements ActionListener {
0262: private double oldRate = ((RatePair) rates[DEFAULT_RATE]).theRate;
0263: private int oldIndex = DEFAULT_RATE;
0264:
0265: public void actionPerformed(ActionEvent e) {
0266: Object object = pauseButton.getSelectedItem();
0267: int newIndex = pauseButton.getSelectedIndex();
0268: if (object instanceof RatePair) {
0269: RatePair rate = (RatePair) object;
0270: userSetRate(rate.theRate);
0271: oldIndex = newIndex;
0272: oldRate = rate.theRate;
0273: } else {
0274: String enteredRate = (String) object;
0275: try {
0276: double newRate = Double.parseDouble(enteredRate);
0277: if (newRate < 0.0)
0278: throw new NumberFormatException();
0279: userSetRate(newRate);
0280: oldIndex = 0;
0281: oldRate = newRate;
0282: } catch (Exception ex) {
0283: postErrorMessage(pauseButton,
0284: "Value must be non-negative numeric");
0285: if (oldIndex == 0) {
0286: pauseButton.setSelectedItem("" + oldRate);
0287: } else {
0288: pauseButton.setSelectedIndex(oldIndex);
0289: }
0290: }
0291: }
0292: }
0293:
0294: public double getRate() {
0295: return oldRate;
0296: }
0297: }
0298:
0299: private PauseButtonListener pauseButtonListener = new PauseButtonListener();
0300:
0301: private JPanel theGUI;
0302:
0303: public JComponent getGUI() {
0304: if (theGUI == null) {
0305: theGUI = new JPanel(new BorderLayout());
0306: JTabbedPane tabbedPane = new JTabbedPane();
0307: theGUI.add(tabbedPane);
0308: for (Iterator managers = scheduleManagers.iterator(); managers
0309: .hasNext();) {
0310: ScheduleManager manager = (ScheduleManager) managers
0311: .next();
0312: tabbedPane.addTab(manager.getGUITitle(), manager
0313: .getGUI());
0314: }
0315: // JPanel top = new JPanel();
0316: // top.add(getJMenuBar());
0317: // theGUI.add(top, BorderLayout.NORTH);
0318: }
0319: return theGUI;
0320: }
0321:
0322: public JMenuBar getJMenuBar() {
0323: JMenuBar top = new JMenuBar();
0324:
0325: JMenu optionsMenu = getOptionsMenu();
0326: if (false) {
0327: JLabel pauseLabel = new JLabel("Execution Rate: ");
0328: pauseLabel.setBorder(BorderFactory.createEmptyBorder(0, 10,
0329: 0, 10));
0330: pauseLabel.setForeground(Color.black);
0331: pauseButton.setToolTipText("Select execution rate");
0332: pauseButton.setEditable(false); // Doesn't work very well
0333: pauseButton.setSelectedIndex(DEFAULT_RATE);
0334: pauseButton.addActionListener(pauseButtonListener);
0335: setRate(((RatePair) rates[DEFAULT_RATE]).theRate);
0336: } else {
0337: ButtonGroup executionRateGroup = new ButtonGroup();
0338: for (int i = 0; i < rates.length; i++) {
0339: final RatePair rate = rates[i];
0340: final JRadioButtonMenuItem item = new JRadioButtonMenuItem(
0341: rates[i].theName);
0342: item.addActionListener(new ActionListener() {
0343: public void actionPerformed(ActionEvent e) {
0344: if (item.isSelected()) {
0345: userSetRate(rate.theRate);
0346: executionRateMenu
0347: .setLabel("Execution Rate ("
0348: + rate.theName + ")");
0349: }
0350: }
0351: });
0352: executionRateGroup.add(item);
0353: executionRateMenu.add(item);
0354: if (i == DEFAULT_RATE)
0355: item.setSelected(true);
0356: }
0357: }
0358: top.add(optionsMenu);
0359: // top.add(getTimeGUI());
0360: // top.add(pauseLabel);
0361: // top.add(pauseButton);
0362: top.add(executionRateMenu);
0363: top.add(getAdvanceMenu());
0364: return top;
0365: }
0366:
0367: private JMenu getAdvanceMenu() {
0368: final JMenu advanceMenu = new JMenu("Advance Time");/* {
0369: public Dimension getMaximumSize() {
0370: return getPreferredSize();
0371: }
0372: };*/
0373: advanceMenu.setToolTipText("Select rapid time advancement");
0374: for (int i = 0; i < advancements.length; i++) {
0375: final AdvanceItem item = advancements[i];
0376: advanceMenu.add(new AbstractAction(item.label) {
0377: public void actionPerformed(ActionEvent e) {
0378: userAdvanceExecutionTime(item.advancement);
0379: }
0380: });
0381: }
0382: advanceMenu.add(new AbstractAction("To Time...") {
0383: public void actionPerformed(ActionEvent e) {
0384: advanceExecutionTimeTo();
0385: }
0386: });
0387: advanceMenu.add(new AbstractAction("Run Time Script...") {
0388: public void actionPerformed(ActionEvent e) {
0389: runTimeScript();
0390: }
0391: });
0392: return advanceMenu;
0393: }
0394:
0395: private JMenu getOptionsMenu() {
0396: JMenu optionsMenu = new JMenu("Options");
0397: optionsMenu.add(new AbstractAction("Scheduling Lookahead...",
0398: null) {
0399: public void actionPerformed(ActionEvent e) {
0400: setSchedulingLookAhead();
0401: }
0402: });
0403: return optionsMenu;
0404: }
0405:
0406: public JToolBar getJToolBar() {
0407: JToolBar top = new JToolBar();
0408:
0409: pauseButton.setEditable(false); // Doesn't work very well
0410: pauseButton.setSelectedIndex(DEFAULT_RATE);
0411: pauseButton.addActionListener(pauseButtonListener);
0412:
0413: setRate(((RatePair) rates[DEFAULT_RATE]).theRate);
0414: top.add(getTimeGUI());
0415: top.add(pauseButton);
0416: top.add(getAdvanceMenu());
0417: return top;
0418: }
0419:
0420: public TimeGUI getTimeGUI() {
0421: if (theTimeGUI == null) {
0422: theTimeGUI = new TimeGUI(this );
0423: updateTimeGUI();
0424: }
0425: return theTimeGUI;
0426: }
0427:
0428: public void timePlay() {
0429: }
0430:
0431: public void timePause() {
0432: }
0433:
0434: public void timeStop() {
0435: cancelTimeScript();
0436: }
0437:
0438: public void updateTimeGUI() {
0439: if (theTimeGUI != null && theExecutionTime > 0L) {
0440: theTimeGUI.setTime(theExecutionTime, theExecutionRate);
0441: }
0442: }
0443:
0444: public static void postErrorMessage(Component component,
0445: String message) {
0446: OptionPane.showOptionDialog(component, message, "Error",
0447: OptionPane.DEFAULT_OPTION, OptionPane.ERROR_MESSAGE,
0448: null, null, null);
0449: }
0450:
0451: private void runTimeScript() {
0452: JFileChooser chooser = new JFileChooser(".");
0453: chooser.setDialogTitle("Select Time Script");
0454: if (chooser.showOpenDialog(getGUI()) == JFileChooser.APPROVE_OPTION) {
0455: setTimeScript(createTimeScript(chooser.getSelectedFile()));
0456: checkTimeScript();
0457: }
0458: }
0459:
0460: public void advanceExecutionTimeTo() {
0461: JPanel message = new JPanel(new GridBagLayout());
0462: GridBagConstraints gbc = new GridBagConstraints();
0463: gbc.gridx = 0;
0464: gbc.anchor = gbc.WEST;
0465: gbc.gridy = 1;
0466: message.add(new JLabel("Time to advance to: "), gbc);
0467: gbc.gridy = 2;
0468: message.add(new JLabel("Transition interval (seconds): "), gbc);
0469: gbc.gridx = 1;
0470: gbc.fill = gbc.HORIZONTAL;
0471: gbc.weightx = 1.0;
0472: JTextField advancement = new JTextField(30);
0473: advancement.setText(new EGDate(theExecutionTime).toString());
0474: gbc.gridy = 1;
0475: message.add(advancement, gbc);
0476: JTextField interval = new JTextField(30);
0477: interval.setText("30");
0478: gbc.gridy = 2;
0479: message.add(interval, gbc);
0480: int opt = OptionPane.showOptionDialog(getGUI(), message,
0481: "Time Advancement", OptionPane.OK_CANCEL_OPTION,
0482: OptionPane.QUESTION_MESSAGE, null, null, null);
0483: if (opt != OptionPane.OK_OPTION)
0484: return;
0485: try {
0486: long newTime = new EGDate(advancement.getText()).getTime();
0487: long transitionInterval = Long
0488: .parseLong(interval.getText()) * 1000L;
0489: userSetExecutionTime(newTime, transitionInterval);
0490: } catch (IllegalArgumentException iae) {
0491: postErrorMessage(theTimeGUI,
0492: "Input not recognized as a date");
0493: }
0494: }
0495:
0496: private void userAdvanceExecutionTime(long advancement) {
0497: cancelTimeScript();
0498: send(SetExecutionTime.createRelativeInstance(advancement,
0499: pauseButtonListener.getRate(), 0L));
0500: }
0501:
0502: private void userSetExecutionTime(long newTime,
0503: long transitionInterval) {
0504: cancelTimeScript();
0505: send(SetExecutionTime.createAbsoluteInstance(newTime,
0506: pauseButtonListener.getRate(), transitionInterval));
0507: }
0508:
0509: private void userSetRate(double newRate) {
0510: cancelTimeScript();
0511: setRate(newRate);
0512: }
0513:
0514: private void setRate(double newRate) {
0515: send(SetExecutionTime.createRateChangeInstance(newRate));
0516: }
0517:
0518: public void send(SetExecutionTime params) {
0519: setPaused(params.theExecutionRate == 0.0);
0520: try {
0521: Iterator iter = clusters.values().iterator();
0522: if (iter.hasNext()) {
0523: ClusterInfo clusterInfo = (ClusterInfo) iter.next();
0524: TimeControlListener listener = new TimeControlListener(
0525: clusterInfo, params);
0526: startListener(listener);
0527: }
0528: } catch (IOException ioe) {
0529: ioe.printStackTrace();
0530: }
0531: }
0532:
0533: public boolean isPaused() {
0534: return isPaused;
0535: }
0536:
0537: public void setPaused(boolean newPaused) {
0538: isPaused = newPaused;
0539: if (newPaused) {
0540: if (pauseButton.getSelectedIndex() != 0)
0541: pauseButton.setSelectedIndex(0);
0542: } else {
0543: updateExecutionTime();
0544: }
0545: }
0546:
0547: public void addListener(Listener l) {
0548: listeners.add(l);
0549: }
0550:
0551: public void startListeners() {
0552: for (Iterator i = listeners.iterator(); i.hasNext();) {
0553: startListener((Listener) i.next());
0554: }
0555: }
0556:
0557: public void startListener(Listener l) {
0558: l.start();
0559: }
0560:
0561: public InventoryReportListener createInventoryReportListener(
0562: String source, Object[] handlers,
0563: String itemIdentification, long aReportDate)
0564: throws IOException {
0565: ClusterInfo clusterInfo = (ClusterInfo) clusters.get(source);
0566: if (clusterInfo == null) {
0567: System.err.println("No info for " + source);
0568: return null;
0569: }
0570: return new InventoryReportListener(clusterInfo, handlers,
0571: itemIdentification, aReportDate);
0572: }
0573:
0574: public EventMonitorListener createEventMonitorListener(
0575: String source, Object[] handlers, Report aReport)
0576: throws IOException {
0577: ClusterInfo clusterInfo = (ClusterInfo) clusters.get(source);
0578: if (clusterInfo == null) {
0579: System.err.println("No info for " + source);
0580: return null;
0581: }
0582: return new EventMonitorListener(clusterInfo, handlers, aReport);
0583: }
0584:
0585: public ConstraintElementListener createConstraintElementListener(
0586: String source, Object[] handlers,
0587: TaskConstraintsRequest aRequest) throws IOException {
0588: ClusterInfo clusterInfo = (ClusterInfo) clusters.get(source);
0589: if (clusterInfo == null) {
0590: System.err.println("No info for " + source);
0591: return null;
0592: }
0593: return new ConstraintElementListener(clusterInfo, handlers,
0594: aRequest);
0595: }
0596:
0597: /**
0598: * Before sending the first request, ask the user for the location
0599: * of a cluster. Get the list of URLs and clusters from there.
0600: **/
0601:
0602: private String getContactURL() {
0603: String s = (String) OptionPane
0604: .showInputDialog(
0605: getGUI(),
0606: "Enter location of a cluster Log Plan Server in the form host:port",
0607: "Cluster Location",
0608: OptionPane.INFORMATION_MESSAGE, null, null,
0609: "localhost:5555");
0610: if (s == null)
0611: System.exit(0); // if we don't know where the clusters are located, quit
0612: s = s.trim();
0613: if (s.length() == 0) {
0614: return "http://localhost:5555/";
0615: }
0616: int i = s.indexOf(":");
0617: if (i == -1) {
0618: return "http://" + s + ":5555/";
0619: }
0620: return "http://" + s + "/";
0621: }
0622:
0623: private void getClusterInfo(String url) {
0624: try {
0625: ConnectionHelper connection = new ConnectionHelper(url);
0626: Hashtable clusterURLs = connection.getClusterIdsAndURLs();
0627: if (clusterURLs == null) {
0628: throw new RuntimeException(
0629: "Unable to obtain cluster identifier to URL mappings.");
0630: }
0631: for (Iterator iter = clusterURLs.keySet().iterator(); iter
0632: .hasNext();) {
0633: String clusterName = (String) iter.next();
0634: String clusterURL = (String) clusterURLs
0635: .get(clusterName);
0636: ClusterInfo clusterInfo = new ClusterInfo(clusterName,
0637: clusterURL);
0638: clusters.put(clusterName, clusterInfo);
0639: }
0640: } catch (RuntimeException re) {
0641: throw re;
0642: } catch (Exception e) {
0643: clusters = null;
0644: throw new RuntimeException(e.toString());
0645: }
0646: }
0647:
0648: /**
0649: * Update the current execution time and rate.
0650: **/
0651: public void setExecutionTime(String theSource,
0652: ExecutionTimeStatus anExecutionTimeStatus) {
0653: ClusterInfo clusterInfo = (ClusterInfo) clusters.get(theSource);
0654: clusterInfo.theExecutionTimeStatus = anExecutionTimeStatus;
0655: updateExecutionTime();
0656: }
0657:
0658: /**
0659: * Called after a cluster's time status has changed to decide what
0660: * the effect of that change is to be on the event generator.
0661: * Generally, we accept the latest reported execution time, and use
0662: * its rate.
0663: **/
0664: private void updateExecutionTime() {
0665: synchronized (clusters) {
0666: ExecutionTimeStatus latestExecutionTimeStatus = null;
0667: for (Iterator i = clusters.values().iterator(); i.hasNext();) {
0668: ClusterInfo clusterInfo = (ClusterInfo) i.next();
0669: ExecutionTimeStatus this ExecutionTimeStatus = clusterInfo.theExecutionTimeStatus;
0670: if (this ExecutionTimeStatus == null) {
0671: continue; // Have not yet heard from this cluster
0672: }
0673: if (latestExecutionTimeStatus == null) {
0674: latestExecutionTimeStatus = this ExecutionTimeStatus;
0675: continue;
0676: }
0677: long this Time = this ExecutionTimeStatus.theExecutionTime;
0678: long thatTime = latestExecutionTimeStatus.theExecutionTime;
0679: if (this Time != thatTime) {
0680: if (this Time > thatTime) {
0681: latestExecutionTimeStatus = this ExecutionTimeStatus;
0682: }
0683: continue;
0684: }
0685: double this Rate = this ExecutionTimeStatus.theExecutionRate;
0686: double thatRate = latestExecutionTimeStatus.theExecutionRate;
0687: if (this Rate < thatRate) {
0688: latestExecutionTimeStatus = this ExecutionTimeStatus;
0689: }
0690: }
0691: if (latestExecutionTimeStatus == null) {
0692: return; // This probably never happens
0693: }
0694: theExecutionTime = latestExecutionTimeStatus.theExecutionTime;
0695: theExecutionRate = latestExecutionTimeStatus.theExecutionRate;
0696: checkTimeScript();
0697: }
0698: updateTimeGUI();
0699: if (!isPaused()) {
0700: advanceManagerTime();
0701: }
0702: }
0703:
0704: /**
0705: * Interpret the time script. If there is no time script, just
0706: * return. If this is there is no currently executing item, execute
0707: * the next (first) applicable item. If the there is a currently
0708: * executing item, see if the advancement is done and if so, execute
0709: * the next applicable item. An item is done if its endTime has been
0710: * reached or if the the execution rate has returned to 1.0 and the
0711: * endTime has been nearly reached.
0712: **/
0713: private void checkTimeScript() {
0714: if (timeScript == null)
0715: return;
0716: if (theExecutionRate != 1.0)
0717: timeScriptSawHighRate = true;
0718: if (timeScriptCurrentIndex < 0) {
0719: nextTimeScriptItem();
0720: } else {
0721: TimeScriptItem item = (TimeScriptItem) timeScript
0722: .get(timeScriptCurrentIndex);
0723: long timeRemaining = item.endTime - theExecutionTime;
0724: if (timeRemaining <= 0L || timeScriptSawHighRate
0725: && theExecutionRate == 1.0) {
0726: nextTimeScriptItem();
0727: }
0728: }
0729: }
0730:
0731: private void nextTimeScriptItem() {
0732: for (; timeScriptCurrentIndex < timeScript.size(); timeScriptCurrentIndex++) {
0733: if (timeScriptCurrentIndex < 0)
0734: continue; // Get off the snide
0735: TimeScriptItem item = (TimeScriptItem) timeScript
0736: .get(timeScriptCurrentIndex);
0737: System.out.println("nextTimeScriptItem: " + item);
0738: long timeRemaining = item.endTime - theExecutionTime;
0739: if (timeRemaining >= 0L) { // Do this one
0740: final SetExecutionTime set = SetExecutionTime
0741: .createRelativeInstance(timeRemaining, 1.0,
0742: item.elapsedTime);
0743: new Thread("Time Script Runner") {
0744: public void run() {
0745: send(set);
0746: }
0747: }.start();
0748: return; // Done for now.
0749: }
0750: timeScriptSawHighRate = false; // Done with this item
0751: }
0752: cancelTimeScript(); // Script is finished
0753: }
0754:
0755: public ScheduleManager findScheduleManager(Class managerClass) {
0756: for (Iterator i = scheduleManagers.iterator(); i.hasNext();) {
0757: ScheduleManager m = (ScheduleManager) i.next();
0758: if (m.getClass() == managerClass)
0759: return m;
0760: }
0761: return null;
0762: }
0763:
0764: private void advanceManagerTime() {
0765: for (Iterator i = scheduleManagers.iterator(); i.hasNext();) {
0766: ScheduleManager m = (ScheduleManager) i.next();
0767: m.advanceTime(theExecutionTime);
0768: }
0769: }
0770:
0771: public void setSchedulingLookAhead() {
0772: String lookAhead = (String) OptionPane.showInputDialog(
0773: theTimeGUI, "Enter scheduling lookahead (minutes): ",
0774: "Scheduling Lookahead", OptionPane.QUESTION_MESSAGE,
0775: null, null, new Long(getSchedulingLookAhead()
0776: / ONE_MINUTE));
0777: try {
0778: long newTime = new Long(lookAhead).longValue() * ONE_MINUTE;
0779: setSchedulingLookAhead(newTime);
0780: } catch (IllegalArgumentException iae) {
0781: postErrorMessage(theTimeGUI,
0782: "Input not recognized as a number");
0783: }
0784: }
0785:
0786: public void setSchedulingLookAhead(long newLookAhead) {
0787: theSchedulingLookAhead = newLookAhead;
0788: }
0789:
0790: public long getSchedulingLookAhead() {
0791: return theSchedulingLookAhead;
0792: }
0793:
0794: public long getExecutionTime() {
0795: if (theExecutionTime <= 0L) {
0796: throw new RuntimeException(
0797: "theExecutionTime has not been set");
0798: }
0799: return theExecutionTime;
0800: }
0801:
0802: public double getExecutionRate() {
0803: return theExecutionRate;
0804: }
0805:
0806: private void displayErrorString(String reply) {
0807: OptionPane.showOptionDialog(null, reply, reply,
0808: OptionPane.DEFAULT_OPTION, OptionPane.ERROR_MESSAGE,
0809: null, null, null);
0810: }
0811:
0812: private static void setGUIDefaults() {
0813: ThemeFactory.establishMetalTheme();
0814: EGTableModelBase.setWidths();
0815: }
0816:
0817: public String[] getClusterNames() {
0818: String[] result = new String[clusters.size()];
0819: Iterator values = clusters.values().iterator();
0820: for (int i = 0; i < result.length; i++) {
0821: result[i] = ((ClusterInfo) values.next()).theClusterName;
0822: }
0823: return result;
0824: }
0825:
0826: public void restore() {
0827: String prefix = getClass().getName() + ".";
0828: Properties props = new Properties();
0829: try {
0830: props.load(new FileInputStream("eg.properties"));
0831: for (Iterator managers = scheduleManagers.iterator(); managers
0832: .hasNext();) {
0833: ScheduleManager manager = (ScheduleManager) managers
0834: .next();
0835: manager.restore(props, prefix);
0836: }
0837: } catch (IOException ioe) {
0838: }
0839: }
0840:
0841: public boolean shutDown() {
0842: String prefix = getClass().getName() + ".";
0843: Properties props = new Properties();
0844: for (Iterator managers = scheduleManagers.iterator(); managers
0845: .hasNext();) {
0846: ScheduleManager manager = (ScheduleManager) managers.next();
0847: manager.save(props, prefix);
0848: }
0849: try {
0850: props.store(new FileOutputStream("eg.properties"),
0851: "Event Generator Properties");
0852: } catch (IOException ioe) {
0853: postErrorMessage(getGUI(), "Failed to write eg.properties"
0854: + ioe);
0855: }
0856: return true;
0857: }
0858:
0859: private static HashSet plugIns = new HashSet();
0860:
0861: /**
0862: * Add plugins found in a Properties object.
0863: **/
0864: private static void addPlugins(Properties props) {
0865: String prefix = EventGenerator.class.getName() + ".plugin.";
0866: for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
0867: String key = (String) e.nextElement();
0868: String line = "";
0869: if (key.startsWith(prefix)) {
0870: try {
0871: line = props.getProperty(key);
0872: addPlugin(line);
0873: } catch (ClassNotFoundException cnfe) {
0874: System.err.println("Plugin class not found: "
0875: + line);
0876: }
0877: }
0878: }
0879: }
0880:
0881: /**
0882: * Add plugins found listed in a file
0883: **/
0884: private static void addPlugins(String filename) {
0885: int n = 0;
0886: try {
0887: BufferedReader reader = new BufferedReader(new FileReader(
0888: filename));
0889: try {
0890: String line;
0891: while ((line = reader.readLine()) != null) {
0892: try {
0893: addPlugin(line);
0894: } catch (ClassNotFoundException cnfe) {
0895: System.err.println("Plugin class not found: "
0896: + line);
0897: }
0898: }
0899: } finally {
0900: reader.close();
0901: }
0902: } catch (Exception e) {
0903: System.err.println("addPlugins:" + e);
0904: }
0905: }
0906:
0907: private static void addPlugin(String plugInSpecification)
0908: throws ClassNotFoundException {
0909: plugIns.add(new PluginSpecification(plugInSpecification));
0910: }
0911:
0912: /**
0913: * Get iterator of all plugin specifications that implement the given interface.
0914: **/
0915: public Iterator getPluginSpecifications(final Class interfaceClass) {
0916: return new FilteredIterator(plugIns.iterator(),
0917: new UnaryPredicate() {
0918: public boolean execute(Object o) {
0919: return interfaceClass
0920: .isAssignableFrom(((PluginSpecification) o)
0921: .getPluginClass());
0922: }
0923: });
0924: }
0925:
0926: private static List createTimeScript(File file) {
0927: List script = new ArrayList();
0928: try {
0929: BufferedReader reader = new BufferedReader(new FileReader(
0930: file));
0931: try {
0932: String line;
0933: TimeScriptItem prev = null;
0934: while ((line = reader.readLine()) != null) {
0935: try {
0936: TimeScriptItem item = new TimeScriptItem(line);
0937: System.out.println("createTimeScript: " + item);
0938: if (prev != null
0939: && item.endTime <= prev.endTime) {
0940: throw new RuntimeException(
0941: "Time script start times not monotonic increasing");
0942: }
0943: script.add(item);
0944: prev = item;
0945: } catch (RuntimeException cnfe) {
0946: System.err.println(cnfe + ": " + line);
0947: }
0948: }
0949: if (script.isEmpty())
0950: return null;
0951: return script;
0952: } finally {
0953: reader.close();
0954: }
0955: } catch (Exception e) {
0956: e.printStackTrace();
0957: return null;
0958: }
0959: }
0960:
0961: /**
0962: * If org.cougaar.useBootstrapper is true, will search for installed jar files
0963: * in order to load all classes. Otherwise, will rely solely on classpath.
0964: *
0965: **/
0966: public static void main(String[] args) {
0967: if ("true".equals(System.getProperty(
0968: "org.cougaar.useBootstrapper", "true"))) {
0969: org.cougaar.bootstrap.Bootstrapper.launch(
0970: EventGenerator.class.getName(), args);
0971: } else {
0972: launch(args);
0973: }
0974: }
0975:
0976: private static class TimeGUIListener extends MouseAdapter implements
0977: MouseListener, MouseMotionListener {
0978: JComponent component;
0979: JComponent container;
0980: Point startLocation;
0981: Point startPoint;
0982:
0983: public TimeGUIListener(JComponent component,
0984: JComponent container) {
0985: this .component = component;
0986: this .container = container;
0987: }
0988:
0989: public void mousePressed(MouseEvent e) {
0990: startPoint = e.getPoint();
0991: SwingUtilities.convertPointToScreen(startPoint, e
0992: .getComponent());
0993: startLocation = component.getLocation();
0994: }
0995:
0996: private void moveTo(MouseEvent e) {
0997: Point newPoint = e.getPoint();
0998: SwingUtilities.convertPointToScreen(newPoint, e
0999: .getComponent());
1000: int dx = newPoint.x - startPoint.x;
1001: int dy = newPoint.y - startPoint.y;
1002: component.setLocation(startLocation.x + dx, startLocation.y
1003: + dy);
1004: forceComponentInWindow(component, container);
1005: }
1006:
1007: public void mouseDragged(MouseEvent e) {
1008: if (startPoint != null)
1009: moveTo(e);
1010: }
1011:
1012: public void mouseClicked(MouseEvent e) {
1013: startPoint = null;
1014: }
1015:
1016: public void mouseReleased(MouseEvent e) {
1017: if (startPoint != null) {
1018: moveTo(e);
1019: startPoint = null;
1020: }
1021: }
1022:
1023: public void mouseMoved(MouseEvent e) {
1024: }
1025: }
1026:
1027: private static void forceComponentInWindow(JComponent tp,
1028: JComponent lp) {
1029: Dimension d = lp.getSize();
1030: Rectangle r = tp.getBounds();
1031: boolean changed = false;
1032: if (r.x < 0) {
1033: r.x = 0;
1034: changed = true;
1035: }
1036: if (r.x + r.width > d.width) {
1037: r.x = d.width - r.width;
1038: changed = true;
1039: }
1040: if (r.y < 0) {
1041: r.y = 0;
1042: changed = true;
1043: }
1044: if (r.y + r.height > d.height) {
1045: r.y = d.height - r.height;
1046: changed = true;
1047: }
1048: if (changed)
1049: tp.setLocation(r.x, r.y);
1050: }
1051:
1052: static public void launch(String[] args) {
1053: List timeScript = null;
1054: for (int i = 0; i < args.length; i++) {
1055: if (args[i].equals("-demo")) {
1056: setGUIDefaults();
1057: continue;
1058: }
1059: if (args[i].equals("-plugins")) {
1060: addPlugins(args[++i]);
1061: continue;
1062: }
1063: if (args[i].equals("-time")) {
1064: timeScript = createTimeScript(new File(args[++i]));
1065: continue;
1066: }
1067: System.err.println("Unrecognized argument: " + args[i]);
1068: }
1069: addPlugins(System.getProperties()); // Add plugins specified as system properties
1070: final EventGenerator eventGenerator = new EventGenerator();
1071: JFrame frame = new JFrame("COUGAAR Event Generator");
1072: frame.setContentPane(eventGenerator.getGUI());
1073: frame.setJMenuBar(eventGenerator.getJMenuBar());
1074: eventGenerator.setTimeScript(timeScript);
1075: final JComponent timeGUIPanel = eventGenerator.getTimeGUI();
1076: timeGUIPanel.setBackground(new Color(250, 240, 192));
1077: timeGUIPanel
1078: .setBorder(BorderFactory.createLoweredBevelBorder());
1079: final JLayeredPane lp = frame.getLayeredPane();
1080: final TimeGUIListener listener = new TimeGUIListener(
1081: timeGUIPanel, lp);
1082: lp.add(timeGUIPanel, new Integer(1000));
1083: timeGUIPanel.addMouseListener(listener);
1084: timeGUIPanel.addMouseMotionListener(listener);
1085: lp.addComponentListener(new ComponentAdapter() {
1086: public void componentResized(ComponentEvent e) {
1087: forceComponentInWindow(timeGUIPanel, lp);
1088: }
1089: });
1090: timeGUIPanel.setSize(timeGUIPanel.getPreferredSize());
1091: frame.addWindowListener(new WindowAdapter() {
1092: public void windowClosing(WindowEvent e) {
1093: if (eventGenerator.shutDown()) {
1094: System.exit(0);
1095: }
1096: }
1097: });
1098: forceComponentInWindow(timeGUIPanel, lp);
1099: frame.pack();
1100: frame.setState(frame.ICONIFIED);
1101: timeGUIPanel.setLocation(10000, 0);
1102: frame.show();
1103: eventGenerator.initialize();
1104: frame.setState(frame.NORMAL);
1105: eventGenerator.startListeners();
1106: }
1107: }
|