[Webfunds-commits] java/webfunds/client/utils UpgradesManager.java

Ian Grigg iang@cypherpunks.ai
Fri, 6 Oct 2000 21:12:46 -0400 (AST)


iang        00/10/06 21:12:46

  Added:       webfunds/client/utils UpgradesManager.java
  Log:
  written, works according to 1/4 of promise...

Revision  Changes    Path
1.1                  java/webfunds/client/utils/UpgradesManager.java

Index: UpgradesManager.java
===================================================================
/*
 * $Id: UpgradesManager.java,v 1.1 2000/10/07 01:12:45 iang Exp $
 *
 * Copyright (c) 2000 Systemics Inc on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.client.utils;

import javax.swing.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.util.zip.*;

import webfunds.sox.*;

import webfunds.utils.RawHttp;
import webfunds.utils.RawException;
import webfunds.utils.Panic;
import webfunds.ricardian.Contract;
import webfunds.ricardian.ContractException;

import webfunds.client.sun.ExampleFileFilter;
import webfunds.client.contracts.ChangeContractStore;
import webfunds.client.plugins.Plugin;
import webfunds.client.plugins.ModeNotSupportedException;

import webfunds.client.AccountInfo;
import webfunds.client.WalletInterface;
import webfunds.client.UInterfaceImpl;

public class UpgradesManager
    extends Plugin implements ActionListener
{

    protected String name           = "UpgradesManager";
    protected String generalaction  = "UpgradesManager";
    protected String contractaction = "View Upgrades";

    public String getPluginName()     { return name; }
    public String getGeneralAction()  { return generalaction; }
    public String getContractAction() { return contractaction; }

    public static final String INSTALL_BUTTON = "Install Upgrade";
    public static final String GO_BUTTON      = "Go!";
    public static final String DELETE_BUTTON  = "Delete";
    public static final String FILE_BUTTON    = "Explorer";
    public static final String CLOSE_BUTTON   = "Close";
    public static final String OPEN_BUTTON    = "Open";
    public static final String HASH_BUTTON    = "Hash";

    JTextField          urlField;
    JTextArea           text;
    JList               list;
    JScrollPane         textscroll;
    JButton             butadd;
    JFrame              frame;
    ItemId              contract;
    JMenuItem           fileexit;
    JPanel              urlpanel;


    protected File downloadDir;
    protected File installDir;

    public UpgradesManager() { }

    public void init()
        throws ModeNotSupportedException
    {
        initDownloadDir(new File("downloads"));
    }

    public void init(String dirName)
        throws ModeNotSupportedException
    {
        initDownloadDir(new File(dirName));
    }

    public void run()
    {
        frame = new JFrame("UpgradeBrowser");
        JPanel contentpane = (JPanel)frame.getContentPane();

        DefaultListModel listmodel = new DefaultListModel();

        JMenuBar   mb           = new JMenuBar();

                   text         = new JTextArea();
                   list = new JList(listmodel);
                   textscroll   = new JScrollPane(text);
        JScrollPane listscroll  = new JScrollPane(list);
        JSplitPane splitpane    = new JSplitPane(JSplitPane.VERTICAL_SPLIT, listscroll, textscroll);
                   urlpanel     = new JPanel();

        text.setEditable(false);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setVisibleRowCount(6);

        file = new JMenu("File");
        addFileMenuButton(FILE_BUTTON);
        addFileMenuButton(DELETE_BUTTON);
        addFileMenuButton(HASH_BUTTON);
        file.add(new JSeparator ());
        addFileMenuButton(CLOSE_BUTTON);
        mb.add(file);

        contentpane.add("North", urlpanel);
        contentpane.add("Center", splitpane);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setJMenuBar(mb);

        frame.setSize(600,400);
        addUrlPanel(urlpanel);
        list.addListSelectionListener( new ListSelectionListener()
            {
                public void valueChanged(ListSelectionEvent evt)
                {
                    if (!(evt.getValueIsAdjusting()))
                    {
                        logmsg("click! " + (String)list.getSelectedValue());
                        // showContract((Contract)list.getSelectedValue());
                        // urlField.setText("");
                        installButton.setEnabled(true);
                    }
                }
            });

        urlField.addActionListener( this );
        try
        {
            if (contract != null)
            {
                // showContract( cs.getContract(contract) );
            }
        }
        catch (ClassCastException ccex)
        {
            ui.errorMessage("Couldn't open contract");
            ccex.printStackTrace();
        }
        refreshList();
        frame.show();
    }

    JMenu file;
                 
    protected void addFileMenuButton(String s)
    {
        JMenuItem item = new JMenuItem(s);
        file.add(item);
        item.addActionListener( this );
    }

    public void destroy()
    {
        logmsg("Thread destroyed");
    }

    public void setContractStore(ChangeContractStore contractstore)
    {
        cs = contractstore;
        //refreshList();
    }

    /**
     *  Check that the Download Directory is ok.
     */
    protected void initDownloadDir(File dir)
        throws ModeNotSupportedException
    {
         downloadDir = dir;
         logmsg("make dir " + downloadDir);
         if (!downloadDir.exists())
         {
             downloadDir.mkdirs();
             if (!downloadDir.exists())
                 throw new ModeNotSupportedException(
                         "directory <<" + dir + ">> could not be created?");
         }

         if (!downloadDir.isDirectory())
             throw new ModeNotSupportedException(
                         "directory <<" + dir + ">> is not a directory?");
         if (downloadDir.list() == null)
             throw new ModeNotSupportedException(
                         "directory <<" + dir + ">> does not return list?");

         installDir = new File("plugins");
    }



    public void actionPerformed(ActionEvent evt)
    {
        Object source = evt.getSource();
        String action = evt.getActionCommand();
        if (source.equals(urlField) || action == GO_BUTTON)
        {
            Thread t1 = new Thread()
                {
                    public void run() { UpgradesManager.this.getURL(); }
                };
            logmsg("start from GO");
            t1.start();
        }
//        if (source.equals(urlField))
//        {
//            logmsg("urlField");
//            getURL();
//        }
        else if (action == INSTALL_BUTTON)
        {
          Thread t1 = new Thread()
            {
              public void run() { UpgradesManager.this.installPackage(); }
            };
          logmsg("start from INSTALL ... " + (String)list.getSelectedValue());
          t1.start();
        }
        else if (action == CLOSE_BUTTON)
        {
            frame.dispose();
            this.stop();
        }
        else if (action == DELETE_BUTTON)
        {
            Thread t1 = new Thread()
                {
                    public void run() { UpgradesManager.this.deletePackage(); }
                };
            t1.start();
        }
        else if (action == HASH_BUTTON)
        {
            Thread t1 = new Thread()
                {
                    public void run() { UpgradesManager.this.fileHash(); }
                };
logmsg("start thread");
            t1.start();
        }
        else if (action == FILE_BUTTON)
        {
            Thread t1 = new Thread()
                {
                    public void run() { UpgradesManager.this.fileExplorer(); }
                };
            t1.start();
        }
    }

    private void refreshList()
    {
        installButton.setEnabled(false);

        DefaultListModel listmodel = (DefaultListModel)list.getModel();
        listmodel.clear();

        String[] list = downloadDir.list();
        if (list == null)
            throw new Panic("directory disappeared?");
        
        for (int i = 0; i < list.length; i++)
        {
            listmodel.addElement( list[i] );
        }
    }

    private void addContract()
    {
        URL url;
        try {
            url = new URL(urlField.getText());
        } catch (MalformedURLException ex) {
            ui.errorMessage("Not a valid URL");
            return ;
        }

        try {
            Contract con = Contract.getContract(url);
            cs.addContract(con);
        } catch (ContractException ex) {
            ui.errorMessage("Contract is bad: " + ex);
            return ;
        }

        refreshList();

    }

    /*
     * File chooser.
     */
    private File fileChooser(String suffix)
    {
        JFileChooser chooser = new JFileChooser();
        ExampleFileFilter filter = new ExampleFileFilter();
        filter.addExtension(suffix);
        filter.setDescription("Contracts");
        chooser.setFileFilter(filter);
        chooser.setCurrentDirectory(new File("."));
        chooser.setMultiSelectionEnabled(false);
        int returnVal = chooser.showOpenDialog(frame);

        if (returnVal != JFileChooser.APPROVE_OPTION)
            return null ;

        return chooser.getSelectedFile() ;

    }


    /*
     * File explorer for adding contracts by file.
     * This was the [new] button in AccountBrowserImpl.
     */
    private File fileChooser()
    {
        return fileChooser("asc");
    }

    /*
     * File explorer for adding contracts by file.
     * This was the [new] button in AccountBrowserImpl.
     */
    private void fileExplorer()
    {
        File f = fileChooser("zip");
        if (f == null)
            return ;

        installPackage(f);
    }

    /*
     */
    private void fileHash()
    {
logmsg("fileHash()");
        File f = fileChooser();
        if (f == null)
            return ;

        // Read file to be hashed.
        byte[] buf;
        try {
            FileInputStream fis = new FileInputStream(f);
            buf = new byte[fis.available()];
            fis.read(buf);
            fis.close();
        } catch (IOException ex) {
            ui.errorMessage("bad file: " + ex);
            return ;
        }

        byte[] hash;
        try {
            hash = Contract.doCanonicalDigest(buf);
        } catch (ContractException ex) {
            ui.errorMessage("Cannot hash, file is not contract?  " + ex);
            return ;
        }


        //
        //  Need to put it in a text box in order to get C&P capability.
        //
        TextArea hashBox = new TextArea(1, 55);

        hashBox.append(webfunds.utils.Hex.data2hex(hash));
    
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        java.awt.datatransfer.Clipboard clipboard;
        clipboard = toolkit.getSystemClipboard();
        java.awt.datatransfer.StringSelection ss;
        ss = new java.awt.datatransfer.StringSelection(hashBox.getText());
        clipboard.setContents(ss, ss);

//        String msg = "Hash of the contract is: ";
//        JTextPane text = new JTextPane();
//        text.setText(msg);
//        text.setEditable(false);
//        //text.setBackground(frame.getBackground());

        JOptionPane.showMessageDialog(frame, hashBox, "Hash of " + f,
                                          JOptionPane.INFORMATION_MESSAGE);
    }

    static final String httpproto = "http://";
    static final String fileproto = "file:/";

    private void getURL()
    {
        logmsg("URL: <" + urlField.getText() + ">");
        String s = urlField.getText().trim();
        int index = s.indexOf(httpproto);
        int index2 = s.indexOf(fileproto);
        logmsg("s: <" + s + ">" + " index = "  + index);
        if (index < 0 && index2 < 0)
            s = httpproto + s;

        URL url = null;
        try
        {
            logmsg("URL? <" + s + ">");
            url = new URL(s);
        }
        catch (MalformedURLException ex)
        {
            ui.errorMessage("Not a valid URL");
            return ;
        }

        logmsg("download: " + url);
        list.getSelectionModel().clearSelection();
        installButton.setEnabled(false);

            if (s.endsWith(".html") || s.endsWith(".htm") || s.endsWith("/"))
            {
                displayURL(url);
            }
            else if (s.endsWith(".zip"))
            {
                downloadURLtoFile(url);
            }
            else
            {
                ui.errorMessage("URL is unknown form, not .html nor .zip");
                return ;
            }
    }

    /**
     *  Download the url into a file.
     *
     *  This needs to be multithreaded!!!!
     *
     *  @return an array of the contents found at url
     */
    protected void downloadURLtoFile(URL url)
    {
         logmsg("extract filename from " + url);
         String fileName = url.getFile();
         int i = fileName.lastIndexOf("/");
         if (i >= 0)
             fileName = fileName.substring(i);
         logmsg("name is " + fileName);
         File f = new File(downloadDir, fileName);
         logmsg("file is " + f);
         downloadURLtoFile(url, f);
    }

    /**
     *  Download the url into a file.
     *
     *  This needs to be multithreaded!!!!
     *
     *  @return an array of the contents found at url
     */
    protected void downloadURLtoFile(URL url, File f)
    {
        InputStream is;
        try {
            is = url.openStream();
        } catch (IOException ex) {
            ui.errorMessage("URL " + url + " is bad: " + ex);
            return ;
        }

        FileOutputStream fos;
        try {
            fos = new FileOutputStream(f);
        } catch (IOException ex) {
            ui.errorMessage("File " + f + " is bad: " + ex);
            return ;
        }

        try {
            copy(is, fos);
        } catch (IOException ex) {
            ui.errorMessage("File " + f + " failed to download: " + ex);
            return ;
        }

//        int next;
//        try {
//            next = is.available();
//        } catch (IOException ex) {
//            ui.errorMessage("URL " + url + " disconnected: " + ex);
//            return ;
//        }
//
//        while (next > 0)
//        {
//            try {
//                byte[] buf = new byte[is.available()];
//                is.read(buf);
//                fos.write(buf);
//                next = is.available();
//            } catch (IOException ex) {
//                ui.errorMessage("URL " + url + " download failed: " + ex);
//                return ;
//            }
//        }
//
//        try {
//            is.close();
//        } catch (IOException ex) {
//            logmsg("IOEx on close (ignored): " + ex);
//        }
//
//        try {
//            fos.close();
//        } catch (IOException ex) {
//            logmsg("IOEx on close (ignored): " + ex);
//        }
        ui.infoMessage("URL " + url + " downloaded");
        refreshList();
    }

    /**
     *  Read the url page and display it.
     *
     *  This needs to be multithreaded!!!!
     *
     *  @return an array of the contents found at url
     */
    void displayURL(URL url)
    {
        byte[] b;
        try {
            RawHttp http = new RawHttp(url, bug);
            b = http.getPage(10240);
        } catch (RawException ex) {
            ui.errorMessage("URL " + url + " cannot access: " + ex);
                return ;
        }
        showPage(b);
    }



    private void showPage(byte[] page)
    {
        if (page == null)
        {
            ui.errorMessage("No Page to show?");
            return;
        }

//        try
//        {
            text.setText(new String(page));
            textscroll.getViewport().setViewPosition( new Point(1,1) );
//        }
//        catch (Exception e)
//        {
//            e.printStackTrace();
//            ui.errorMessage("Error while opening page");
//        }
    }

    private void deletePackage()
    {
        String s = (String)list.getSelectedValue();
        if (s == null)
        {
            ui.errorMessage("No file selected ?");
            return ;
        }
        File f = new File(downloadDir, s);
        f.delete();
        refreshList();
    }

    private void installPackage()
    {
        String s = (String)list.getSelectedValue();
        if (s == null)
        {
            ui.errorMessage("No Install Package Selected");
            return ;
        }
        logmsg("String ... " + s);
        File f = new File(downloadDir, s);
        installPackage(f);
    }

    private void installPackage(File f)
    {
        if (!f.exists())
        {
            ui.errorMessage("Package " + f + " does not exist?");
            return ;
        }
       
        logmsg("Installing ... " + f);

        logmsg("Reading ... " + f);
        FileInputStream fis;
        try {
            fis = new FileInputStream(f);
        } catch (FileNotFoundException ex) {
            ui.errorMessage("Package " + f + " does not exist: " + ex);
            return ;
        }

        logmsg("Unzipping ... " + f);
        ZipInputStream zis = new ZipInputStream(fis);
        boolean notEOF = true;
        while (notEOF)
        {
            try {
                ZipEntry ze = zis.getNextEntry();
                if (ze == null)               // is EOF!
                    break ;
                installInDir(installDir, ze, zis);
                zis.closeEntry();
            } catch (IOException ex) {
                ui.errorMessage("zip failed: " + ex);
                return ;
            }
        }

        ui.infoMessage("package " + f.getName() + " is installed.\n\n" +
              "Now restart WebFunds and the package should be started.\n\n" +
              "( Later generations of WebFunds should handle this better.)");
        //PackageStarterChoice ps = new PackageStarterChoice(f);
    }

    private void installInDir(File dir, ZipEntry ze, InputStream is)
        throws IOException
    {
        String name = ze.getName();
        File f = new File(dir, name);
        logmsg(f.toString());
        
        if (ze.isDirectory())
        {
            if (f.exists() && !f.isDirectory())
                f.delete();
            if (!f.exists())
                f.mkdirs();
            if (!f.exists() || !f.isDirectory())
                throw new IOException("directory " + f + " failed");
            return ;
        }

        if (f.exists())
            f.delete();

        FileOutputStream fos;
        try {
            fos = new FileOutputStream(f);
        } catch (FileNotFoundException ex) {
            throw new IOException("file " + f + " cannot open for write: "+ex);
        }

        try {
            copy(is, fos);
        } catch (FileNotFoundException ex) {
            throw new IOException("file " + f + " copy failed: " + ex);
        }


    }


    private static void copy(InputStream is, OutputStream os)
        throws IOException
    {
        int size = 10240;
        byte[] buf = new byte[size];

        int offset = 0;
        while (is.available() > 0)
        {
            int i;
            i = is.read(buf, offset, size - offset);
            if (i == -1)                   // EOF!
               break ;
            if (i <= 0)
               throw new IOException("read returned " + i);
// logmsg("i == " + i + ";  offset == " + offset + "   (" + size + ")");
            offset += i;
            if (offset < size)             // partial read?
                continue ;                 // keep reading until full

            os.write(buf);
            offset = 0;
        }

        if (offset > 0)
            os.write(buf, 0, offset);
        os.flush();
    }


    JButton installButton;

    private void addUrlPanel(JPanel panel)
    {
        urlField             = new JTextField(50);
        JLabel urllabel = new JLabel("URL: ");
        JButton goButton  = new JButton(GO_BUTTON);
        JButton fileButton  = new JButton(FILE_BUTTON);
        installButton  = new JButton(INSTALL_BUTTON);
        installButton.setEnabled(false);

        GridBagConstraints c = new GridBagConstraints();

        panel.setLayout(new GridBagLayout());
        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 1;
        c.weightx = 0.0;
        c.weighty = 0.5;
        c.anchor = GridBagConstraints.NORTHWEST;
        c.fill = GridBagConstraints.NONE;
        c.insets = new Insets(2, 2, 2, 2);
        panel.add(urllabel, c);

        c.gridx = 1;
        c.gridwidth = GridBagConstraints.RELATIVE;
        c.weightx = 1.0;
        c.weighty = .5;
        c.fill = GridBagConstraints.BOTH;
        panel.add(urlField, c);
               
        c.gridx = 2;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.weightx = 0.0;
        c.weighty = .5;
        c.fill = GridBagConstraints.NONE;
        panel.add(goButton, c);

        //
        //  Next row - the button bar.
        //  Adding a 3rd button doesn't work?
        //
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = GridBagConstraints.RELATIVE;
        c.weightx = 0.0;
        c.anchor = GridBagConstraints.SOUTH;
        c.fill = GridBagConstraints.NONE;
        panel.add(installButton, c);

//        c.gridx = 1;
//        c.gridwidth = GridBagConstraints.REMAINDER;
//        c.weightx = 1.0;
//        c.weighty = .5;
//        c.fill = GridBagConstraints.NONE;
//        panel.add(fileButton, c);
               
        goButton.addActionListener( this );
        installButton.addActionListener( this );
//        fileButton.addActionListener( this );
    }

    public static void main(String[] args)
        throws Exception
    {
        String dir = ".";
        if (args.length > 0)
            dir = args[0];

        UpgradesManager cb = new UpgradesManager();
        cb.bug = new PrintWriter(System.err, true);
        cb.setUInterface(new UInterfaceImpl());
        cb.setContractStore(new ChangeContractStore(new File(dir)));
        cb.init();
        cb.start();
    }
}