0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: /**
0043: * @author Ana von Klopp
0044: */package org.netbeans.modules.web.monitor.client;
0045:
0046: import java.util.ArrayList;
0047: import java.util.Comparator;
0048: import java.util.Date;
0049: import java.util.Enumeration;
0050: import java.util.Hashtable;
0051: import java.util.List;
0052: import java.util.Vector;
0053: import java.util.Iterator;
0054: import java.io.File;
0055: import java.io.FileNotFoundException;
0056: import java.io.InputStreamReader;
0057: import java.io.IOException;
0058: import java.io.OutputStream;
0059: import java.io.PrintWriter;
0060: import java.net.InetAddress;
0061: import java.net.MalformedURLException;
0062: import java.net.Socket;
0063: import java.net.UnknownHostException;
0064: import java.net.URL;
0065: import java.util.logging.Level;
0066: import java.util.logging.Logger;
0067:
0068: import javax.swing.SwingUtilities;
0069:
0070: import org.openide.DialogDisplayer;
0071: import org.openide.NotifyDescriptor;
0072: import org.openide.awt.HtmlBrowser;
0073: import org.openide.filesystems.FileAlreadyLockedException;
0074: import org.openide.filesystems.FileObject;
0075: import org.openide.filesystems.FileLock;
0076: import org.openide.filesystems.FileUtil;
0077: import org.openide.filesystems.FileSystem;
0078: import org.openide.filesystems.Repository;
0079: import org.openide.filesystems.URLMapper;
0080: import org.openide.nodes.Node;
0081: import org.openide.nodes.AbstractNode;
0082: import org.openide.nodes.Children;
0083: import org.openide.util.NbBundle;
0084: import org.openide.util.RequestProcessor;
0085:
0086: import org.netbeans.modules.web.monitor.data.*;
0087:
0088: class Controller {
0089:
0090: // REPLAY strings - must be coordinated with server.MonitorFilter
0091: final static String REPLAY = "netbeans.replay"; //NOI18N
0092: final static String PORT = "netbeans.replay.port"; //NOI18N
0093: final static String REPLAYSTATUS = "netbeans.replay.status"; //NOI18N
0094: final static String REPLAYSESSION = "netbeans.replay.session"; //NOI18N
0095: static final boolean debug = false;
0096: //private transient static boolean starting = true;
0097:
0098: // Test server location and port
0099: // Should use InetAddress.getLocalhost() instead
0100: private transient static String server = "localhost"; //NOI18N
0101: private transient static int port = 8080;
0102:
0103: // Location of the files
0104: private static FileObject monDir = null;
0105: private static FileObject currDir = null;
0106: private static FileObject saveDir = null;
0107: private static FileObject replayDir = null;
0108:
0109: final static String monDirStr = "HTTPMonitor"; // NOI18N
0110: final static String currDirStr = "current"; // NOI18N
0111: final static String saveDirStr = "save"; // NOI18N
0112: final static String replayDirStr = "replay"; // NOI18N
0113:
0114: // Constant nodes etc we need to know about
0115: private transient NavigateNode root = null;
0116: private Children.SortedArray currTrans = null;
0117: private Children.SortedArray savedTrans = null;
0118:
0119: // These are the ones that should go.
0120: private Hashtable currBeans = null;
0121: private Hashtable saveBeans = null;
0122:
0123: private transient Comparator comp = null;
0124:
0125: private boolean useBrowserCookie = true;
0126:
0127: private static Controller instance = null;
0128: private Date startDate;
0129:
0130: private Controller() {
0131: // TODO: setting the startup date to 30s earlier from now to prevent deletion of the
0132: // first request (#56880), the ideal fix should be to use the IDE startup time
0133: startDate = new Date(System.currentTimeMillis() - 30000);
0134: currBeans = new Hashtable();
0135: saveBeans = new Hashtable();
0136: createNodeStructure();
0137: /*
0138: registerBrowserListener();
0139: */
0140: }
0141:
0142: static Controller getInstance() {
0143: if (instance == null)
0144: instance = new Controller();
0145: return instance;
0146: }
0147:
0148: /**
0149: * Invoked at startup, creates the root folder and the folder for
0150: * current and saved transactions (and their children arrays).
0151: */
0152: private void createNodeStructure() {
0153:
0154: comp = new CompTime(true);
0155: currTrans = new Children.SortedArray();
0156: currTrans.setComparator(comp);
0157: savedTrans = new Children.SortedArray();
0158: savedTrans.setComparator(comp);
0159:
0160: CurrNode currNode = new CurrNode(currTrans);
0161: SavedNode savedNode = new SavedNode(savedTrans);
0162:
0163: Node[] kids = new Node[2];
0164: kids[0] = currNode;
0165: kids[1] = savedNode;
0166:
0167: Children children = new Children.Array();
0168: children.add(kids);
0169: root = new NavigateNode(children);
0170:
0171: }
0172:
0173: /**
0174: * Adds a transaction to the list of current transactions.
0175: */
0176: void addTransaction(String id) {
0177:
0178: if (debug)
0179: log("Creating node for " + id);
0180: TransactionNode[] nodes = new TransactionNode[1];
0181: MonitorData md = retrieveMonitorData(id, currDirStr);
0182: try {
0183: nodes[0] = createTransactionNode(md, true);
0184: currTrans.add(nodes);
0185: } catch (Exception ex) {
0186: // If there is some kind of parsing exception, do nothing
0187: }
0188: }
0189:
0190: /**
0191: * Adds a transaction to the list of current transactions.
0192: */
0193: protected NavigateNode getRoot() {
0194: return root;
0195: }
0196:
0197: protected static FileObject getMonDir()
0198: throws FileNotFoundException {
0199:
0200: if (monDir == null || !monDir.isFolder()) {
0201: try {
0202: createDirectories();
0203: } catch (FileNotFoundException ex) {
0204: throw ex;
0205: }
0206: }
0207: return monDir;
0208: }
0209:
0210: protected static FileObject getCurrDir()
0211: throws FileNotFoundException {
0212:
0213: if (currDir == null || !currDir.isFolder()) {
0214: try {
0215: createDirectories();
0216: } catch (FileNotFoundException ex) {
0217: throw ex;
0218: }
0219: }
0220: return currDir;
0221: }
0222:
0223: protected static FileObject getReplayDir()
0224: throws FileNotFoundException {
0225:
0226: if (replayDir == null || !replayDir.isFolder()) {
0227: try {
0228: createDirectories();
0229: } catch (FileNotFoundException ex) {
0230: throw ex;
0231: }
0232: }
0233: return replayDir;
0234: }
0235:
0236: protected static FileObject getSaveDir()
0237: throws FileNotFoundException {
0238:
0239: if (saveDir == null || !saveDir.isFolder()) {
0240: try {
0241: createDirectories();
0242: } catch (FileNotFoundException ex) {
0243: throw ex;
0244: }
0245: }
0246: return saveDir;
0247: }
0248:
0249: boolean haveDirectories() {
0250: if (currDir == null) {
0251: try {
0252: currDir = getCurrDir();
0253: } catch (Exception ex) {
0254: return false;
0255: }
0256: }
0257:
0258: if (saveDir == null) {
0259: try {
0260: saveDir = getSaveDir();
0261: } catch (Exception ex) {
0262: return false;
0263: }
0264: }
0265: return true;
0266: }
0267:
0268: private static void createDirectories()
0269: throws FileNotFoundException {
0270:
0271: if (debug)
0272: log("Now in createDirectories()"); // NOI18N
0273:
0274: FileObject rootdir = Repository.getDefault()
0275: .getDefaultFileSystem().getRoot();
0276: if (debug) {
0277: log("Root directory is " + rootdir.getName()); // NOI18N
0278: File rootF = FileUtil.toFile(rootdir);
0279: log("Root directory abs path " + // NOI18N
0280: rootF.getAbsolutePath());
0281: }
0282:
0283: FileLock lock = null;
0284:
0285: if (monDir == null || !monDir.isFolder()) {
0286: try {
0287: monDir = rootdir.getFileObject(monDirStr);
0288: } catch (Exception ex) {
0289: }
0290:
0291: if (monDir == null || !monDir.isFolder()) {
0292: if (monDir != null) {
0293: try {
0294: lock = monDir.lock();
0295: monDir.delete(lock);
0296: } catch (FileAlreadyLockedException falex) {
0297: throw new FileNotFoundException();
0298: } catch (IOException ex) {
0299: throw new FileNotFoundException();
0300: } finally {
0301: if (lock != null)
0302: lock.releaseLock();
0303: }
0304: }
0305: try {
0306: monDir = rootdir.createFolder(monDirStr);
0307: } catch (IOException ioex) {
0308: if (debug)
0309: ioex.printStackTrace();
0310: }
0311: }
0312: if (monDir == null || !monDir.isFolder())
0313: throw new FileNotFoundException();
0314: }
0315:
0316: if (debug)
0317: log("monitor directory is " + monDir.getName());// NOI18N
0318:
0319: // Current directory
0320:
0321: if (currDir == null || !currDir.isFolder()) {
0322:
0323: try {
0324: currDir = monDir.getFileObject(currDirStr);
0325: } catch (Exception ex) {
0326: }
0327:
0328: if (currDir == null || !currDir.isFolder()) {
0329: lock = null;
0330: if (currDir != null) {
0331: try {
0332: lock = currDir.lock();
0333: currDir.delete(lock);
0334: } catch (FileAlreadyLockedException falex) {
0335: throw new FileNotFoundException();
0336: } catch (IOException ex) {
0337: throw new FileNotFoundException();
0338: } finally {
0339: if (lock != null)
0340: lock.releaseLock();
0341: }
0342: }
0343: try {
0344: currDir = monDir.createFolder(currDirStr);
0345: } catch (IOException ex) {
0346: if (debug)
0347: ex.printStackTrace();
0348: }
0349: }
0350: if (currDir == null || !currDir.isFolder())
0351: throw new FileNotFoundException();
0352: }
0353:
0354: if (debug)
0355: log("curr directory is " + currDir.getName()); // NOI18N
0356:
0357: // Save Directory
0358: if (saveDir == null || !saveDir.isFolder()) {
0359: try {
0360: saveDir = monDir.getFileObject(saveDirStr);
0361: } catch (Exception ex) {
0362: }
0363:
0364: if (saveDir == null || !saveDir.isFolder()) {
0365: if (saveDir != null) {
0366: lock = null;
0367: try {
0368: lock = saveDir.lock();
0369: saveDir.delete(lock);
0370: } catch (FileAlreadyLockedException falex) {
0371: throw new FileNotFoundException();
0372: } catch (IOException ex) {
0373: throw new FileNotFoundException();
0374: } finally {
0375: if (lock != null)
0376: lock.releaseLock();
0377: }
0378: }
0379: try {
0380: saveDir = monDir.createFolder(saveDirStr);
0381: } catch (IOException ex) {
0382: if (debug)
0383: ex.printStackTrace();
0384: }
0385: }
0386: if (saveDir == null || !saveDir.isFolder())
0387: throw new FileNotFoundException();
0388:
0389: if (debug)
0390: log("save directory is " + saveDir.getName()); // NOI18N
0391: }
0392:
0393: // Replay Directory
0394:
0395: if (replayDir == null || !replayDir.isFolder()) {
0396:
0397: try {
0398: replayDir = monDir.getFileObject(replayDirStr);
0399: } catch (Exception ex) {
0400: }
0401:
0402: if (replayDir == null || !replayDir.isFolder()) {
0403: if (replayDir != null) {
0404: lock = null;
0405: try {
0406: lock = replayDir.lock();
0407: replayDir.delete(lock);
0408: } catch (FileAlreadyLockedException falex) {
0409: throw new FileNotFoundException();
0410: } catch (IOException ex) {
0411: throw new FileNotFoundException();
0412: } finally {
0413: if (lock != null)
0414: lock.releaseLock();
0415: }
0416: }
0417: try {
0418: replayDir = monDir.createFolder(replayDirStr);
0419: } catch (Exception ex) {
0420: if (debug)
0421: ex.printStackTrace();
0422: }
0423: }
0424: if (replayDir == null || !replayDir.isFolder())
0425: throw new FileNotFoundException();
0426:
0427: if (debug)
0428: log("replay directory is " + replayDir.getName());// NOI18N
0429: }
0430: }
0431:
0432: /**
0433: * Invoked by ReplayAction. Replays the transaction corresponding to
0434: * the selected node.
0435: *
0436: * PENDING - it would be better if the nodes know which server
0437: * they were processed on. This would be the case if we listed the
0438: * nodes separately depending on the server that collected the
0439: * data.
0440: *
0441: */
0442: void replayTransaction(Node node) {
0443:
0444: if (debug)
0445: log("replayTransaction(Node node) from node "
0446: + node.getName()); // NOI18N
0447:
0448: if (!checkServer(true))
0449: return;
0450:
0451: TransactionNode tn = null;
0452: try {
0453: tn = (TransactionNode) node;
0454: } catch (ClassCastException cce) {
0455: if (debug)
0456: log("Selected node was not a transaction node");//NOI18N
0457: return;
0458: }
0459:
0460: MonitorData md = getMonitorData(tn, false, false);
0461: if (md == null) {
0462: String msg = NbBundle.getMessage(Controller.class,
0463: "MSG_NoMonitorData");
0464: Logger.getLogger("global").log(Level.INFO, msg);
0465: return;
0466: }
0467: if (!useBrowserCookie)
0468: md.getRequestData().setReplaceSessionCookie(true);
0469:
0470: if (debug) {
0471: log("Replace is " + // NOI18N
0472: String.valueOf(md.getRequestData()
0473: .getReplaceSessionCookie()));
0474: String fname = md.createTempFile("control-replay.xml"); // NOI18N
0475: log("Wrote replay data to " + fname);// NOI18N
0476: }
0477:
0478: String status;
0479: if (tn.isCurrent())
0480: status = currDirStr;
0481: else
0482: status = saveDirStr;
0483: try {
0484: replayTransaction(md, status);
0485: } catch (UnknownHostException uhe) {
0486: // Notify the user that there is no host
0487:
0488: Object[] options = { NbBundle.getBundle(Controller.class)
0489: .getString("MON_OK"), };
0490:
0491: NotifyDescriptor noServerDialog = new NotifyDescriptor(
0492: NbBundle.getMessage(Controller.class,
0493: "MON_Exec_server_no_host", md
0494: .getServerName()), NbBundle
0495: .getBundle(Controller.class).getString(
0496: "MON_Exec_server"),
0497: NotifyDescriptor.DEFAULT_OPTION,
0498: NotifyDescriptor.INFORMATION_MESSAGE, options,
0499: options[0]);
0500: DialogDisplayer.getDefault().notify(noServerDialog);
0501:
0502: } catch (IOException ioe) {
0503:
0504: if (debug) {
0505: log(ioe.getMessage());
0506: ioe.printStackTrace();
0507: }
0508:
0509: // Notify the user that the server is not running
0510: Object[] options = { NbBundle.getBundle(Controller.class)
0511: .getString("MON_OK"), };
0512:
0513: NotifyDescriptor noServerDialog = new NotifyDescriptor(
0514: NbBundle.getMessage(Controller.class,
0515: "MON_Exec_server_start", md
0516: .getServerAndPort()), NbBundle
0517: .getBundle(Controller.class).getString(
0518: "MON_Exec_server"),
0519: NotifyDescriptor.DEFAULT_OPTION,
0520: NotifyDescriptor.INFORMATION_MESSAGE, options,
0521: options[0]);
0522: DialogDisplayer.getDefault().notify(noServerDialog);
0523: }
0524: }
0525:
0526: /**
0527: * Invoked by EditPanel. Replays the transaction corresponding to
0528: * the selected node.
0529: */
0530: void replayTransaction(MonitorData md) throws UnknownHostException,
0531: IOException {
0532:
0533: // PENDING - can't make UI changes right now for Sierra
0534: // any exception thrown in this method indicates that we
0535: // couldn't even get to the monitor data, and we should add an
0536: // additional panel to that effect. Also, unreadable monitor
0537: // data should cause the transaction to be removed from the
0538: // pane.
0539:
0540: if (debug)
0541: log("replayTransaction(MonitorData md)"); //NOI18N
0542:
0543: FileObject fo;
0544: FileLock lock = null;
0545: OutputStream out = null;
0546: PrintWriter pw = null;
0547:
0548: if (debug)
0549: log("Creating record for replay"); //NOI18N
0550:
0551: String id = md.getAttributeValue("id"); // NOI18N
0552:
0553: try {
0554: // This will fail if the file already exists. This can
0555: // happen if the replay previously failed because the
0556: // server was not running. This is dealt with in the
0557: // catch clause below.
0558: fo = getReplayDir().createData(id, "xml"); //NOI18N
0559: if (debug)
0560: log(" Created file for replay data");
0561: } catch (IOException ioex) {
0562:
0563: try {
0564: fo = getReplayDir().getFileObject(id, "xml");
0565: } catch (IllegalArgumentException iaex) {
0566: // This is only thrown if getReplayDir() is not a
0567: // folder. This should not happen.
0568: throw new IOException("No replay dir");
0569: }
0570:
0571: if (!fo.isData()) {
0572: throw new IOException("Can't create file, giving up");
0573: }
0574:
0575: try {
0576: lock = fo.lock();
0577: } catch (FileAlreadyLockedException falex) {
0578: throw new IOException("Old file exist, islocked");
0579: }
0580:
0581: try {
0582: fo.delete(lock);
0583: } catch (IOException ioex2) {
0584: throw new IOException("Couldn't delete old file");
0585: } finally {
0586: if (lock != null)
0587: lock.releaseLock();
0588: }
0589:
0590: try {
0591: fo = getReplayDir().createData(id, "xml"); //NOI18N
0592: } catch (IOException ioex2) {
0593: if (debug)
0594: log(" Couldn't create file for replay data");
0595: throw ioex2;
0596: }
0597: }
0598:
0599: try {
0600: lock = fo.lock();
0601: } catch (FileAlreadyLockedException fale) {
0602: if (debug)
0603: log("Can't get a file lock for the replay file");
0604: throw new IOException();
0605: }
0606:
0607: try {
0608: out = fo.getOutputStream(lock);
0609: pw = new PrintWriter(out);
0610: md.write(pw);
0611: if (debug)
0612: log("...record complete"); //NOI18N
0613:
0614: if (debug) {
0615: String fname = md.createTempFile("control-record.xml"); // NOI18N
0616: log("Wrote replay data to " + fname); // NOI18N
0617: }
0618: } catch (IOException ioex) {
0619: throw ioex;
0620: } finally {
0621: if (lock != null)
0622: lock.releaseLock();
0623: try {
0624: pw.close();
0625: } catch (Throwable t) {
0626: }
0627: try {
0628: out.close();
0629: } catch (Throwable t) {
0630: }
0631: }
0632:
0633: try {
0634: replayTransaction(md, replayDirStr);
0635: } catch (UnknownHostException uhe) {
0636: throw uhe;
0637: } catch (IOException ioe) {
0638: throw ioe;
0639: }
0640: }
0641:
0642: /**
0643: *
0644: */
0645: void replayTransaction(MonitorData md, String status)
0646: throws UnknownHostException, IOException {
0647:
0648: if (debug)
0649: log("replayTransaction(MonitorData md, String status )"); //NOI18N
0650:
0651: URL url = null;
0652: try {
0653: String name = md.getServerName();
0654: int port = md.getServerPort();
0655:
0656: StringBuffer uriBuf = new StringBuffer(128);
0657: uriBuf.append(md.getRequestData().getAttributeValue("uri")); //NOI18N
0658: uriBuf.append("?"); //NOI18N
0659: uriBuf.append(REPLAY);
0660: uriBuf.append("="); //NOI18N
0661: uriBuf.append(md.getAttributeValue("id")); //NOI18N
0662: uriBuf.append("&"); //NOI18N
0663: uriBuf.append(REPLAYSTATUS);
0664: uriBuf.append("="); //NOI18N
0665: uriBuf.append(status);
0666:
0667: String portS = null;
0668: try {
0669: FileObject fo = Repository.getDefault()
0670: .getDefaultFileSystem().getRoot();
0671: URL u = getSampleHTTPServerURL();
0672: portS = String
0673: .valueOf(u.getPort()/*HttpServer.getRepositoryRoot().getPort()*/);
0674: } catch (Exception ex) {
0675: // No internal HTTP server, do nothing
0676: }
0677: if (portS != null) {
0678: uriBuf.append("&"); //NOI18N
0679: uriBuf.append(PORT);
0680: uriBuf.append("="); //NOI18N
0681: uriBuf.append(portS);
0682: }
0683:
0684: if (md.getRequestData().getReplaceSessionCookie()) {
0685: uriBuf.append("&"); //NOI18N
0686: uriBuf.append(REPLAYSESSION);
0687: uriBuf.append("="); //NOI18N
0688: uriBuf.append(md.getRequestData().getSessionID());
0689: }
0690: url = new URL("http", name, port, uriBuf.toString()); //NOI18N
0691: } catch (MalformedURLException me) {
0692: if (debug)
0693: log(me.getMessage());
0694: } catch (NumberFormatException ne) {
0695: if (debug)
0696: log(ne.getMessage());
0697: }
0698:
0699: // Send the url to the browser.
0700: try {
0701: showReplay(url);
0702: } catch (UnknownHostException uhe) {
0703: throw uhe;
0704: } catch (IOException ioe) {
0705: throw ioe;
0706: }
0707: }
0708:
0709: void saveTransaction(Node[] nodes) {
0710:
0711: if (!haveDirectories()) {
0712: // PENDING - report the error properly
0713: // This should not happen
0714: log("Couldn't get the directory"); //NOI18N
0715: return;
0716: }
0717:
0718: Node[] newNodes = new Node[nodes.length];
0719: TransactionNode mvNode;
0720: String id;
0721:
0722: boolean error = false;
0723:
0724: for (int i = 0; i < nodes.length; ++i) {
0725:
0726: mvNode = (TransactionNode) nodes[i];
0727: id = mvNode.getID();
0728:
0729: if (debug)
0730: log(" Saving " + id); //NOI18N
0731:
0732: if (currBeans.containsKey(id))
0733: saveBeans.put(id, currBeans.remove(id));
0734:
0735: // Note I didn't load the bean here yet. Will only do that
0736: // if the data is displayed.
0737:
0738: FileLock lock = null;
0739: try {
0740: FileObject fold = currDir.getFileObject(id, "xml"); //NOI18N
0741: lock = fold.lock();
0742: fold.copy(saveDir, id, "xml"); //NOI18N
0743: if (debug)
0744: log(fold.getName());
0745: fold.delete(lock);
0746: mvNode.setCurrent(false);
0747: newNodes[i] = mvNode;
0748: } catch (FileAlreadyLockedException falex) {
0749: error = true;
0750: // PENDING report properly
0751: } catch (IOException ioex) {
0752: error = true;
0753: // PENDING report properly
0754: } catch (Exception ex) {
0755: error = true;
0756: // PENDING report properly
0757: } finally {
0758: if (lock != null)
0759: lock.releaseLock();
0760: }
0761:
0762: }
0763: if (!error)
0764: currTrans.remove(nodes);
0765: savedTrans.add(newNodes);
0766: }
0767:
0768: /**
0769: * Invoked by DeleteAction. Deletes a saved transaction
0770: */
0771:
0772: void deleteTransaction(final Node[] nodes) {
0773:
0774: if (!haveDirectories()) {
0775: // PENDING - report the error property
0776: // This should not happen
0777: log("Couldn't get the directory"); //NOI18N
0778: return;
0779: }
0780:
0781: // PENDING
0782: if ((nodes == null) || (nodes.length == 0))
0783: return;
0784:
0785: final ProgressMonitor progressMonitor = new ProgressMonitor();
0786:
0787: RequestProcessor.getDefault().post(new Runnable() {
0788: public void run() {
0789: // give awt thread chance to draw the progress monitor
0790: Thread.yield();
0791: // remove nodes
0792: currTrans.remove(nodes);
0793: savedTrans.remove(nodes);
0794:
0795: int oldValue = 0;
0796: for (int i = 0; i < nodes.length; i++) {
0797: TransactionNode node = (TransactionNode) nodes[i];
0798: FileObject fileObject = null;
0799: if (node.isCurrent()) {
0800: String id = node.getID();
0801: fileObject = currDir.getFileObject(id, "xml");
0802: currBeans.remove(id);
0803: } else {
0804: String id = node.getID();
0805: fileObject = saveDir.getFileObject(id, "xml");
0806: saveBeans.remove(id);
0807: }
0808: if (fileObject != null) {
0809: // delete the file
0810: FileLock lock = null;
0811: try {
0812: lock = fileObject.lock();
0813: fileObject.delete(lock);
0814: } catch (FileAlreadyLockedException falex) {
0815: Logger.getLogger("global").log(Level.INFO,
0816: null, falex);
0817: } catch (IOException exception) {
0818: Logger.getLogger("global").log(Level.INFO,
0819: null, exception);
0820: } finally {
0821: if (lock != null) {
0822: lock.releaseLock();
0823: }
0824: }
0825: }
0826: // update the progress monitor if needed
0827: final int newValue = 100 * (i + 1) / nodes.length;
0828: if (newValue > oldValue) {
0829: oldValue = newValue;
0830: SwingUtilities.invokeLater(new Runnable() {
0831: public void run() {
0832: progressMonitor.setValue(newValue);
0833: }
0834: });
0835: }
0836: }
0837: SwingUtilities.invokeLater(new Runnable() {
0838: public void run() {
0839: progressMonitor.close();
0840: }
0841: });
0842: }
0843: });
0844: progressMonitor.setVisible(true);
0845: }
0846:
0847: void deleteDirectory(String dir) {
0848:
0849: if (!haveDirectories()) {
0850: // PENDING - report the error property
0851: // This should not happen
0852: log("Couldn't get the directory"); //NOI18N
0853: return;
0854: }
0855:
0856: final FileObject directory;
0857: if (dir.equals(saveDirStr)) {
0858: directory = saveDir;
0859: savedTrans.remove(savedTrans.getNodes());
0860: saveBeans.clear();
0861: }
0862:
0863: else {
0864: directory = currDir;
0865: currTrans.remove(currTrans.getNodes());
0866: currBeans.clear();
0867: }
0868: if (directory.getChildren().length == 0) {
0869: return;
0870: }
0871: final ProgressMonitor progressMonitor = new ProgressMonitor();
0872:
0873: RequestProcessor.getDefault().post(new Runnable() {
0874: public void run() {
0875: Thread.yield();
0876:
0877: int number = directory.getChildren().length;
0878: int oldValue = -1;
0879: int i = 0;
0880:
0881: for (Enumeration e = directory.getData(false); e
0882: .hasMoreElements(); ++i) {
0883: FileObject fo = (FileObject) e.nextElement();
0884: FileLock lock = null;
0885: try {
0886: lock = fo.lock();
0887: fo.delete(lock);
0888: } catch (FileAlreadyLockedException falex) {
0889: Logger.getLogger("global").log(Level.INFO,
0890: null, falex);
0891: } catch (IOException exception) {
0892: Logger.getLogger("global").log(Level.INFO,
0893: null, exception);
0894: } finally {
0895: if (lock != null) {
0896: lock.releaseLock();
0897: }
0898: }
0899: // update the progress monitor if needed
0900: final int newValue = 100 * i / number;
0901: if (newValue > oldValue) {
0902: oldValue = newValue;
0903: SwingUtilities.invokeLater(new Runnable() {
0904: public void run() {
0905: progressMonitor.setValue(newValue);
0906: }
0907: });
0908: }
0909: }
0910: SwingUtilities.invokeLater(new Runnable() {
0911: public void run() {
0912: progressMonitor.close();
0913: }
0914: });
0915: }
0916: });
0917: progressMonitor.setVisible(true);
0918: }
0919:
0920: void deleteTransactions() {
0921: deleteDirectory(Constants.Files.save);
0922: deleteDirectory(Constants.Files.current);
0923: savedTrans.remove(savedTrans.getNodes());
0924: currTrans.remove(currTrans.getNodes());
0925: }
0926:
0927: void getTransactions() {
0928:
0929: if (debug)
0930: log("getTransactions"); //NOI18N
0931:
0932: if (!haveDirectories()) {
0933: // PENDING - report the error property
0934: // This should not happen
0935: log("Couldn't get the directory"); //NOI18N
0936: return;
0937: }
0938:
0939: Enumeration e = null;
0940: Vector nodes = new Vector();
0941: int numtns = 0;
0942: TransactionNode[] tns = null;
0943: FileObject fo = null;
0944: String id = null;
0945: MonitorData md = null;
0946:
0947: currTrans.remove(currTrans.getNodes());
0948: if (debug)
0949: log("getTransactions removed old nodes"); //NOI18N
0950:
0951: e = currDir.getData(false);
0952: final List fileObjectsToDelete = new ArrayList();
0953: while (e.hasMoreElements()) {
0954:
0955: fo = (FileObject) e.nextElement();
0956: // #43213 - avoiding ModuleInstall class, delaying deletion of old records until now
0957: if (fo.lastModified().after(startDate)) {
0958: id = fo.getName();
0959: if (debug)
0960: log("getting current transaction: " + id); //NOI18N
0961:
0962: // Retrieve the monitordata
0963: md = retrieveMonitorData(id, currDir);
0964: if (md != null) {
0965: nodes.add(createTransactionNode(md, true));
0966: }
0967: } else {
0968: fileObjectsToDelete.add(fo);
0969: }
0970: }
0971: RequestProcessor.getDefault().post(new Runnable() {
0972: public void run() {
0973: for (Iterator it = fileObjectsToDelete.iterator(); it
0974: .hasNext();) {
0975: try {
0976: ((FileObject) it.next()).delete();
0977: } catch (IOException e) {
0978: Logger.getLogger("global").log(Level.INFO,
0979: null, e);
0980: }
0981: }
0982: }
0983: });
0984:
0985: numtns = nodes.size();
0986: tns = new TransactionNode[numtns];
0987: for (int i = 0; i < numtns; ++i)
0988: tns[i] = (TransactionNode) nodes.elementAt(i);
0989: currTrans.add(tns);
0990:
0991: savedTrans.remove(savedTrans.getNodes());
0992: nodes = new Vector();
0993: e = saveDir.getData(false);
0994: while (e.hasMoreElements()) {
0995:
0996: fo = (FileObject) e.nextElement();
0997: id = fo.getName();
0998: if (debug)
0999: log("getting current transaction: " + id); //NOI18N
1000: // Retrieve the monitordata
1001: md = retrieveMonitorData(id, saveDir);
1002: if (md != null) {
1003: nodes.add(createTransactionNode(md, false));
1004: }
1005: }
1006:
1007: numtns = nodes.size();
1008: tns = new TransactionNode[numtns];
1009: for (int i = 0; i < numtns; ++i) {
1010: tns[i] = (TransactionNode) nodes.elementAt(i);
1011: if (debug)
1012: log("Adding saved node" + tns[i].toString()); //NOI18N
1013:
1014: }
1015: savedTrans.add(tns);
1016: }
1017:
1018: private int parseStatusCode(String statusCode) {
1019: if (statusCode == null) {
1020: return -1;
1021: }
1022: // The statusCode is expected to look like e.g. "404: Not Found", if not
1023: // the status code was not resolved, which mostly means there was no error => 200
1024: int statusCodeNum = 200;
1025: try {
1026: int idx = statusCode.indexOf(':');
1027: if (idx != -1) {
1028: statusCode = statusCode.substring(0, idx);
1029: statusCodeNum = Integer.valueOf(statusCode).intValue();
1030: }
1031: } catch (NumberFormatException nfe) {
1032: // ignore
1033: }
1034: return statusCodeNum;
1035: }
1036:
1037: private TransactionNode createTransactionNode(MonitorData md,
1038: boolean current) {
1039:
1040: if (debug)
1041: log("createTransactionNode(MonitorData)"); //NOI18N
1042: Dispatches dis = null;
1043: try {
1044: dis = md.getDispatches();
1045: } catch (Exception ex) {
1046: // Any parsing exception at this point, just ignore this
1047: // part of the request
1048: }
1049:
1050: TransactionNode node = null;
1051:
1052: // No dispatched requests, we add a regular transaction node
1053: if (dis == null || dis.sizeDispatchData() == 0) {
1054:
1055: if (debug)
1056: log("No dispatched requests"); //NOI18N
1057: node = new TransactionNode(md.getAttributeValue("id"), // NOI18N
1058: md.getAttributeValue("method"), // NOI18N
1059: md.getAttributeValue("resource"), //NOI18N
1060: current, parseStatusCode(md.getRequestData()
1061: .getAttributeValue("status"))); // NOI18N
1062: } else {
1063:
1064: int numChildren = dis.sizeDispatchData();
1065: if (debug)
1066: log("We had some dispatched requests: " + //NOI18N
1067: String.valueOf(numChildren));
1068: if (debug)
1069: log("\t for id " + //NOI18N
1070: md.getAttributeValue("resource")); //NOI18N
1071: // Create all the children. 1
1072: Children.Array nested = new Children.Array();
1073:
1074: // First we create an array of children that has the same
1075: // size as the set of nodes.
1076: NestedNode[] nds = new NestedNode[numChildren];
1077: for (int i = 0; i < numChildren; ++i) {
1078: if (debug) {
1079: log("Getting a new monitor data object"); //NOI18N
1080: log(dis.getDispatchData(i).getAttributeValue(
1081: "resource")); //NOI18N
1082: }
1083: nds[i] = createNestedNode(dis.getDispatchData(i), md
1084: .getAttributeValue("method"), // NOI18N
1085: null, i);
1086: }
1087:
1088: nested.add(nds);
1089: node = new TransactionNode(md.getAttributeValue("id"), // NOI18N
1090: md.getAttributeValue("method"), // NOI18N
1091: md.getAttributeValue("resource"), //NOI18N
1092: nested, current, parseStatusCode(md
1093: .getRequestData().getAttributeValue(
1094: "status"))); // NOI18N
1095:
1096: }
1097: return node;
1098: }
1099:
1100: private NestedNode createNestedNode(DispatchData dd, String method,
1101: int[] locator, int index) {
1102:
1103: Dispatches dis = dd.getDispatches();
1104: NestedNode node = null;
1105:
1106: int[] newloc = null;
1107: if (locator != null) {
1108: newloc = new int[locator.length + 1];
1109: int j = 0;
1110: while (j < locator.length) {
1111: newloc[j] = locator[j];
1112: ++j;
1113: }
1114: newloc[j] = index;
1115: } else {
1116: newloc = new int[1];
1117: newloc[0] = index;
1118: }
1119:
1120: // No dispatched requests, we add a regular transaction node
1121: if (dis == null || dis.sizeDispatchData() == 0) {
1122: node = new NestedNode(dd.getAttributeValue("resource"),// NOI18N
1123: method, newloc, parseStatusCode(dd.getRequestData()
1124: .getAttributeValue("status"))); // NOI18N
1125: } else {
1126: int numChildren = dis.sizeDispatchData();
1127: Children.Array nested = new Children.Array();
1128: NestedNode[] nds = new NestedNode[numChildren];
1129: for (int i = 0; i < numChildren; ++i) {
1130: nds[i] = createNestedNode(dis.getDispatchData(i),
1131: method, newloc, i);
1132: }
1133:
1134: nested.add(nds);
1135: node = new NestedNode(dd.getAttributeValue("resource"), // NOI18N
1136: method, nested, newloc, parseStatusCode(dd
1137: .getRequestData().getAttributeValue(
1138: "status"))); // NOI18N
1139: }
1140: return node;
1141: }
1142:
1143: /**
1144: * Sets the machine name and port of the web server. Not used in
1145: * this version, we do not support remote debugging.
1146: */
1147: static void setServer(String loc, int p) {
1148: port = p;
1149: server = loc;
1150: return;
1151: }
1152:
1153: void setComparator(Comparator comp) {
1154: currTrans.setComparator(comp);
1155: savedTrans.setComparator(comp);
1156: }
1157:
1158: /** This method toggles whether the request uses the browser's
1159: * cookie or a cookie specified by the user. In 3.6, it is not
1160: * possible to configure the monitor to use user-specified
1161: * cookies, but I leave the method, in case it becomes possible in
1162: * the future. Basically, we can no longer set the cookie on the
1163: * server side (the Servlet APIs does not provide any method for
1164: * doing this) but we could technically tell the browser that
1165: * issues the replay request to send another cookie (the APIs for
1166: * that are not there now). If so, the feature can be
1167: * reintroduced.
1168: */
1169: void setUseBrowserCookie(boolean value) {
1170: useBrowserCookie = value;
1171: if (debug)
1172: log("Setting useBrowserCookie to " + //NOI18N
1173: String.valueOf(useBrowserCookie));
1174: }
1175:
1176: boolean getUseBrowserCookie() {
1177: return useBrowserCookie;
1178: }
1179:
1180: /**
1181: * @param node A node on the Monitor GUI
1182: * @return a data record
1183: * Convenience method - this gets the DataRecord corresponding to
1184: * a node on the TransactionView panel from the cache if it is
1185: * present. This is used to display the data from the node.
1186: */
1187: DataRecord getDataRecord(AbstractNode node) {
1188: return getDataRecord(node, true);
1189: }
1190:
1191: /**
1192: * @param node A node on the Monitor GUI
1193: * @param fromCache true if it is OK to get the data record from
1194: * the cache
1195: * @return a data record
1196: */
1197: DataRecord getDataRecord(AbstractNode anode, boolean fromCache) {
1198:
1199: if (debug)
1200: log("Entered getDataRecord()"); //NOI18N
1201:
1202: if (anode instanceof TransactionNode) {
1203:
1204: if (debug)
1205: log("TransactionNode"); //NOI18N
1206:
1207: // Since this method is used to retrieve data records for
1208: // the purposes of displaying the transaction, we cache
1209: // the result
1210: MonitorData md = getMonitorData((TransactionNode) anode,
1211: fromCache, true);
1212: if (md == null) {
1213: String msg = NbBundle.getMessage(Controller.class,
1214: "MSG_NoMonitorData");
1215: Logger.getLogger("global").log(Level.INFO, msg);
1216: return null;
1217: }
1218: return (DataRecord) md;
1219: } else if (anode instanceof NestedNode) {
1220:
1221: NestedNode node = (NestedNode) anode;
1222:
1223: if (debug)
1224: log(node.toString());
1225:
1226: int index[] = node.getIndex();
1227:
1228: AbstractNode parent = (AbstractNode) node.getParentNode();
1229: if (parent == null) {
1230: if (debug)
1231: log("null parent, something went wrong!"); //NOI18N
1232: return null;
1233: }
1234:
1235: while (parent != null
1236: && !(parent instanceof TransactionNode)) {
1237: if (debug)
1238: log("Parent is not transaction node"); //NOI18N
1239: if (debug)
1240: log(parent.toString());
1241: parent = (AbstractNode) (parent.getParentNode());
1242: }
1243:
1244: if (debug)
1245: log("We got the transaction node"); //NOI18N
1246:
1247: // We get the data record, from cache if it is present,
1248: // and cache the node also
1249: MonitorData md = getMonitorData((TransactionNode) parent,
1250: true, true);
1251: if (md == null) {
1252: String msg = NbBundle.getMessage(Controller.class,
1253: "MSG_NoMonitorData");
1254: Logger.getLogger("global").log(Level.INFO, msg);
1255: return null;
1256: }
1257: DataRecord dr = (DataRecord) md;
1258: int[] nodeindex = node.getIndex();
1259:
1260: int c = 0;
1261: while (c < nodeindex.length) {
1262: if (debug)
1263: log("Doing the data record cycle"); //NOI18N
1264: if (debug)
1265: log(String.valueOf(c) + ":" + //NOI18N
1266: String.valueOf(nodeindex[c]));
1267: Dispatches dis = dr.getDispatches();
1268: dr = (DataRecord) dis.getDispatchData(nodeindex[c]);
1269: ++c;
1270: }
1271: return dr;
1272: }
1273: return null;
1274: }
1275:
1276: /**
1277: * @param node A node on the Monitor GUI
1278: * @param fromCache true if it is OK to get the data record from
1279: * the cache
1280: * @param cacheIt true if it is OK to cache the data that we
1281: * retrieve
1282: * @return a data record, <code>null</code> if monitor date could not be got
1283: */
1284: MonitorData getMonitorData(TransactionNode node, boolean fromCache,
1285: boolean cacheIt) {
1286:
1287: String id = node.getID();
1288: Hashtable ht = null;
1289: FileObject dir = null;
1290:
1291: if (node.isCurrent()) {
1292: ht = currBeans;
1293: dir = currDir;
1294: if (debug)
1295: log("node is current"); //NOI18N
1296: } else {
1297: ht = saveBeans;
1298: dir = saveDir;
1299: }
1300:
1301: if (debug) {
1302: log("node id is " + node.getID()); //NOI18N
1303: log("using directory " + dir.getName()); //NOI18N
1304: }
1305:
1306: if (fromCache && ht.containsKey(id))
1307: return (MonitorData) (ht.get(id));
1308:
1309: MonitorData md = retrieveMonitorData(id, dir);
1310: if (cacheIt && md != null)
1311: ht.put(id, md);
1312: return md;
1313: }
1314:
1315: /**
1316: * @param id The ID of the record
1317: * @param dirS The name of the directory in which the transaction
1318: * resides
1319: **/
1320: MonitorData retrieveMonitorData(String id, String dirS) {
1321:
1322: if (debug)
1323: log("retrieveMonitorData(String, String)"); //NOI18N
1324: if (!haveDirectories()) {
1325: // PENDING - report the error property
1326: log("Couldn't get the directory"); //NOI18N
1327: return null;
1328: }
1329:
1330: FileObject dir = null;
1331:
1332: if (dirS.equalsIgnoreCase(currDirStr))
1333: dir = currDir;
1334: else if (dirS.equalsIgnoreCase(saveDirStr))
1335: dir = saveDir;
1336: else if (dirS.equalsIgnoreCase(replayDirStr))
1337: dir = replayDir;
1338:
1339: if (debug)
1340: log("Directory = " + dir.getName()); //NOI18N
1341: return retrieveMonitorData(id, dir);
1342: }
1343:
1344: /**
1345: * @param id The ID of the record.
1346: * @param dir The directory in which the transaction resides.
1347: * @return monitor date, <code>null</code> if monitor date could not be retrieved.
1348: */
1349: MonitorData retrieveMonitorData(String id, FileObject dir) {
1350:
1351: // PENDING - this method needs an error reporting mechanism in
1352: // case the monitor data cannot be retrieved. Now it will just
1353: // return null.
1354: if (debug)
1355: log("retrieveMonitorData(String, FileObject)"); //NOI18N
1356: if (!haveDirectories()) {
1357: // PENDING - report the error property
1358: log("Couldn't get the directory"); //NOI18N
1359: return null;
1360: }
1361:
1362: MonitorData md = null;
1363: FileObject fo = null;
1364: FileLock lock = null;
1365: InputStreamReader in = null;
1366:
1367: try {
1368: fo = dir.getFileObject(id, "xml"); // NOI18N
1369: if (debug)
1370: log("From file: " + //NOI18N
1371: FileUtil.toFile(fo).getAbsolutePath());
1372: if (debug)
1373: log("Locking it..."); //NOI18N
1374: lock = fo.lock();
1375: if (debug)
1376: log("Getting InputStreamReader"); //NOI18N
1377: in = new InputStreamReader(fo.getInputStream());
1378: if (debug)
1379: log("Creating monitor data"); //NOI18N
1380: md = MonitorData.createGraph(in);
1381: try {
1382: if (dir == replayDir)
1383: fo.delete(lock);
1384: } catch (IOException ioex2) {
1385: }
1386: } catch (FileAlreadyLockedException falex) {
1387: Logger.getLogger("global").log(Level.INFO, null, falex);
1388: if (debug) {
1389: log("File is locked: " + fo.getNameExt()); //NOI18N
1390: falex.printStackTrace();
1391: }
1392: } catch (IOException ioex) {
1393: Logger.getLogger("global").log(Level.INFO, null, ioex);
1394: if (debug) {
1395: log("Couldn't read data file: " + fo.getNameExt()); //NOI18N
1396: ioex.printStackTrace();
1397: }
1398: } catch (Exception ex) {
1399: Logger.getLogger("global").log(Level.INFO, null, ex);
1400: if (debug) {
1401: log("Something went wrong when retrieving record"); //NOI18N
1402: ex.printStackTrace();
1403: }
1404: } finally {
1405: try {
1406: in.close();
1407: } catch (Throwable t) {
1408: }
1409: if (lock != null)
1410: lock.releaseLock();
1411: }
1412: if (debug)
1413: log("We're done!"); //NOI18N
1414: return md;
1415: }
1416:
1417: private void showReplay(final URL url) throws UnknownHostException,
1418: IOException {
1419:
1420: if (debug)
1421: log("showReplay(URL url) url is " + url.toString()); // NOI18N
1422: // First we check that we can find a host of the name that's
1423: // specified
1424: ServerCheck sc = new ServerCheck(url.getHost());
1425: if (debug)
1426: log("host is " + url.getHost()); //NOI18N
1427: Thread t = new Thread(sc);
1428: t.start();
1429: try {
1430: t.join(2000);
1431: } catch (InterruptedException ie) {
1432: }
1433: t = null;
1434: if (!sc.isServerGood()) {
1435: if (debug)
1436: log("showReplay(): No host"); // NOI18N
1437: throw new UnknownHostException();
1438: }
1439:
1440: if (debug)
1441: log("performed server check"); // NOI18N
1442:
1443: // Next we see if we can connect to the server
1444: try {
1445: Socket server = new Socket(url.getHost(), url.getPort());
1446: server.close();
1447: server = null;
1448: } catch (UnknownHostException uhe) {
1449: if (debug)
1450: log("showReplay(): uhe2"); // NOI18N
1451: throw uhe;
1452: } catch (IOException ioe) {
1453: if (debug)
1454: log("showReplay(): No service"); // NOI18N
1455: throw ioe;
1456: }
1457:
1458: if (debug)
1459: log("showReplay(): reaching the end..."); // NOI18N
1460:
1461: // window system code must be run in AWT thread
1462: SwingUtilities.invokeLater(new Runnable() {
1463: public void run() {
1464: HtmlBrowser.URLDisplayer.getDefault().showURL(url);
1465: }
1466: });
1467: }
1468:
1469: // PENDING - use the logger instead
1470: private static void log(final String s) {
1471: System.out.println("Controller::" + s); //NOI18N
1472: }
1473:
1474: private static URL getSampleHTTPServerURL() {
1475: FileSystem fs = Repository.getDefault().getDefaultFileSystem();
1476: FileObject fo = fs.findResource("HTTPServer_DUMMY");
1477: if (fo == null) {
1478: return null;
1479: }
1480: URL u = URLMapper.findURL(fo, URLMapper.NETWORK);
1481: return u;
1482: }
1483:
1484: boolean checkServer(boolean replay) {
1485:
1486: try {
1487: URL u = getSampleHTTPServerURL();
1488: if (debug)
1489: log("Getting HTTP server - url " + u);
1490: if (u.getProtocol().equals("http")) {
1491: //HttpServer.getRepositoryRoot();
1492: if (debug)
1493: log("Got the HTTP server");
1494: return true;
1495: }
1496: } catch (Throwable t) {
1497:
1498: if (debug) {
1499: log("Exception: " + t.getMessage());
1500: t.printStackTrace();
1501: }
1502:
1503: Object[] options = { NbBundle.getBundle(Controller.class)
1504: .getString("MON_OK"), };
1505: String msg = null;
1506: if (replay)
1507: msg = NbBundle.getBundle(Controller.class).getString(
1508: "MON_CantReplay");
1509: else
1510: msg = NbBundle.getBundle(Controller.class).getString(
1511: "MON_NoServer");
1512:
1513: NotifyDescriptor noServerDialog = new NotifyDescriptor(msg,
1514: NbBundle.getBundle(Controller.class).getString(
1515: "MON_NoServerTitle"),
1516: NotifyDescriptor.DEFAULT_OPTION,
1517: NotifyDescriptor.INFORMATION_MESSAGE, options,
1518: options[0]);
1519: DialogDisplayer.getDefault().notify(noServerDialog);
1520: }
1521: return false;
1522: }
1523:
1524: /**
1525: * Does the server we try to replay on exist?
1526: */
1527: class ServerCheck implements Runnable {
1528:
1529: boolean serverGood = false;
1530: String serverName = null;
1531:
1532: ServerCheck(String name) {
1533: serverName = name;
1534: }
1535:
1536: public void run() {
1537: try {
1538: InetAddress.getByName(serverName);
1539: serverGood = true;
1540:
1541: } catch (UnknownHostException e) {
1542: serverGood = false;
1543: }
1544: }
1545:
1546: boolean isServerGood() {
1547: return serverGood;
1548: }
1549:
1550: }
1551:
1552: /**
1553: * Sort by time
1554: */
1555: class CompTime implements Comparator {
1556:
1557: boolean descend = true;
1558:
1559: CompTime(boolean descend) {
1560: this .descend = descend;
1561: }
1562:
1563: public int compare(Object o1, Object o2) {
1564:
1565: if (debug) {
1566: log("In compareTime"); //NOI18N
1567: log("Comparing " + String.valueOf(o1) + //NOI18N
1568: " and " + String.valueOf(o2)); //NOI18N
1569: log("Cast the nodes"); //NOI18N
1570: }
1571:
1572: TransactionNode n1 = (TransactionNode) o1;
1573: TransactionNode n2 = (TransactionNode) o2;
1574:
1575: if (debug) {
1576: try {
1577: log(n1.getID());
1578: log(n2.getID());
1579: } catch (Exception ex) {
1580: }
1581: ;
1582: }
1583:
1584: int result;
1585: if (descend)
1586: result = n1.getID().compareTo(n2.getID());
1587: else
1588: result = n2.getID().compareTo(n1.getID());
1589: if (debug)
1590: log("End of compareTime"); //NOI18N
1591: return result;
1592: }
1593: }
1594:
1595: // PENDING
1596: // Really dumb way of forcing this, but I couldn't get the tree to
1597: // repaint... Will remove this method when that works.
1598: void updateNodeNames() {
1599:
1600: TransactionNode tn;
1601:
1602: Node[] nodes = currTrans.getNodes();
1603: int size = nodes.length;
1604: for (int i = 0; i < size; ++i) {
1605: tn = (TransactionNode) nodes[i];
1606: tn.setNameString();
1607: }
1608:
1609: nodes = savedTrans.getNodes();
1610: size = nodes.length;
1611: for (int i = 0; i < size; ++i) {
1612: tn = (TransactionNode) nodes[i];
1613: tn.setNameString();
1614: }
1615: }
1616:
1617: /**
1618: * Sort alphabetically
1619: */
1620: class CompAlpha implements Comparator {
1621:
1622: public int compare(Object o1, Object o2) {
1623: if (debug)
1624: log("In compareAlpha"); //NOI18N
1625: TransactionNode n1 = (TransactionNode) o1;
1626: TransactionNode n2 = (TransactionNode) o2;
1627: if (debug)
1628: log("cast the nodes"); //NOI18N
1629: if (debug) {
1630: log("Comparing " + String.valueOf(o1) + //NOI18N
1631: " and " + String.valueOf(o2)); //NOI18N
1632: try {
1633: log("names"); //NOI18N
1634: log(n1.getName());
1635: log(n2.getName());
1636: log("IDs"); //NOI18N
1637: log(n1.getID());
1638: log(n2.getID());
1639: } catch (Exception ex) {
1640: }
1641: ;
1642: }
1643: int diff = n1.getName().compareTo(n2.getName());
1644: if (diff == 0)
1645: return n1.getID().compareTo(n2.getID());
1646: else
1647: return diff;
1648: }
1649: }
1650: } // Controller
|