gt:                     String msg = figureStatus(exitval);
context: /*
    This file is part of the "UpLib 1.7.11" release.
    Copyright (C) 2003-2011  Palo Alto Research Center, Inc.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU 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 General Public License for more details.
    
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
  
  /*
   * UpLibDropTarget.java is a portable application that allows files
   * to be dropped on top of it, upon which it submits them to the UpLib
   * repository.
   */
  
  package com.parc.uplib.portal;
  
  import java.awt.CardLayout;
  import java.awt.Color;
  import java.awt.Container;
  import java.awt.Dimension;
  import java.awt.Font;
  import java.awt.Frame;
  import java.awt.Graphics;
  import java.awt.Graphics2D;
  import java.awt.GraphicsConfiguration;
  import java.awt.Point;
  import java.awt.RenderingHints;
  import java.awt.datatransfer.DataFlavor;
  import java.awt.datatransfer.Transferable;
  import java.awt.datatransfer.UnsupportedFlavorException;
  import java.awt.dnd.DnDConstants;
  import java.awt.dnd.DropTarget;
  import java.awt.dnd.DropTargetDragEvent;
  import java.awt.dnd.DropTargetDropEvent;
  import java.awt.dnd.DropTargetEvent;
  import java.awt.dnd.DropTargetListener;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.MouseEvent;
  import java.awt.geom.AffineTransform;
  import java.awt.image.AffineTransformOp;
  import java.awt.image.BufferedImage;
  import java.io.BufferedReader;
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.net.URL;
  import java.util.Collections;
  import java.util.Enumeration;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.Set;
  import java.util.Vector;
  import java.util.logging.Logger;
  import java.util.regex.Pattern;
  
  import javax.imageio.ImageIO;
  import javax.swing.AbstractButton;
  import javax.swing.BorderFactory;
  import javax.swing.Box;
  import javax.swing.ButtonGroup;
  import javax.swing.ImageIcon;
  import javax.swing.JButton;
  import javax.swing.JCheckBox;
  import javax.swing.JComponent;
  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JOptionPane;
  import javax.swing.JPanel;
  import javax.swing.JPasswordField;
  import javax.swing.JRadioButton;
  import javax.swing.JScrollPane;
  import javax.swing.JSlider;
  import javax.swing.JSpinner;
  import javax.swing.JTextArea;
  import javax.swing.JTextField;
  import javax.swing.SpinnerNumberModel;
  import javax.swing.SwingConstants;
  import javax.swing.TransferHandler;
  import javax.swing.border.Border;
  import javax.swing.border.CompoundBorder;
  import javax.swing.border.EmptyBorder;
  import javax.swing.border.LineBorder;
  
  import com.parc.uplib.util.Configurator;
  import com.parc.uplib.util.ErrorDialog;
  import com.parc.uplib.util.LogStackTrace;
  import com.parc.uplib.util.WorkPopup;
  import com.parc.uplib.util.WorkThread;
  
  public class Portal extends JPanel implements WorkThread.DialogCounter, DropTargetListener {
  
      private final static int N_DIVISIONS = 60;
  
      private final static int DROPSTATE_NO_DROP = 1;
      private final static int DROPSTATE_GOOD_DROP = 2;
      private final static int DROPSTATE_BAD_DROP = 3;
      
      private static class UploadFilenameFilter implements java.io.FilenameFilter {
          public UploadFilenameFilter () {
          }
          public boolean accept (File dir, String name) {
              return (! (name.startsWith(".") || name.startsWith("#")));
          }
      }
  
      private final static UploadFilenameFilter UPLOAD_FILENAME_FILTER = new UploadFilenameFilter();
  
      final static Color BACKGROUND_COLOR = new Color(.878f, .941f, .973f);
      final static Color TOOLS_COLOR = new Color(.754f, .848f, .910f);
      final static Color UPLIB_ORANGE = new Color(.937f, .157f, .055f);
      final static Color WHITE = new Color(1.0f, 1.0f, 1.0f);
      final static Color BLACK = new Color(0.0f, 0.0f, 0.0f);
      final static Color BORDER_GRAY = new Color(0.7f, 0.7f, 0.7f);
  
      protected static Pattern quotes = Pattern.compile("'");
      protected static String addDocumentProgramString = null;
      protected static String getDocumentProgramString = null;
      private static String uplibVersion = null;
      private static String drycleanURL = null;
  
      private static BufferedImage logoImage = null;
      private static ImageIcon uplib_favicon = null;
      private static BufferedImage swirlImage = null;
      private static BufferedImage docImage = null;
      private static ImageIcon docIcon = null;
      private static BufferedImage badDropImage = null;
      private static BufferedImage goodDropImage = null;
      private static BufferedImage[] rotatedSwirlImages = new BufferedImage[N_DIVISIONS];
      private static BufferedImage[] rotatedDocImages = new BufferedImage[N_DIVISIONS];
      private static RenderingHints logo_rendering_hints = null;
      private static PortalTransferHandler pth = null;
  
      private static Runtime theRuntime = Runtime.getRuntime();
  
      private static boolean is_mac = false;
      private static boolean is_windows = false;
  
      private static float doc_size_increment = 1.0f;
  
      // --------------------- private instance variables -------------------
  
      // logger to send messages to
      private Logger logger;
  
      // the rotated swirl image that's current
      private int which_swirl_image = 0;
      private int which_doc_image = 0;
      // the size of the spinning document icon, if displayed
      private float doc_size = 0.0f;
  
      // "sticky" search and upload settings
      private String filepath = null;
      private String query = null;
      private File   currentDir = null;
      private int rememberedMinScore = 25;
      private String theRepoURL = null;
      private String theRepoPassword = null;
      private String retrieval_format = null;
      private String retrieval_action = null;
      private boolean show_popup = true;
      
      // lists of currently active uploads and searches
      private java.util.List uploads;
      private java.util.List searches;
  
      // current state of drop acceptance
      private int drop_status = DROPSTATE_NO_DROP;
  
      // is there a query dialog currently being displayed?
      private int dialog_showing = 0;
  
      // should swirling be used in display of portal?
      private boolean do_swirl = true;
  
      // list of listeners to notify when some action is performed
      private LinkedList listeners;
  
      static {
          try {
              is_mac = System.getProperty("os.name").toLowerCase().startsWith("mac");
              is_windows = System.getProperty("os.name").toLowerCase().startsWith("win");
  
              findResources();
  
          } catch (Exception x) {
              LogStackTrace.severe(Logger.getLogger("global"), "Can't load resources needed for Portal widget", x);
          }
      }
  
      private static class AnimationThread extends Thread {
  
          private Set portals;
          private boolean exiting;
  
          public AnimationThread () {
              super("com.parc.uplib.portal.Portal.AnimationThread");
              setDaemon(true);
              portals = new HashSet();
              exiting = false;
          }
  
          synchronized public void exit () {
              exiting = true;
          }
  
          public void run () {
  
              // set a timer to periodically check the number of active uploads
              // and update the display
  
              int loop_counter = 0;
              Iterator portals_iterator;
              Portal portal;
  
              while (! exiting) {
  
                  try {
                      Thread.sleep(100);  // sleep 100 ms
                  } catch (InterruptedException x) {
                      // no big deal
                  };
  
                  loop_counter += 1;
  
                  portals_iterator = portals.iterator();
  
                  while (portals_iterator.hasNext()) {
  
                      portal = (Portal) (portals_iterator.next());
                      java.util.List current_uploads = portal.currentUploads();
                      java.util.List current_searches = portal.currentSearches();
  
                      // go through the current_uploads list and
                      // current_searches list and check to see if there are any
                      // dead soldiers
                      for (int i = 0;  i < current_uploads.size(); ) {
                          UploadThread t = (UploadThread) current_uploads.get(i);
                          int s = t.getWorkerState();
                          if (s == WorkThread.PROCSTATE_COMPLETE) {
                              current_uploads.remove(t);
                              int stat = t.exitval;
                              String filename = t.filename;
                              if (filename != null)
                                  portal.notifyActionListeners(new DocumentUploaded(portal, filename, stat));
                              portal.repaint();
                          } else if (s == WorkThread.PROCSTATE_INITIALIZATION) {
                              i += 1;
                          } else {
                              i += 1;
                          }
                      }
  
                      for (int i = 0;  i < current_searches.size(); ) {
                          SearchThread t = (SearchThread) current_searches.get(i);
                          int s = t.getWorkerState();
                          if (s == WorkThread.PROCSTATE_COMPLETE) {
                              current_searches.remove(t);
                              String query = portal.getQuery();
                              int stat = t.exitval;
                              if (query != null)
                                  portal.notifyActionListeners(new SearchPerformed(portal, query));
                              portal.repaint();
                          } else {
                              i += 1;
                          }
                      }
  
                      portal.incrementSwirlImage();
                  }
              }
  
          }
  
          private static AnimationThread the_animation_thread = null;
  
          public static void addPortal (Portal p) {
              synchronized(AnimationThread.class) {
                  if (the_animation_thread != null)
                      the_animation_thread.portals.add(p);
              }
          }
  
          public static void removePortal (Portal p) {
              synchronized(AnimationThread.class) {
                  if (the_animation_thread != null)
                      the_animation_thread.portals.remove(p);
              }
          }
  
          public static synchronized void ensurePortalAnimationThread () {
              synchronized (AnimationThread.class) {
                  if (the_animation_thread == null) {
                      the_animation_thread = new AnimationThread();
                      the_animation_thread.setDaemon(true);
                      the_animation_thread.start();
                  }
              }
          }
      }
  
      public static class StickyPropertySet extends java.awt.event.ActionEvent {
          final static String ACTION_NAME = "StickyPropertySet";
          String name;
          String value;
          public StickyPropertySet (Portal p, String pname, String pvalue) {
              super(p, ActionEvent.ACTION_PERFORMED, ACTION_NAME);
              this.name = pname;
              this.value = pvalue;
          }
          public String getName () {
              return name;
          }
          public String getValue() {
              return value;
          }
      }
  
      public static class DocumentUploaded extends java.awt.event.ActionEvent {
          final static String ACTION_NAME = "DocumentUploaded";
          String document;
          int status;
          public DocumentUploaded (Portal p, String docpath, int status) {
              super(p, ActionEvent.ACTION_PERFORMED, ACTION_NAME);
              this.document = docpath;
              this.status = status;
          }
          public String getDocument () {
              return document;
          }
          public int getStatus() {
              return status;
          }
      }
  
      public static class SearchPerformed extends java.awt.event.ActionEvent {
          final static String ACTION_NAME = "SearchPerformed";
          String query;
          public SearchPerformed (Portal p, String query) {
              super(p, ActionEvent.ACTION_PERFORMED, ACTION_NAME);
              this.query = query;
          }
          public String getQuery () {
              return query;
          }
      }
  
      private class GetDocumentPopup extends WorkPopup
          implements ActionListener {
  
          String myRepoURL;
          String myRepoPassword;
          String format;
          String action;
  
          JTextField      repository_widget;
          JCheckBox       stickyrepo_widget;
          JPasswordField  password_widget;
          JTextField      query_widget;
          JTextField      action_widget;
          JSlider         minscore_widget;
          JSpinner        format_widget;
          JCheckBox       pickall_widget;
          private ButtonGroup format_buttons;
  
          JButton         submit_button;
          JButton         cancel_button;
  
          private String  myquery;
  
          GetDocumentPopup (Frame frame, String q, String repoURL, String repoPassword, String format, String action) {
              super (frame, false);
              myquery = q;
              myRepoURL = repoURL;
              myRepoPassword = repoPassword;
              this.action = action;
              this.format = format;
              // getLogger().info("URL is " + repoURL + ", password is " + repoPassword);
              finish();
          }
  
          public void initValues() {
          }
  
          public String getFormat() {
              return format_buttons.getSelection().getActionCommand();
          }
  
          public void setFormat(String f) {
              Enumeration e = format_buttons.getElements();
              while (e.hasMoreElements()) {
                  AbstractButton b = (AbstractButton) (e.nextElement());
                  format_buttons.setSelected(b.getModel(), b.getActionCommand().equals(f));
              }
          }
  
          public void initComponents() {
              Box s;
              JLabel f;
  
              setTitle("Find UpLib Document");
  
              Box b = Box.createVerticalBox();
              b.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
  
              Container contents = getContentPane();
  
              Font bold = new Font(null, Font.BOLD, contents.getFont().getSize());
              Font italic = new Font(null, Font.ITALIC, contents.getFont().getSize());
  
              s = Box.createHorizontalBox();
              f = new JLabel("Query");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              query_widget = new JTextField((myquery == null) ? "" : myquery);
              query_widget.addActionListener(this);
              query_widget.setActionCommand("queried");
              initialfocus = query_widget;
              s.add(Box.createHorizontalStrut(5));
              s.add(query_widget);
              s.add(Box.createHorizontalStrut(5));
              Border outer = new LineBorder(UPLIB_ORANGE, 3);
              Border inner = new EmptyBorder(5, 5, 5, 5);
              s.setBorder(new CompoundBorder(outer, inner));
              b.add(s);
  
              b.add(Box.createVerticalStrut(20));
  
              s = Box.createHorizontalBox();
              f = new JLabel("Repository");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              repository_widget = new JTextField((myRepoURL == null) ? "" : myRepoURL);
              s.add(Box.createHorizontalStrut(5));
              s.add(repository_widget);
              s.add(Box.createGlue());
              b.add(s);
  
              s = Box.createHorizontalBox();
              f = new JLabel("Password");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              password_widget = new JPasswordField((myRepoPassword == null) ? "" : myRepoPassword);
              s.add(Box.createHorizontalStrut(5));
              s.add(password_widget);
              s.add(Box.createHorizontalStrut(5));
              s.add(Box.createGlue());
              stickyrepo_widget = new JCheckBox("Remember", (myRepoURL != null) || (myRepoPassword != null));
              s.add(stickyrepo_widget);
              s.add(Box.createGlue());
              b.add(s);
  
              b.add(Box.createVerticalStrut(20));
  
              s = Box.createHorizontalBox();
              f = new JLabel("Format");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
  
              String[] formats = new String[] {"html", "pdf", "images", "text", "icon", "metadata", "uplib"};
  
              //            s.add(Box.createHorizontalStrut(5));
              // format_widget = new JSpinner(new SpinnerListModel(formats));
              // ((JSpinner.ListEditor)format_widget.getEditor()).getTextField().setEditable(false);
              // s.add(format_widget);
  
              format_buttons = new ButtonGroup();
              JRadioButton first = null, selected = null;
              for (int i = 0;  i < formats.length;  i++) {
                  Box s2 = Box.createHorizontalBox();
                  JRadioButton r = new JRadioButton(formats[i]);
                  if (i == 0)
                      first = r;
                  r.setActionCommand(formats[i]);
                  format_buttons.add(r);
                  if ((format != null) && format.equals(formats[i])) {
                      selected = r;
                      r.setSelected(true);
                  }
                  s2.add(r);
                  s2.setBorder(new LineBorder(BORDER_GRAY, 1));
                  if (i > 0) {
                      s.add(Box.createHorizontalStrut(2));
                  }
                  s.add(s2);
              }
              if (selected == null)
                  first.setSelected(true);
              
              b.add(s);
              b.add(Box.createVerticalStrut(5));
  
              s = Box.createHorizontalBox();
              f = new JLabel("Action");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              action_widget = new JTextField((action != null) ? action : "(default for format)");
              s.add(Box.createHorizontalStrut(5));
              s.add(action_widget);
              b.add(s);
  
              b.add(Box.createVerticalStrut(10));
  
              s = Box.createHorizontalBox();
              f = new JLabel("Min score");
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              // minscore_widget = new JSpinner(new SpinnerNumberModel(.75d, 0d, 1d, 0.05d));
              minscore_widget = new JSlider(0, 100, rememberedMinScore);
              s.add(minscore_widget);
              s.add(Box.createHorizontalStrut(10));
              pickall_widget = new JCheckBox("Show All", false);
              s.add(pickall_widget);
              b.add(s);
  
              s = Box.createHorizontalBox();
              s.add(Box.createHorizontalStrut(10));
              cancel_button = new JButton("Cancel");
              cancel_button.setActionCommand("cancel");
              cancel_button.addActionListener(this);
              s.add(cancel_button);
  
              f = new JLabel ("<html><b>UpLib " + uplibVersion + "</b> &middot; <small>PARC / ISL</small></html>",
                              uplib_favicon, SwingConstants.CENTER);
              f.setFont(new Font("Serif", Font.PLAIN, 14));
              f.setIconTextGap(10);
              f.setForeground(WHITE);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
  
              s.add(Box.createGlue());
              s.add(f);
              s.add(Box.createGlue());
  
              submit_button = new JButton("Submit");
              submit_button.setActionCommand("submit");
              submit_button.addActionListener(this);
              s.add(submit_button);
              s.add(Box.createHorizontalStrut(10));
              b.add(s);
  
              contents.add(b);
          }
  
          public void actionPerformed(ActionEvent e) {
              if ("submit".equals(e.getActionCommand())) {
                  submitted = true;
                  setVisible(false);
              }
              else if ("cancel".equals(e.getActionCommand())) {
                  cancelled = true;
                  setVisible(false);
              }
              else if ("queried".equals(e.getActionCommand())) {
                  submitted = true;
                  setVisible(false);
              }
              else
                  getLogger().info("Unexpected Action " + e);
          }
      }
  
      private class SearchThread extends WorkThread {
          
          private String[] UpLibGetDocumentExitVals = new String[] {
              "Error of some kind",
              "Invalid or missing password supplied",
              "No results matching query",
              "No results above score threshold",
              "Bad command-line option specified",
              "Couldn't communicate with the specified repository",
          };
  
          private static final int GETDOC_GENERAL_ERROR = 1;
          private static final int GETDOC_UNAUTHORIZED = 2;
          private static final int GETDOC_NO_RESULTS = 3;
          private static final int GETDOC_NO_RESULTS_ABOVE_THRESHOLD = 4;
          private static final int GETDOC_BAD_OPTION = 5;
          private static final int GETDOC_COMM_ERROR = 6;
  
          private Portal portal;
  
          public SearchThread (Portal top) {
              super(top.getLogger(), top);
              portal = top;
          }
  
          public void createDialog() throws WorkThread.DialogError {
              GraphicsConfiguration gc = portal.getGraphicsConfiguration();
              dialog = new GetDocumentPopup(new JFrame("Get Document", gc), query, theRepoURL, theRepoPassword,
                                            retrieval_format, retrieval_action);
              Dimension d = dialog.getSize();
              if (d.width < 300)
                  dialog.setSize(new Dimension(300, d.height));
              Point p = WorkPopup.bestLocation(dialog, gc.getBounds(), portal.getTopLevelAncestor().getBounds());
              if (p != null)
                  dialog.setLocation(p);
          }
  
          public Vector getCommandLine() {
  
              GetDocumentPopup theDialog = (GetDocumentPopup) dialog;
  
              thePassword = new String(theDialog.password_widget.getPassword());
  
              query = theDialog.query_widget.getText();
              String theRepository = theDialog.repository_widget.getText();
              retrieval_format = theDialog.getFormat();
              retrieval_action = theDialog.action_widget.getText();
              rememberedMinScore = theDialog.minscore_widget.getValue();
              float minscore = rememberedMinScore/100.0f;
  
              if (theDialog.stickyrepo_widget.isSelected()) {
                  setRepoURLAndPassword(theRepository, thePassword);
              } else {
                  setRepoURLAndPassword(null, null);
              }
  
              Vector c = new Vector();
              c.add(getDocumentProgramString);
              if (theDialog.pickall_widget.isSelected())
                  c.add("--pickall");
              else
                  c.add("--pickone");
              if (theRepository.length() > 0) {
                  c.add("--repository=" + theRepository);
              };
              if (thePassword.equals("(none)") || thePassword.length() == 0) {
                  // do something somewhere
                  c.add("--nopassword");
              } else {
                  addEnvironmentProperty("UPLIB_PASSWORD", thePassword);
              }
              if (!(retrieval_format == null || retrieval_format.length() == 0 || retrieval_format.equals("(default)")))
                  c.add("--format=" + retrieval_format);
              if (!(retrieval_action == null || retrieval_action.length() == 0 || retrieval_action.equals("(default for format)")))
                  c.add("--action=" + retrieval_action);
              c.add("--minscore=" + minscore);
  
              c.add(quoteit(query));
  
              return c;
          }
  
          private String figureStatus (int exitval) {
              if (exitval < 1)
                  return null;
              else if (exitval == GETDOC_UNAUTHORIZED) {
                  if (thePassword.equals("(none)") || thePassword.length() == 0)
                      return "No password supplied.";
                  else
                      return "Invalid password supplied.";
              } else if (exitval == GETDOC_COMM_ERROR) {
                  return "Couldn't communicate with the UpLib repository.";
              } else if (exitval > UpLibGetDocumentExitVals.length)
                  return UpLibGetDocumentExitVals[0];
              else
                  return UpLibGetDocumentExitVals[exitval-1];
          }
  
          public void finalCleanup() {
              if (!cancelled) {
                  if (exitval != 0) {
                      String msg = figureStatus(exitval);
                      ErrorDialog.say(msg, (exitval == 1) ? error_output.toString() : null, "Search:  " + query);
                      // JOptionPane.showMessageDialog(null, msg, "Search:  " + query, JOptionPane.ERROR_MESSAGE);
                  } else {
                      query = null;
                  }
              }
          }
  
      }
  
      private class SubmissionParameterPopup extends WorkPopup
          implements ActionListener {
  
          String theFilename;
          String myRepoURL;
          String myRepoPassword;
  
          JTextField     repository_widget;
          JCheckBox      stickyrepo_widget;
          JPasswordField password_widget;
          JTextField     categories_widget;
          JTextField     authors_widget;
          JTextField     title_widget;
          JTextField     keywords_widget;
          JTextField     date_widget;
          JTextField     source_widget;
          JSpinner       dpi_widget;
          ButtonGroup    dpi_buttons;
  
          JCheckBox      monochrome_widget;
          JCheckBox      notext_widget;
          JCheckBox      keepblankpages_widget;
          JCheckBox      dryclean_widget;
  
          JButton        submit_button;
          JButton        cancel_button;
  
          SubmissionParameterPopup (Frame frame, String filename, String repoURL, String repoPassword) {
              super (frame, false);
              theFilename = filename;
              myRepoURL = repoURL;
              myRepoPassword = repoPassword;
              finish();
          }
  
          public int getDPI () {
              String dpi = dpi_buttons.getSelection().getActionCommand();
              if (dpi == "auto")
                  return 0;
              else if (dpi == "75")
                  return 75;
              else if (dpi == "other")
                  return ((SpinnerNumberModel)(dpi_widget.getModel())).getNumber().intValue();
              return 0;
          }
  
          private JTextField addField (String fieldname, Box b, Font font, Vector labels) {
  
              JLabel f;
              JTextField w;
              Box s;
  
              s = Box.createHorizontalBox();
              f = new JLabel(fieldname);
              if (font != null)
                  f.setFont(font);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              labels.add(f);
              s.add(f);
              w = new JTextField();
              s.add(Box.createHorizontalStrut(5));
              s.add(Box.createGlue());
              s.add(w);
              s.add(Box.createGlue());
              b.add(s);
  
              return w;
          }
  
          public void initValues() {
          }
  
          public void initComponents() {
              Box s, s2, s3;
              JLabel f;
              Vector labels = new Vector();
  
              setTitle("UpLib Upload Parameters");
  
              Box b = Box.createVerticalBox();
              b.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
  
              Container contents = getContentPane();
  
              Font bold = new Font(null, Font.BOLD, contents.getFont().getSize());
              Font italic = new Font(null, Font.ITALIC, contents.getFont().getSize());
  
              s = Box.createHorizontalBox();
              s.add(Box.createHorizontalStrut(10));
              s.add(Box.createGlue());
              f = new JLabel();
              f.setFont(bold);
              if (theFilename.length() > 100)
                  f.setText(theFilename.substring(0,50) + "..." + theFilename.substring(theFilename.length()-50, theFilename.length()));
              else
                  f.setText(theFilename);
              s.add(f);
              s.add(Box.createGlue());
              s.add(Box.createHorizontalStrut(10));
              b.add(s);              
  
              b.add(Box.createVerticalStrut(10));
  
              s = Box.createHorizontalBox();
              f = new JLabel("Repository");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              labels.add(f);
              s.add(f);
              repository_widget = new JTextField((myRepoURL == null) ? "" : myRepoURL);
              s.add(Box.createHorizontalStrut(5));
              s.add(repository_widget);
              s.add(Box.createGlue());
              b.add(s);
  
              s = Box.createHorizontalBox();
              f = new JLabel("Password");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              labels.add(f);
              s.add(f);
              password_widget = new JPasswordField((myRepoPassword == null) ? "" : myRepoPassword);
              s.add(Box.createHorizontalStrut(5));
              s.add(Box.createGlue());
              s.add(password_widget);
              s.add(Box.createHorizontalStrut(5));
              stickyrepo_widget = new JCheckBox("Remember", (myRepoURL != null) || (myRepoPassword != null));
              s.add(stickyrepo_widget);
              s.add(Box.createGlue());
              b.add(s);
  
              b.add(Box.createVerticalStrut(10));
  
              title_widget = addField("Title", b, italic, labels);
              initialfocus = title_widget;
              authors_widget = addField("Authors", b, italic, labels);
              date_widget = addField("Date", b, italic, labels);
              categories_widget = addField("Categories", b, italic, labels);
              keywords_widget = addField("Keywords", b, italic, labels);
              source_widget = addField("Source", b, italic, labels);
  
              b.add(Box.createVerticalStrut(10));
  
              s = Box.createHorizontalBox();
              f = new JLabel("DPI:");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              dpi_buttons = new ButtonGroup();
              JRadioButton r = new JRadioButton("auto");
              r.setActionCommand("auto");
              dpi_buttons.add(r);
              r.setSelected(true);
              s2 = Box.createHorizontalBox();
              s3 = Box.createVerticalBox();
              s3.add(Box.createGlue());
              s3.add(r);
              s3.add(Box.createGlue());
              s2.add(s3);
              s2.setBorder(new LineBorder(BORDER_GRAY, 1));
              s.add(s2);
              s.add(Box.createHorizontalStrut(3));
              r = new JRadioButton("75");
              r.setActionCommand("75");
              dpi_buttons.add(r);
              s2 = Box.createHorizontalBox();
              s3 = Box.createVerticalBox();
              s3.add(Box.createGlue());
              s3.add(r);
              s3.add(Box.createGlue());
              s2.add(s3);
              s2.setBorder(new LineBorder(BORDER_GRAY, 1));
              s.add(s2);
              s.add(Box.createHorizontalStrut(3));
              s2 = Box.createHorizontalBox();
              r = new JRadioButton("other");
              r.setActionCommand("other");
              dpi_buttons.add(r);
              s2.add(r);
              dpi_widget = new JSpinner(new SpinnerNumberModel(400, 50, 600, 5));
              s2.add(dpi_widget);
              s2.setBorder(new LineBorder(BORDER_GRAY, 1));
              s.add(s2);
              s.add(Box.createGlue());
              b.add(s);
  
              s = Box.createHorizontalBox();
              monochrome_widget = new JCheckBox("No color", false);
              s.add(monochrome_widget);
              s.add(Box.createGlue());
              notext_widget = new JCheckBox("No text", false);
              s.add(notext_widget);
              s.add(Box.createGlue());
              keepblankpages_widget = new JCheckBox("Keep blank pages", false);
              s.add(keepblankpages_widget);
              if (drycleanURL != null) {
                  s.add(Box.createGlue());
                  dryclean_widget = new JCheckBox("Dryclean", false);
                  s.add(dryclean_widget);
              } else {
                  dryclean_widget = null;
              }
              b.add(s);
  
              b.add(Box.createVerticalStrut(10));
  
              s = Box.createHorizontalBox();
              s.add(Box.createHorizontalStrut(10));
              cancel_button = new JButton("Cancel");
              cancel_button.setActionCommand("cancel");
              cancel_button.addActionListener(this);
              s.add(cancel_button);
  
              f = new JLabel ("<html><b>UpLib " + uplibVersion + "</b> &middot; <small>PARC / ISL</small></html>",
                              uplib_favicon, SwingConstants.CENTER);
              f.setFont(new Font("Serif", Font.PLAIN, 14));
              f.setIconTextGap(10);
              f.setForeground(WHITE);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
  
              s.add(Box.createGlue());
              s.add(f);
              s.add(Box.createGlue());
  
              submit_button = new JButton("Submit");
              submit_button.setActionCommand("submit");
              submit_button.addActionListener(this);
              s.add(submit_button);
              s.add(Box.createHorizontalStrut(10));
              b.add(s);
  
              contents.add(b);
  
          }
  
          public void actionPerformed(ActionEvent e) {
              if ("submit".equals(e.getActionCommand())) {
                  if (repository_widget.getText().length() > 0) {
                      submitted = true;
                      setVisible(false);
                  } else {
                      JOptionPane.showMessageDialog(this, "No repository specified.", "Can't submit", JOptionPane.ERROR_MESSAGE);
                  }
              }
              else if ("cancel".equals(e.getActionCommand())) {
                  cancelled = true;
                  filepath = null;
                  setVisible(false);
              }
          }
      }
  
      private class SnippetSubmissionPopup extends WorkPopup
          implements ActionListener {
  
          String theSnippet;
          String myRepoURL;
          String myRepoPassword;
  
          JTextField     repository_widget;
          JCheckBox      stickyrepo_widget;
          JPasswordField password_widget;
          JTextField     categories_widget;
          JTextField     authors_widget;
          JTextField     title_widget;
          JTextField     keywords_widget;
          JTextField     date_widget;
          JTextField     source_widget;
          // SnippetEditorPane    snippet_widget;
          JTextArea      snippet_widget;
  
          JButton        submit_button;
          JButton        cancel_button;
  
          SnippetSubmissionPopup (Frame frame, String snippet, String repoURL, String repoPassword) {
              super (frame, false);
              theSnippet = snippet;
              myRepoURL = repoURL;
              myRepoPassword = repoPassword;
              finish();
          }
  
          private JTextField addField (String fieldname, Box b, Font font, Vector labels) {
  
              JLabel f;
              JTextField w;
              Box s;
  
              s = Box.createHorizontalBox();
              f = new JLabel(fieldname);
              if (font != null)
                  f.setFont(font);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              labels.add(f);
              s.add(f);
              w = new JTextField();
              s.add(Box.createHorizontalStrut(5));
              s.add(Box.createGlue());
              s.add(w);
              s.add(Box.createGlue());
              b.add(s);
  
              return w;
          }
  
          public void initValues() {
          }
  
          public void initComponents() {
              Box s, s2, s3;
              JLabel f;
              Vector labels = new Vector();
  
              setTitle("UpLib Upload Parameters");
  
              Box b = Box.createVerticalBox();
              b.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
  
              Container contents = getContentPane();
  
              Font bold = new Font(null, Font.BOLD, contents.getFont().getSize());
              Font italic = new Font(null, Font.ITALIC, contents.getFont().getSize());
              Font typewriter = new Font("Monospaced", Font.PLAIN, contents.getFont().getSize());
  
              s = Box.createHorizontalBox();
              f = new JLabel("Repository");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              labels.add(f);
              s.add(f);
              repository_widget = new JTextField((myRepoURL == null) ? "(default)" : myRepoURL);
              s.add(Box.createHorizontalStrut(5));
              s.add(repository_widget);
              s.add(Box.createGlue());
              b.add(s);
  
              s = Box.createHorizontalBox();
              f = new JLabel("Password");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              labels.add(f);
              s.add(f);
              password_widget = new JPasswordField((myRepoPassword == null) ? "" : myRepoPassword);
              s.add(Box.createHorizontalStrut(5));
              s.add(Box.createGlue());
              s.add(password_widget);
              s.add(Box.createHorizontalStrut(5));
              stickyrepo_widget = new JCheckBox("Remember", (myRepoURL != null) || (myRepoPassword != null));
              s.add(stickyrepo_widget);
              s.add(Box.createGlue());
              b.add(s);
  
              b.add(Box.createVerticalStrut(10));
  
              s = Box.createHorizontalBox();
              f = new JLabel("Snippet:");
              f.setFont(italic);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              s.add(f);
              s.add(Box.createGlue());
              b.add(s);
              snippet_widget = new JTextArea(theSnippet);
              snippet_widget.setRows(8);
              snippet_widget.setLineWrap(true);
              snippet_widget.setWrapStyleWord(true);
              snippet_widget.setFont(typewriter);
              snippet_widget.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              JScrollPane jsp = new JScrollPane(snippet_widget,
                                                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                                                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
              b.add(jsp);
              b.add(Box.createVerticalStrut(10));
  
              title_widget = addField("Title", b, italic, labels);
              source_widget = addField("Source", b, italic, labels);
              initialfocus = source_widget;
              authors_widget = addField("Authors", b, italic, labels);
              date_widget = addField("Date", b, italic, labels);
              categories_widget = addField("Categories", b, italic, labels);
              categories_widget.setText("snippet");
              keywords_widget = addField("Keywords", b, italic, labels);
  
              b.add(Box.createVerticalStrut(10));
  
              s = Box.createHorizontalBox();
              s.add(Box.createHorizontalStrut(10));
              cancel_button = new JButton("Cancel");
              cancel_button.setActionCommand("cancel");
              cancel_button.addActionListener(this);
              s.add(cancel_button);
  
              f = new JLabel ("<html><b>UpLib " + uplibVersion + "</b> &middot; <small>PARC / ISL</small></html>",
                              uplib_favicon, SwingConstants.CENTER);
              f.setFont(new Font("Serif", Font.PLAIN, 14));
              f.setIconTextGap(10);
              f.setForeground(WHITE);
              f.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
  
              s.add(Box.createGlue());
              s.add(f);
              s.add(Box.createGlue());
  
              submit_button = new JButton("Submit");
              submit_button.setActionCommand("submit");
              submit_button.addActionListener(this);
              s.add(submit_button);
              s.add(Box.createHorizontalStrut(10));
              b.add(s);
  
              contents.add(b);
          }
  
          public Dimension getPreferredSize () {
              Dimension d = snippet_widget.getPreferredSize();
              // getLogger().info("first d is " + d);
              d = super.getPreferredSize();
              // getLogger().info("second d is " + d);
              return d;
          }
  
          public void actionPerformed(ActionEvent e) {
              if ("submit".equals(e.getActionCommand())) {
                  submitted = true;
                  setVisible(false);
              }
              else if ("cancel".equals(e.getActionCommand())) {
                  cancelled = true;
                  filepath = null;
                  setVisible(false);
              }
          }
      }
  
      private class UploadThread extends WorkThread {
          
          Portal portal;
          String filename;
          String repository;
          private boolean show_dialog;
          private SubmissionParameterPopup inner_dialog;
  
          public UploadThread (String theFilename, Portal top, boolean show_popup) {
              super(top.getLogger(), top);
              portal = top;
              filename = theFilename;
              show_dialog = show_popup;
              inner_dialog = null;
          }
          
          public void createDialog () throws WorkThread.DialogError {
              File pfile;            
              
              if (filename == null) {
                  if (filepath != null) {
                      filename = filepath;
                  } else {
                      Frame owner;
                      Container c = portal.getTopLevelAncestor();
                      if (!(c instanceof Frame)) {
                          owner = new Frame(portal.getGraphicsConfiguration());
                      } else {
                          owner = (Frame) c;
                      }
                      java.awt.FileDialog chooser = new java.awt.FileDialog(owner);
                      chooser.setMode(java.awt.FileDialog.LOAD);
                      chooser.setTitle("Select file to upload to UpLib");
                      chooser.setModal(true);
                      chooser.setResizable(true);
                      while (filename == null) {
                          if (currentDir != null) {
                              try {
                                  chooser.setDirectory(currentDir.getCanonicalPath());
                              } catch (IOException x) {
                                  LogStackTrace.warning(getLogger(), x);
                              }
                          }
                          chooser.setVisible(true);
                          String selFile = chooser.getFile();
                          if (selFile == null) {
                              dialog = null;
                              throw new WorkThread.DialogError("No file selected.");
                          } else if ((pfile = new File(chooser.getDirectory(), selFile)).canRead()) {
                              filename = pfile.getPath();
                              getLogger().info("Opening this file:  " + filename);
                          } else {
                              String possibleDir = chooser.getDirectory();
                              if ((possibleDir != null) && (new File(possibleDir)).exists()) {
                                  currentDir = new File(possibleDir);
                              }
                              if (pfile.exists()) {
                                  ErrorDialog.say("Can't read file " + pfile.getPath() + ".", null, "Unreadable File");
                              } else {
                                  ErrorDialog.say("File " + pfile.getPath() + " doesn't exist.", null, "Unreadable File");
                              }
                          }
                      }
                  }
              }
              filepath = filename;
              GraphicsConfiguration gc = portal.getGraphicsConfiguration();
              inner_dialog = new SubmissionParameterPopup(new JFrame("UpLib Upload Parameters", gc), filename,
                                                    portal.theRepoURL, portal.theRepoPassword);
              if (show_dialog) {
                  dialog = inner_dialog;
                  Dimension d = dialog.getSize();
                  if (d.width < 400)
                      dialog.setSize(new Dimension(400, d.height));
                  Point p = WorkPopup.bestLocation(dialog, gc.getBounds(), portal.getTopLevelAncestor().getBounds());
                  if (p != null)
                      dialog.setLocation(p);
              } else {
                  dialog = null;
                  inner_dialog.actionPerformed(new ActionEvent(inner_dialog, ActionEvent.ACTION_PERFORMED, "submit"));
              }
          }
  
          public Vector getCommandLine() {
  
              SubmissionParameterPopup theDialog = (SubmissionParameterPopup) ((dialog != null) ? dialog : inner_dialog);
  
              thePassword = new String(theDialog.password_widget.getPassword());
  
              repository = theDialog.repository_widget.getText();
              String authors = theDialog.authors_widget.getText();
              String keywords = theDialog.keywords_widget.getText();
              String categories = theDialog.categories_widget.getText();
              String title = theDialog.title_widget.getText();
              String date = theDialog.date_widget.getText();
              String source = theDialog.source_widget.getText();
              int tiffdpi = theDialog.getDPI();
  
              boolean noColor = theDialog.monochrome_widget.isSelected();
              boolean noText = theDialog.notext_widget.isSelected();
              boolean keepBlankPages = theDialog.keepblankpages_widget.isSelected();
              boolean dryclean = (theDialog.dryclean_widget == null) ? false : theDialog.dryclean_widget.isSelected();
  
              if (theDialog.stickyrepo_widget.isSelected()) {
                  setRepoURLAndPassword(repository, thePassword);
              } else {
                  setRepoURLAndPassword(null, null);
              }
  
              Vector c = new Vector();
              c.add(addDocumentProgramString);
              if (!repository.equals("(default)")) {
                  c.add("--repository=" + repository);
              };
              if (thePassword.equals("(none)") || thePassword.length() == 0) {
                  c.add("--nopassword");
              } else {
                  addEnvironmentProperty("UPLIB_PASSWORD", thePassword);
              }
              if (title.length() > 0) {
                  c.add("--title=" + quoteit(title, "title"));
              }
              if (authors.length() > 0) {
                  c.add("--authors=" + quoteit(authors, "authors"));
              }
              if (categories.length() > 0) {
                  c.add("--categories=" + quoteit(categories, "categories"));
              }
              if (keywords.length() > 0) {
                  c.add("--keywords=" + quoteit(keywords, "keywords"));
              }
              if (source.length() > 0) {
                  c.add("--source=" + quoteit(source, "source"));
              }
              if (date.length() > 0) {
                  c.add("--date=" + date);
              }
              if (tiffdpi > 0) {
                  c.add("--tiff-dpi=" + tiffdpi);
              }
              if (dryclean) {
                  c.add("--dryclean");
              };
              if (noColor) {
                  c.add("--nocolor");
              };
              if (noText) {
                  c.add("--notext");
              };
              if (keepBlankPages) {
                  c.add("--keepblankpages");
              };
              c.add(quoteit(filename));
  
              return c;
          }
  
          final static int ADDDOC_CONN_ERROR = 2;
          final static int ADDDOC_UNAUTHORIZED = 3;
          final static int ADDDOC_NO_PARSER = 4;
          final static int ADDDOC_PROCESS_ERROR = 5;
  
          private String figureStatus (int exitval) {
              getLogger().info("exitval is " + exitval);
              if (exitval < 1)
                  return null;
              else if (exitval == ADDDOC_UNAUTHORIZED) {
                  if (thePassword.equals("(none)") || thePassword.length() == 0)
                      return "No password supplied.";
                  else
                      return "Invalid password supplied.";
              } else if (exitval == ADDDOC_CONN_ERROR) {
                  return "Can't connect to repository at " + repository + ".";
              } else if (exitval == ADDDOC_NO_PARSER) {
                  return "No parser for the document's format.";
              } else if (exitval == ADDDOC_PROCESS_ERROR) {
                  return null;
              } else {
                  return null;
              }
          }
  
          public void finalCleanup() {
              if (exitval != 0) {
                  if (!cancelled) {
  