TomWiedenhoeft - 2005-02-24

Hallo, again!

Here is a modified class that might interest you.

The modified EchoTagHandler.java below can echo to a file.

It writes something like this to file:
"2004-11-11 10:23:56.123 This is a log message"

Benefit:
In complex tests this "logging" helps to track down the actions of single automatons.

If you think the modification is usefull for you please intergrate it into the official version.
It would be very helpfull because we won't have any trouble if you come out with the next version of JFC-Unit.

Thanks a lot.
Tom Wiedenhoeft

---schnipp---
/*
* Created on Oct 24, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package junit.extensions.xml.elements;

import junit.extensions.jfcunit.xml.JFCXMLTestCase;

import junit.extensions.xml.IXMLTestCase;
import junit.extensions.xml.XMLException;

import junit.framework.Assert;

import org.w3c.dom.Element;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.File;

import java.util.Calendar;

/**
* Provide a mechanism for sending debug messages to the
* test case developer.
*
* <H3>Tag Name:</H3>
* echo
* <H3>Attributes:</H3>
* <pre>
* message - the message to output        [required]
* mode    - what is the output mechanism [optional]
*          'stdout' is default, sends output to stdout
*          'dialog' sends the output to a JOptionPane
*          'confirm' sends the output to a JOptionPane
*                    confirmation dialog.
*          'stderr' sends the output to stderr
*          'file' sends the output to a file
* block   - Block is a valid attribute when the mode is
*           dialog or confirm. It controlls the modality
*           of the dialog. Default value is true.
*          'file' sends the output to a file [optional]
* file    - File to write to if mode is 'file'. Default is
*           '{user.home}/echo.log'. [optional]
* </pre>
* <H3>Examples:</H3>
* <pre>
*   &lt;echo message="hello world"/&gt;
*   &lt;echo mode='dialog' message="hello world"/&gt;
*   &lt;echo mode='dialog' block="false" message="hello world"/&gt;
*   &lt;echo mode='stderr' message="hello world"/&gt;
*   &lt;echo mode='file' message="hello world" file="c:/tmp/xy.log"/&gt;
* </pre>
* @author JFCUnit contributors
*/
public class EchoTagHandler extends AbstractTagHandler {
    /**
     * Result of confirm dialog when YES button is pressed.
     */
    private static final int YES_OPTION = JOptionPane.YES_OPTION;

    /**
     * Result of confirm dialog when NO or CANCEL button is pressed.
     */
    private static final int NO_OPTION = JOptionPane.NO_OPTION;

    /**
     * Window close result.
     */
    private boolean m_result = false;

    /**
     * Constructor.
     * @param element Element to be processed by the tag handler.
     * @param testcase parent test case.
     */
    public EchoTagHandler(final Element element, final IXMLTestCase testcase) {
        super(element, testcase);
    }

    /**
     * Handle the XML processing of the tag 'echo'.
     * @throws XMLException upon failure of processing.
     */
    public void processElement() throws XMLException {
        validateElement();

        final String msg = getString(MESSAGE);

        String       mode = getString(MODE);

        if (mode == null) {
            mode = STDOUT;
        }

        boolean block = getBoolean("block", true);

        if (DIALOG.equals(mode)) {
            m_result = false;

            if (block) {
                JOptionPane.showMessageDialog(null, msg);
            } else {
                showDialog(msg);
            }

            System.err.println("[echo] " + msg);
        } else if (CONFIRM.equalsIgnoreCase(mode)) {
            System.err.println("[echo] " + msg);

            if (block) {
                m_result = JOptionPane.showConfirmDialog(null, msg, "Confirm",
                        JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
            } else {
                m_result = (showConfirm(msg) == JOptionPane.YES_OPTION);
            }

            if (!m_result) {
                Assert.fail(msg);
            }
        } else if (STDERR.equalsIgnoreCase(mode)) {
            System.err.println("[echo] " + msg);
        } else if (STDOUT.equalsIgnoreCase(mode)) {
            System.out.println("[echo] " + msg);
        }  else if (FILE.equalsIgnoreCase(mode)) {
            String file = getString(FILE);
            if (file == null) {
                String userHome = System.getProperty("user.home");
                file = userHome + File.separator + "echo.log";
            }
            String timeStamp = (new TimeStamp()).getFullTimstamp();
            String s = timeStamp + " " + msg;
            PrintWriter out = null;
            try {
                out =
                    new PrintWriter(
                            new BufferedWriter(
                                    new FileWriter(file, true)));
                out.println(s);
            } catch(IOException e) {
                throw new XMLException(
                        "Failed to echo message '" + msg + "' to file '" + file + "'. " + e.getMessage(),
                        null,
                        getElement(),
                        getXMLTestCase().getPropertyCache());
            } finally {
                if(out != null)
                {
                    try {
                        out.close();
                    } catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        } else {
            throw new XMLException("Invalid mode", null,
                getElement(),
                getXMLTestCase().getPropertyCache());
        }
    }

    /**
     * Make sure the appropriate tag and attributes are used.
     * @throws XMLException when validation fails.
     */
    public void validateElement() throws XMLException {
        super.validateElement();

        // message is a required attribute
        checkRequiredAttribute(MESSAGE);
    }

    /**
     * Show a confirm dialog.
     * @param msg Message to be displayed.
     * @return YES_OPTION or NO_OPTION
     */
    int showConfirm(final String msg) {
        return showDialog(msg, true);
    }

    /**
     * Show a Dialog.
     * @param msg Message to be displayed.
     */
    void showDialog(final String msg) {
        showDialog(msg, false);
    }

    /**
     * Show the dialog with the message given.
     * @param msg message to be displayed.
     * @param confirm if true then use YES/NO buttons.
     * @return YES_OPTION or NO_OPTION.
     */
    int showDialog(final String msg, final boolean confirm) {
        EchoDialog ed = new EchoDialog(msg, confirm);
        ed.setVisible(true);

        IXMLTestCase tc = getXMLTestCase();

        while (!ed.getDialogClosed()) {
            if (tc instanceof JFCXMLTestCase) {
                ((JFCXMLTestCase) tc).sleep(1000);
            } else {
                try {
                    Thread.currentThread().sleep(1000);
                } catch (InterruptedException ie) {
                    ;
                }
            }
        }

        return ed.getResult();
    }

    /**
     * Generates a verbose timestamp.
     * Example: 2004-11-11 10:23:56.123
     *
     * @author tom@smart-tail.com (Tom Wiedenhoeft, DV-Ratio acting under contract with Siemens L&A PA)
     */
    public class TimeStamp {
        public String getFullTimstamp() {
            Calendar cal = Calendar.getInstance();

            StringBuffer buf = new StringBuffer();
            buf.append(Integer.toString(cal.get(Calendar.YEAR)));
            buf.append("-");

            String s = Integer.toString(cal.get(Calendar.MONTH) + 1);
            if(s.length() < 2)
            {
                s = "0" + s;
            }

            buf.append(s);
            buf.append("-");

            s = Integer.toString(cal.get(Calendar.DAY_OF_MONTH));
            if(s.length() < 2)
            {
                s = "0" + s;
            }

            buf.append(s);
            buf.append(" ");

            s = Integer.toString(cal.get(Calendar.HOUR_OF_DAY));
            if(s.length() < 2)
            {
                s = "0" + s;
            }

            buf.append(s);
            buf.append(":");

            s = Integer.toString(cal.get(Calendar.MINUTE));
            if(s.length() < 2)
            {
                s = "0" + s;
            }
            buf.append(s);
            buf.append(":");

            s = Integer.toString(cal.get(Calendar.SECOND));
            if(s.length() < 2)
            {
                s = "0" + s;
            }
            buf.append(s);
            buf.append(".");

            s = Integer.toString(cal.get(Calendar.MILLISECOND));
            if(s.length() == 1)
            {
                s = "00" + s;
            }
            else if(s.length() == 2)
            {
                s = "0" + s;
            }
            buf.append(s);

            return buf.toString();
        }
    }

    /**
     * <p>Title: EchoDialog non-modal dialog for echos</p>
     * <p>Description: Non modal dialog for echo/confirm.
     * This dialog allows Application to be exercized.
     * <p>Copyright: Copyright (c) 2003</p>
     * <p>Company: JFCUnit Project</p>
     * @author Kevin Wilson
     * @version 1.0
     */
    private class EchoDialog extends JDialog implements ActionListener {
        /**
         * NO Button.
         */
        private JButton m_no;

        /**
         * Yes Button.
         */
        private JButton m_ok;

        /**
         * Private result of the dialog.
         */
        private volatile boolean m_dislogClosed = false;

        /**
         * Result of the dialog.
         */
        private int m_result = JOptionPane.DEFAULT_OPTION;

        /**
         * Constructor.
         * @param message Message to be displayed.
         * @param confirm true if YES/NO buttons false for OK button.
         */
        public EchoDialog(final String message, final boolean confirm) {
            JLabel msg = new JLabel(message);

            m_ok = new JButton("OK");

            if (confirm) {
                m_ok.setText("Yes");
            }

            m_ok.addActionListener(this);
            m_no = new JButton("No");
            m_no.addActionListener(this);
            m_no.setVisible(confirm);

            JPanel buttonPanel = new JPanel();
            buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
            buttonPanel.add(Box.createHorizontalGlue());
            buttonPanel.add(m_ok);
            buttonPanel.add(m_no);
            buttonPanel.add(Box.createHorizontalGlue());

            JPanel panel = new JPanel();
            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
            panel.add(msg);
            panel.add(buttonPanel);
            setContentPane(panel);
            this.setModal(false);
            pack();
        }

        /**
         * Get the dialog closed state.
         * @return true if the dialog was closed.
         */
        public boolean getDialogClosed() {
            return m_dislogClosed;
        }

        /**
         * Get the result of the dialog.
         * @return the result of the dialog YES_OPTION, NO_OPTION.
         */
        public int getResult() {
            return m_result;
        }

        /**
         * Action handler for this dialog.
         * @param ae ActionEvent to be consumed.
         */
        public void actionPerformed(final ActionEvent ae) {
            Object source = ae.getSource();

            if (source == m_ok) {
                m_result = YES_OPTION;
            } else if (source == m_no) {
                m_result = NO_OPTION;
            }

            this.setVisible(false);
            this.dispose();
            m_ok               = null;
            m_no               = null;
            m_dislogClosed     = true;
        }
    }
}

---schnapp---