com.sshtools.powervnc.PowerVNCPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.sshtools.powervnc.PowerVNCPanel.java

Source

//Changes (c) CCLRC 2006
/*
 *  Sshtools - SshVNC
 *
 *  Copyright (C) 2002 Lee David Painter.
 *
 *  Written by: 2002 Lee David Painter <lee@sshtools.com>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package com.sshtools.powervnc;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.AccessControlException;
import java.security.AccessController;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import net.sf.jftp.JFtp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sshtools.common.authentication.KBIRequestHandlerDialog;
import com.sshtools.common.authentication.PasswordAuthenticationDialog;
import com.sshtools.common.authentication.PasswordChange;
import com.sshtools.common.authentication.PublicKeyAuthenticationPrompt;
import com.sshtools.common.configuration.SshToolsConnectionProfile;
import com.sshtools.common.mru.MRUAction;
import com.sshtools.common.mru.MRUListModel;
import com.sshtools.common.mru.MRUMenu;
import com.sshtools.common.ui.CloseAction;
import com.sshtools.common.ui.ConnectionPropertiesAction;
import com.sshtools.common.ui.DataNotificationListener;
import com.sshtools.common.ui.EditAction;
import com.sshtools.common.ui.IconWrapperPanel;
import com.sshtools.common.ui.MenuAction;
import com.sshtools.common.ui.DesktopAction;
import com.sshtools.common.ui.NewWindowAction;
import com.sshtools.common.ui.OpenAction;
import com.sshtools.common.ui.RecordAction;
import com.sshtools.common.ui.FileManagerAction;
import com.sshtools.common.ui.ResourceIcon;
import com.sshtools.common.ui.SaveAction;
import com.sshtools.common.ui.SaveAsAction;
import com.sshtools.common.ui.SessionProvider;
import com.sshtools.common.ui.SessionProviderAction;
import com.sshtools.common.ui.SessionProviderFactory;
import com.sshtools.common.ui.SessionProviderFrame;
import com.sshtools.common.ui.SshToolsApplication;
import com.sshtools.common.ui.SshToolsApplicationClientPanel;
import com.sshtools.common.ui.SshToolsApplicationException;
import com.sshtools.common.ui.SshToolsApplicationPanel;
import com.sshtools.common.ui.SshToolsConnectionTab;
import com.sshtools.common.ui.StandardAction;
import com.sshtools.common.ui.StatusBar;
import com.sshtools.common.ui.StopAction;
import com.sshtools.j2ssh.SshException;
import com.sshtools.j2ssh.SshThread;
import com.sshtools.j2ssh.authentication.KBIAuthenticationClient;
import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient;
import com.sshtools.j2ssh.authentication.PublicKeyAuthenticationClient;
import com.sshtools.j2ssh.authentication.SshAuthenticationClient;
import com.sshtools.j2ssh.connection.ChannelState;
import com.sshtools.j2ssh.forwarding.ForwardingClient;
import com.sshtools.j2ssh.forwarding.ForwardingConfiguration;
import com.sshtools.j2ssh.forwarding.ForwardingIOChannel;
import com.sshtools.j2ssh.forwarding.VNCDisplay;
import com.sshtools.j2ssh.io.IOStreamConnector;
import com.sshtools.j2ssh.session.SessionChannelClient;
import com.sshtools.sshterm.emulation.TerminalEmulation;
import com.sshtools.sshterm.emulation.TerminalPanel;

public class PowerVNCPanel

        extends SshToolsApplicationClientPanel

        implements ActionListener {

    public final static String PROFILE_PROPERTY_VNC_HOST = "VNC_HOST";

    public final static String PROFILE_PROPERTY_VNC_DISPLAY = "VNC_DISPLAY";

    public final static String PROFILE_PRE_VNC_COMMAND = "PRE_VNC_COMMAND";

    public final static String PROFILE_POST_VNC_COMMAND = "POST_VNC_COMMAND";

    public final static String PROFILE_PROPERTY_PREFERRED_ENCODING =

            "PREFERRED_ENCODING";

    public final static String PROFILE_PROPERTY_USE_COPY_RECT = "USE_COPY_RECT";

    public final static String PROFILE_PROPERTY_COMPRESS_LEVEL =

            "COMPRESS_LEVEL";

    public final static String PROFILE_PROPERTY_JPEG_QUALITY = "JPEG_QUALITY";

    public final static String PROFILE_PROPERTY_CURSOR_UPDATES =

            "CURSOR_UPDATES";

    public final static String PROFILE_PROPERTY_EIGHT_BIT_COLORS =

            "EIGHT_BIT_COLORS";

    public final static String PROFILE_PROPERTY_REVERSE_MOUSE_BUTTONS_2_AND_3 =

            "REVERSE_MOUSE_BUTTONS_2_AND_3";

    public final static String PROFILE_PROPERTY_SHARE_DESKTOP = "SHARE_DESKTOP";

    public final static String PROFILE_PROPERTY_VIEW_ONLY = "VIEW_ONLY";

    public final static String PROFILE_PROPERTY_ENCRYPTED_VNC_PASSWORD =

            "ENCRYPTED_VNC_PASSWORD";

    public final static String PROFILE_PROPERTY_SSH_PASSWORD =

            "SSH_PASSWORD";

    public final static String PROFILE_PROPERTY_SCREEN_SIZE_POLICY = "VNC_SCREEN_SIZE";

    public final static String PROFILE_PROPERTY_VNC_SERVER_OS = "VNC_SERVER_OS";

    // Screen size properties
    public final static int PROFILE_SCREEN_NO_CHANGE = 0;
    public final static int PROFILE_SCREEN_REMOTE_DESKTOP = 1;

    // Server operating system properties
    public final static int PROFILE_VNC_SERVER_OS_WINDOWSMAC = 0;
    public final static int PROFILE_VNC_SERVER_OS_LINUX = 1;

    /*public final static int PROFILE_SCREEN_640_480 = 0;
       public final static int PROFILE_SCREEN_800_600 = 1;
       public final static int PROFILE_SCREEN_1024_768 = 2;*/

    private TerminalPanel terminal;
    protected TerminalEmulation emulation;

    private Vector sessionFrames = new Vector();
    private HashMap sessionActions = new HashMap();

    // Logger

    protected static Log log = LogFactory.getLog(PowerVNC.class);

    //  Private instance variables

    private VNCMain vnc;

    private StandardAction desktopAction;

    private StandardAction closeAction;

    private StandardAction filemanagerAction;

    private StandardAction clipboardAction;

    private StandardAction ctrlAltDelAction;

    private StandardAction recordAction;

    private StandardAction stopAction;

    private Thread rfbThread;

    private JFileChooser recordingFileChooser;

    private VNCTab vncTab;

    private StatusBar statusBar;

    private javax.swing.Timer sendTimer, receiveTimer;

    private ForwardingClient.ClientForwardingListener forwardingConfig;

    private SshToolsConnectionTab[] additionalTabs;

    private OpenAction openAction;

    private EditAction editAction;

    private SaveAction saveAction;

    private SaveAsAction saveAsAction;

    private MRUActionImpl mruAction;

    private ConnectionPropertiesAction connectionPropertiesAction;

    private boolean closing = false;

    ForwardingIOChannel channel;

    SshToolsConnectionProfile newProfile; // Full screen mode

    private boolean fullScreenMode;

    public static final ResourceIcon SSHVNC_ICON = new ResourceIcon(PowerVNCPanel.class,

            "sshvncframeicon.gif");

    //  Private static instance variables

    private static boolean debug = true;

    public void init(SshToolsApplication application) throws SshToolsApplicationException {
        System.out.println("init");

        super.init(application);

        setLayout(new BorderLayout());
        sendTimer = new javax.swing.Timer(500, this);

        sendTimer.setRepeats(false);

        receiveTimer = new javax.swing.Timer(500, this);

        receiveTimer.setRepeats(false);

        statusBar = new StatusBar();

        statusBar.setUser("");

        statusBar.setHost("");

        statusBar.setStatusText("Disconnected");

        statusBar.setConnected(false);

        setLayout(new BorderLayout());

        // Create our terminal emulation object
        try {
            emulation = createEmulation();
        } catch (IOException ioe) {
            throw new SshToolsApplicationException(ioe);
        }

        // Set a scrollbar for the terminal - doesn't seem to be as simple as this

        emulation.setBufferSize(1000);

        // Create our swing terminal and add it to the main frame
        terminal = new TerminalPanel(emulation);

        terminal.requestFocus();

        //

        try {

            vnc = new VNCMain(this);

            //  Additional connection tabs

            additionalTabs = new SshToolsConnectionTab[] { new VNCTab( /*vnc*/), new VNCAdvancedTab( /*vnc*/) };

            add(vnc, BorderLayout.CENTER);

            initActions();

        }

        catch (Throwable t) {

            StringWriter sw = new StringWriter();

            t.printStackTrace(new PrintWriter(sw));

            IconWrapperPanel p =

                    new IconWrapperPanel(

                            UIManager.getIcon("OptionPane.errorIcon"),

                            new ErrorTextBox(

                                    ((t.getMessage() == null)

                                            ? "<no message supplied>"

                                            : t.getMessage())

                                            + (debug

                                                    ? ("\n\n" + sw.getBuffer().toString())

                                                    : "")));

            p.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));

            add(p, BorderLayout.CENTER);

            throw new SshToolsApplicationException(

                    "Failed to start SshVNC. ",

                    t);

        }

    }

    public ResourceIcon getIcon() {

        return SSHVNC_ICON;

    }

    public boolean postConnection() {

        return true;

    }

    public SshToolsConnectionTab[] getAdditionalConnectionTabs() {

        return additionalTabs;

    }

    public void actionPerformed(ActionEvent evt) {

        if (evt.getSource() == receiveTimer) {

            statusBar.setReceiving(false);

        }

        else if (evt.getSource() == sendTimer) {

            statusBar.setSending(false);

        }

        if (sessionActions.containsKey(evt.getActionCommand())) {
            SessionProviderAction action = (SessionProviderAction) sessionActions.get(evt.getActionCommand());
            SessionProviderFrame frame;
            // Do we have an existing frame?
            for (Iterator it = sessionFrames.iterator(); it.hasNext();) {
                frame = (SessionProviderFrame) it.next();
                if (action.getProvider().getProviderClass().isInstance(frame)) {
                    frame.show();
                    return;
                }
            }

            try {
                frame = new SessionProviderFrame(getCurrentConnectionProfile(), ssh, action.getProvider());
                if (frame.initFrame(getApplication())) {
                    frame.show();
                    sessionFrames.add(frame);
                }

            } catch (Throwable ex) {
            }
        }

    }

    public void setFrameResizeable(boolean frameResizeable) {

        vnc.setFrameResizeable(frameResizeable);

    }

    public StatusBar getStatusBar() {

        return statusBar;

    }

    public JToolBar getToolBar() {

        return toolBar;

    }

    public void initVNC(

            InputStream in,

            OutputStream out,

            PowerVNCOptions options) {

        log.info("Initialising VNC");

        try {

            vnc.init(in, out, this, options);

        }

        catch (EOFException e) {

            if (isConnected() && !closing) {
                showErrorMessage(this, "The server closed the connection.", "Error", null);
            }
        } catch (Exception e) {
            if (isConnected() && !closing) {
                showErrorMessage(this, "Error", e);
            }
        } finally {
            // DO NOT CLOSE the connection since other session providers may
            // be open - closeConnection(true);
        }
    }

    public void closeVNC() {
        vnc.closeConnection();
        setAvailableActions();
    }

    public synchronized void closeConnection(boolean doDisconnect) {

        statusBar.setStatusText("Closing VNC");

        SessionProviderFrame browserFrame;
        for (Iterator it = sessionFrames.iterator(); it.hasNext();) {
            try {
                browserFrame = (SessionProviderFrame) it.next();
                browserFrame.exit();
                browserFrame.dispose();
            } catch (Throwable ex) {
            }
        }

        sessionFrames.clear();

        if (ssh != null && ssh.isConnected()) {
            super.closeConnection(doDisconnect);

            if (doDisconnect) {
                closeVNC();
            }

            try {
                String command = getCurrentConnectionProfile().getApplicationProperty(PROFILE_POST_VNC_COMMAND,
                        null);

                if (command != null && command.trim().length() > 0) {

                    statusBar.setStatusText("Executing command: " + command);

                    remove(vnc);
                    add(terminal, BorderLayout.CENTER);
                    emulation.reset();
                    emulation.clearScreen();
                    emulation.setCursorPosition(0, 0);
                    terminal.refresh();
                    log.debug("Executing post VNC command " + command);
                    SessionChannelClient session = ssh.openSessionChannel();
                    session.requestPseudoTerminal("vt100", 80, 24, 0, 0, "");
                    if (session.executeCommand(command)) {
                        session.bindInputStream(emulation.getTerminalInputStream());
                        session.bindOutputStream(emulation.getTerminalOutputStream());
                    }

                    try {
                        session.getState().waitForState(ChannelState.CHANNEL_CLOSED);

                    } catch (InterruptedException ex) {
                    } finally {
                        remove(terminal);
                        add(vnc, BorderLayout.CENTER);
                    }
                }
            } catch (Exception e) {

            }

            try {
                if (channel != null) {
                    channel.close();
                }
            } catch (IOException ex) {
            }

            statusBar.setUser("");
            statusBar.setHost("");
            statusBar.setStatusText("Disconnected");
            statusBar.setConnected(false);
            // Reset the menu items
            setAvailableActions();
            // Null the session and current properties
            ssh = null;
            forwardingConfig = null;
            //
            //setCurrentConnectionProfile(null);
            setNeedSave(false);
            //setCurrentConnectionFile(null);
            setContainerTitle(null);
            setAvailableActions();
        }
    }

    protected int showAuthenticationPrompt(SshAuthenticationClient instance) throws

    IOException {

        // Get password from profile, if any ppp

        String profPw = getCurrentConnectionProfile()
                .getApplicationProperty(PowerVNCPanel.PROFILE_PROPERTY_SSH_PASSWORD, "");

        if (!profPw.equals("")) {

            // SSH_PASSWORD is hexascii-encoded. Decode.

            ((PasswordAuthenticationClient) instance).setPassword(HexASCII.ToString(profPw));

        }

        instance.setUsername(getCurrentConnectionProfile().getUsername());

        if (instance instanceof PasswordAuthenticationClient) {

            PasswordAuthenticationDialog dialog =

                    new PasswordAuthenticationDialog(

                            (Frame) SwingUtilities.getAncestorOfClass(

                                    Frame.class, PowerVNCPanel.this));

            instance.setAuthenticationPrompt(dialog);

            ((PasswordAuthenticationClient) instance).setPasswordChangePrompt(

                    PasswordChange.getInstance());

            PasswordChange.getInstance().setParentComponent(

                    PowerVNCPanel.this);

        }

        else if (instance instanceof PublicKeyAuthenticationClient) {

            PublicKeyAuthenticationPrompt prompt = new PublicKeyAuthenticationPrompt(

                    PowerVNCPanel.this);

            instance.setAuthenticationPrompt(prompt);

        }

        else if (instance instanceof KBIAuthenticationClient) {

            KBIAuthenticationClient kbi = new KBIAuthenticationClient();

            ((KBIAuthenticationClient) instance).setKBIRequestHandler(

                    new KBIRequestHandlerDialog(

                            (Frame) SwingUtilities.getAncestorOfClass(

                                    Frame.class, PowerVNCPanel.this)));

        }

        return ssh.authenticate(instance,
                getCurrentConnectionProfile().getApplicationProperty(PROFILE_PROPERTY_VNC_HOST, "localhost"));

    }

    public void authenticationComplete(boolean newProfile) throws SshException,

            IOException {

        //     System.out.println("giga");
        statusBar.setStatusText("User authenticated");
        setContainerTitle(getCurrentConnectionProfile().getHost());

        int localPort = 0;

        String host = getCurrentConnectionProfile().getApplicationProperty(PROFILE_PROPERTY_VNC_HOST, "localhost");
        /*
            String port = getCurrentConnectionProfile()
                .getApplicationProperty(
                PROFILE_PROPERTY_VNC_DISPLAY,
                "5900");
        */
        //    String host = "192.168.0.3";
        String port = PowerVNC.DISPLAY;

        final VNCDisplay display = new VNCDisplay(host + ":" + port, 5900);

        final String addr = "0.0.0.0";

        String command = getCurrentConnectionProfile().getApplicationProperty(

                PROFILE_PRE_VNC_COMMAND, null);

        if (command != null && command.trim().length() > 0) {

            statusBar.setStatusText("Executing command: " + command);
            remove(vnc);
            add(terminal, BorderLayout.CENTER);

            emulation.reset();
            emulation.clearScreen();
            emulation.setCursorPosition(0, 0);
            terminal.refresh();

            log.debug("Executing pre VNC command" + command);

            SessionChannelClient session = ssh.openSessionChannel();

            session.requestPseudoTerminal("vt100", 80, 24, 0, 0, "");

            if (session.executeCommand(command)) {

                session.bindInputStream(emulation.getTerminalInputStream());
                session.bindOutputStream(emulation.getTerminalOutputStream());
            }

            try {

                session.getState().waitForState(ChannelState.CHANNEL_CLOSED);

            }

            catch (InterruptedException ex) {

            } finally {

                remove(terminal);
                //        Rectangle r = new Rectangle(vnc.getWidth(), vnc.getHeight());
                ////        vnc.getSize().
                //        setFrameResizeable(true);
                //        setBounds(r);
                //        refresh();
                add(vnc, BorderLayout.CENTER);
                //        JFrame desktop = new JFrame();
                //        desktop.add(vnc, BorderLayout.CENTER);
                //        desktop.pack();
                //              pack();
            }

        }

        statusBar.setStatusText("Setting up VNC forwarding");

        if (log.isDebugEnabled()) {

            log.debug("Setting up forwarding on " + addr

                    + " (" + localPort + ") to " + display.getHost()

                    + ":" + display.getPort());

        }

        final PowerVNCOptions options =

                new PowerVNCOptions(getCurrentConnectionProfile());

        statusBar.setStatusText("Initialising VNC");

        ForwardingConfiguration config =

                new ForwardingConfiguration(

                        "VNC",

                        "forwarded-channel",

                        0,

                        display.getHost(),

                        display.getPort());

        channel =

                new ForwardingIOChannel(

                        ForwardingIOChannel.LOCAL_FORWARDING_CHANNEL,

                        "VNC",

                        config.getHostToConnect(),

                        config.getPortToConnect(),

                        addr,

                        display.getPort());

        if (ssh.openChannel(channel)) {

            // The forwarding channel is open so forward to the
            // VNC protocol

            channel.addEventListener(new DataNotificationListener(statusBar));

            if (newProfile) {

                setNeedSave(true);

            }

            new SshThread(new Runnable() {

                public void run() {

                    //           setBounds(new Rectangle(1000, 1000));
                    //           setVisible(true);
                    //           setPreferredSize(new Dimension(1000, 1000));
                    //           revalidate();
                    //           pack();
                    //           this.setsize(new Dimension(1000, 1000));
                    initVNC(

                            channel.getInputStream(),

                            channel.getOutputStream(),

                            options);

                }

            }

                    , "VNC", true).start();
            //      setBounds(new Rectangle(1000, 1000));
            setSize(800, 800);
            //      show();
            //      setSize(new Dimension(1000, 1000));
            //      revalidate();
            //      resize(800, 800);
            //      refresh();
        }

        else {

            // We need to close the connection and inform the user

            // that the forwarding failed to start

            try {

                SwingUtilities.invokeAndWait(new Runnable() {

                    public void run() {

                        JOptionPane.showMessageDialog(

                                PowerVNCPanel.this,

                                "Powua failed to open a forwarding channel to "

                                        + display.toString(),

                                "Powua",

                                JOptionPane.OK_OPTION);

                    }

                });

            }

            catch (Exception ex) {

                statusBar.setStatusText(

                        "Could not connect to local forwarding server");

            }

            finally {

                closeConnection(true);

            }

        }

    }

    private void initActions() {

        //  Create the action menu groups

        System.out.println("initActions");
        registerActionMenu(new SshToolsApplicationPanel.ActionMenu("File", "File",

                'f', 0));

        registerActionMenu(new SshToolsApplicationPanel.ActionMenu("Edit", "Edit",

                'e', 10));

        registerActionMenu(new SshToolsApplicationPanel.ActionMenu("View", "View",

                'v', 20));

        vncTab = new VNCTab( /*vnc*/);

        desktopAction = new DesktopAction() {

            public void actionPerformed(ActionEvent evt) {

                try {
                    authenticationComplete(false);
                } catch (SshException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                /*
                        newProfile = newConnectionProfile(null);
                    
                        if (newProfile != null) {
                    
                          connect(newProfile, true);
                    
                        }
                    
                        else {
                    
                          log.info("New connection cancelled");
                    
                        }
                */
            }

        };

        registerAction(desktopAction);

        closeAction = new CloseAction() {

            public void actionPerformed(ActionEvent evt) {

                closing = true;
                // Close on a thread to avoid blocking the event queue
                Thread thread = new Thread() {
                    public void run() {
                        closeConnection(true);
                    }
                };

                thread.start();

            }

        };

        registerAction(closeAction);

        filemanagerAction = new FileManagerAction() {

            public void actionPerformed(ActionEvent evt) {

                new JFtp(ssh);
                //         refresh();

            }

        };

        registerAction(filemanagerAction);

        ctrlAltDelAction = new CtrlAltDelAction() {

            public void actionPerformed(ActionEvent evt) {

                try {

                    vnc.sendCtrlAltDel();

                }

                catch (IOException ioe) {

                    closeConnection(true);

                    showErrorMessage(PowerVNCPanel.this, "Error", ioe);

                }

            }

        };

        registerAction(ctrlAltDelAction);

        clipboardAction = new ClipboardAction() {

            public void actionPerformed(ActionEvent evt) {

                vnc.setClipboardVisible(!vnc.isClipboardVisible());

            }

        };

        registerAction(clipboardAction);

        if (getApplication().getMRUModel() != null) {

            registerAction(

                    mruAction = new MRUActionImpl(getApplication().getMRUModel()));

        }

        connectionPropertiesAction = new ConnectionPropertiesAction() {

            public void actionPerformed(ActionEvent evt) {

                editConnection(getCurrentConnectionProfile());

            }

        };

        registerAction(connectionPropertiesAction);

        //  Only allow opening of files if allowed by the security manager

        try {

            if (System.getSecurityManager() != null) {

                AccessController.checkPermission(

                        new FilePermission("<<ALL FILES>>", "read"));

            }

            openAction = new OpenAction() {

                public void actionPerformed(ActionEvent evt) {

                    open();

                }

            };

            registerAction(openAction);

        }

        catch (AccessControlException ace) {

            ace.printStackTrace();

        }

        //  Only allow saving of files if allowed by the security manager

        try {

            if (System.getSecurityManager() != null) {

                AccessController.checkPermission(

                        new FilePermission("<<ALL FILES>>", "write"));

            }

            saveAction = new SaveAction() {

                public void actionPerformed(ActionEvent evt) {

                    saveConnection(false, getCurrentConnectionFile(),

                            getCurrentConnectionProfile());

                }

            };

            registerAction(saveAction);

            saveAsAction = new SaveAsAction() {

                public void actionPerformed(ActionEvent evt) {

                    saveConnection(true, getCurrentConnectionFile(),

                            getCurrentConnectionProfile());

                }

            };

            registerAction(saveAsAction);

            recordAction = new RecordAction() {

                public void actionPerformed(ActionEvent evt) {

                    startRecording();

                }

            };

            registerAction(recordAction);

            stopAction = new StopAction() {

                public void actionPerformed(ActionEvent evt) {

                    stopRecording();

                }

            };

            registerAction(stopAction);

        }

        catch (AccessControlException ace) {

            ace.printStackTrace();

        }

        //  Only allow editing of connection file if read / write is allowed

        try {

            if (System.getSecurityManager() != null) {

                AccessController.checkPermission(

                        new FilePermission("<<ALL FILES>>", "write"));

            }

            if (System.getSecurityManager() != null) {

                AccessController.checkPermission(

                        new FilePermission("<<ALL FILES>>", "read"));

            }

            editAction = new EditAction() {

                public void actionPerformed(ActionEvent evt) {

                    editConnection();

                }

            };

            registerAction(editAction);

        }

        catch (AccessControlException ace) {

            ace.printStackTrace();

        }

        java.util.List providers = SessionProviderFactory.getInstance().getSessionProviders();
        SessionProvider provider;
        SessionProviderAction action;
        for (Iterator it = providers.iterator(); it.hasNext();) {
            provider = (SessionProvider) it.next();
            action = new SessionProviderAction(provider);
            sessionActions.put(action.getActionCommand(), action);
            action.addActionListener(this);
            registerAction(action);
        }

    }

    private void startRecording() {

        if (recordingFileChooser == null) {

            recordingFileChooser =

                    new JFileChooser(System.getProperty("user.home"));

        }

        int ret = recordingFileChooser.showSaveDialog(this);

        int i = 1;

        File file = null;

        while (file == null) {

            File f =

                    new File(

                            recordingFileChooser.getCurrentDirectory(),

                            "vncsession.fbs." + i);

            if (!f.exists()) {

                file = f;

            }

            i++;

        }

        recordingFileChooser.setSelectedFile(file);

        if (ret == recordingFileChooser.APPROVE_OPTION) {

            file = recordingFileChooser.getSelectedFile();

            if (file.exists()

                    && JOptionPane.showConfirmDialog(

                            this,

                            "File " + file.getName() + " already exists. Are you sure?",

                            "File exists",

                            JOptionPane.YES_NO_OPTION,

                            JOptionPane.WARNING_MESSAGE)

                    == JOptionPane.NO_OPTION) {

                return;

            }

            vnc.setRecordingStatus(file.getAbsolutePath());

            setAvailableActions();

        }

    }

    private void stopRecording() {

        vnc.setRecordingStatus(null);

        setAvailableActions();

    }

    public void refresh() {

        try {

            vnc.refresh();

        }

        catch (IOException ioe) {

            closeConnection(true);

            showErrorMessage(this, "Error", ioe);

        }

    }

    public void setAvailableActions() {

        boolean connected = isConnected();

        desktopAction.setEnabled(connected);

        //    OpenAction.seten

        openAction.setEnabled(false);

        closeAction.setEnabled(false);

        filemanagerAction.setEnabled(connected);

        ctrlAltDelAction.setEnabled(false);

        clipboardAction.setEnabled(false);

        String sessionFile = vnc.getRecordingStatus();

        SessionProviderAction action;
        for (Iterator it = sessionActions.values().iterator(); it.hasNext();) {
            action = (SessionProviderAction) it.next();
            action.setEnabled(connected);
        }

        if (stopAction != null) {

            stopAction.setEnabled(connected && sessionFile != null);

        }

        if (recordAction != null) {

            recordAction.setEnabled(connected && sessionFile == null);

        }

        if (openAction != null) {

            openAction.setEnabled(true);

        }

        connectionPropertiesAction.setEnabled(connected);

        closeAction.setEnabled(connected);

        if (saveAction != null) {

            saveAction.setEnabled(connected && isNeedSave());

        }

        if (saveAsAction != null) {

            saveAsAction.setEnabled(connected);

        }

    }

    public void close() {
        closeConnection(true);
    }

    private TerminalEmulation createEmulation() throws IOException {
        return new TerminalEmulation(TerminalEmulation.VT320);
    }

    public boolean canClose() {

        if (isConnected()) {
            if (JOptionPane.showConfirmDialog(this, "Close the current session and exit?", "Exit Application",
                    JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
                return false;
            }
        }
        return true;

    }

    //  Supporting classes
    class ErrorTextBox extends JTextArea {
        ErrorTextBox(String text) {
            super(text);
            setOpaque(false);
            setWrapStyleWord(true);
            setLineWrap(true);
            setEditable(false);
        }
    }

    class IOConnector extends Thread {
        InputStream in;
        OutputStream out;

        IOConnector(InputStream in, OutputStream out) {
            super("IOConnector");
            this.in = in;
            this.out = out;
            start();
        }

        public void run() {
            IOStreamConnector con = new IOStreamConnector(in, out);
        }

    }

    class MRUActionImpl

            extends MRUAction {

        public MRUActionImpl(MRUListModel model) {

            super(model);

        }

        public void cleanUp() {

            ((MRUMenu) getValue(MenuAction.MENU)).cleanUp();

        }

        public void actionPerformed(ActionEvent evt) {

            open(new File(evt.getActionCommand()));

        }

    }

}