From: Fred T. Hamster Date: Tue, 29 May 2012 00:30:52 +0000 (-0400) Subject: updated code for kona libs, not quite working yet. X-Git-Tag: 2.140.90~1336 X-Git-Url: https://feistymeow.org/gitweb/?p=feisty_meow.git;a=commitdiff_plain;h=67d3d9a5e40685d3898f34a3651944c8a0c3e2ca updated code for kona libs, not quite working yet. --- diff --git a/kona/.classpath b/kona/.classpath new file mode 100644 index 00000000..12d4c4aa --- /dev/null +++ b/kona/.classpath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/kona/.project b/kona/.project new file mode 100644 index 00000000..8dd65d00 --- /dev/null +++ b/kona/.project @@ -0,0 +1,17 @@ + + + kona + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/kona/.settings/org.eclipse.jdt.core.prefs b/kona/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..be9cff3a --- /dev/null +++ b/kona/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Tue Feb 07 11:35:37 EST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/kona/lib/ant-junit.jar b/kona/lib/ant-junit.jar new file mode 100644 index 00000000..a759112a Binary files /dev/null and b/kona/lib/ant-junit.jar differ diff --git a/kona/lib/commons-logging-1.1.1-javadoc.jar b/kona/lib/commons-logging-1.1.1-javadoc.jar new file mode 100644 index 00000000..83e063f1 Binary files /dev/null and b/kona/lib/commons-logging-1.1.1-javadoc.jar differ diff --git a/kona/lib/commons-logging-1.1.1-sources.jar b/kona/lib/commons-logging-1.1.1-sources.jar new file mode 100644 index 00000000..00fc09cd Binary files /dev/null and b/kona/lib/commons-logging-1.1.1-sources.jar differ diff --git a/kona/lib/commons-logging-1.1.1.jar b/kona/lib/commons-logging-1.1.1.jar new file mode 100644 index 00000000..8758a96b Binary files /dev/null and b/kona/lib/commons-logging-1.1.1.jar differ diff --git a/kona/lib/commons-logging-adapters-1.1.1.jar b/kona/lib/commons-logging-adapters-1.1.1.jar new file mode 100644 index 00000000..2f23c350 Binary files /dev/null and b/kona/lib/commons-logging-adapters-1.1.1.jar differ diff --git a/kona/lib/commons-logging-api-1.1.1.jar b/kona/lib/commons-logging-api-1.1.1.jar new file mode 100644 index 00000000..bd451168 Binary files /dev/null and b/kona/lib/commons-logging-api-1.1.1.jar differ diff --git a/kona/lib/commons-logging-tests.jar b/kona/lib/commons-logging-tests.jar new file mode 100644 index 00000000..4b96759e Binary files /dev/null and b/kona/lib/commons-logging-tests.jar differ diff --git a/kona/lib/junit-4.5.jar b/kona/lib/junit-4.5.jar new file mode 100644 index 00000000..73392162 Binary files /dev/null and b/kona/lib/junit-4.5.jar differ diff --git a/kona/lib/log4j-1.2.16.jar b/kona/lib/log4j-1.2.16.jar new file mode 100644 index 00000000..3f9d8476 Binary files /dev/null and b/kona/lib/log4j-1.2.16.jar differ diff --git a/kona/log4j.properties b/kona/log4j.properties new file mode 100644 index 00000000..ef68572b --- /dev/null +++ b/kona/log4j.properties @@ -0,0 +1,18 @@ +# don't limit by the logging level, and use two appenders. +log4j.rootCategory=, TTY, LOGFILE + +# TTY is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.TTY=org.apache.log4j.ConsoleAppender +log4j.appender.TTY.Threshold=DEBUG +log4j.appender.TTY.layout=org.apache.log4j.PatternLayout +log4j.appender.TTY.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%-28c{2}] - %m%n + +# LOGFILE is set to be a RollingFileAppender using a PatternLayout. +log4j.appender.LOGFILE=org.apache.log4j.RollingFileAppender +log4j.appender.LOGFILE.File=dragdrop_test.log +log4j.appender.LOGFILE.MaxFileSize=10MB +log4j.appender.LOGFILE.MaxBackupIndex=10 +log4j.appender.LOGFILE.Threshold=DEBUG +log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout +log4j.appender.LOGFILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%-28c{2}] - %m%n + diff --git a/kona/src/org/feistymeow/dragdrop/DragonTransferHandler.java b/kona/src/org/feistymeow/dragdrop/DragonTransferHandler.java new file mode 100755 index 00000000..40833b58 --- /dev/null +++ b/kona/src/org/feistymeow/dragdrop/DragonTransferHandler.java @@ -0,0 +1,88 @@ +package org.feistymeow.dragdrop; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.TransferHandler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A transfer handler that can be extended and used to inter-operate with DragonDropManager. This + * object is not strictly necessary to use, but it can help if one has not already implemented one's + * own transfer handler. + * + * @author Chris Koeritz + * @copyright Copyright (c) 2012-$now By University of Virginia + * @license This file is free software; you can modify and redistribute it under the terms of the + * Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +@SuppressWarnings("serial") +public class DragonTransferHandler extends TransferHandler +{ + static private Log logger = LogFactory.getLog(DragonTransferHandler.class); + IDragonDropDataProvider c_provider; + + public DragonTransferHandler(IDragonDropDataProvider provider) + { + c_provider = provider; + } + + @Override + public boolean canImport(TransferSupport support) + { + if (support == null) return false; + if (!support.isDrop()) + return false; // we don't support cut&paste here. + logger.debug("canImport: base just saying okay."); + return true; + } + + @Override + protected Transferable createTransferable(JComponent c) + { + logger.debug("createTransferable: at base, returning ListTransferable."); + return new ListTransferable(c_provider.provideDragList()); + } + + @Override + protected void exportDone(JComponent source, Transferable data, int action) + { + logger.debug("exportDone: base got event for component " + source.toString()); + } + + @Override + public int getSourceActions(JComponent c) + { + return COPY; + } + + @Override + public boolean importData(TransferSupport support) + { + if (support == null) return false; + logger.debug("importData: at base..."); + + if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { + logger.debug("importing data with java files flavor"); + List files = ListTransferable.extractData(support.getTransferable()); + if ((files != null) && (files.size() != 0)) { + c_provider.consumeDropList(files, support.getDropLocation().getDropPoint()); + return true; + } + } else if (support.isDataFlavorSupported(ListTransferable.getURIListFlavor1()) + || support.isDataFlavorSupported(ListTransferable.getURIListFlavor2())) { + logger.debug("importing data with uri list flavor"); + List files = ListTransferable.extractData(support.getTransferable()); + if ((files != null) && (files.size() != 0)) { + c_provider.consumeDropList(files, support.getDropLocation().getDropPoint()); + return true; + } + } + logger.warn("passing importData request to superclass, which will probably fail."); + return super.importData(support); + } +} diff --git a/kona/src/org/feistymeow/dragdrop/IDragonDropDataProvider.java b/kona/src/org/feistymeow/dragdrop/IDragonDropDataProvider.java new file mode 100644 index 00000000..49641f49 --- /dev/null +++ b/kona/src/org/feistymeow/dragdrop/IDragonDropDataProvider.java @@ -0,0 +1,32 @@ +package org.feistymeow.dragdrop; + +import java.util.List; +import java.awt.Point; + +/** + * An interface for any object that can interact with a DragonTransferSupport to receive files (or + * other things) that are dropped on it and that can provide files (or other things) for dragging to + * another location. Note that the details of finding a selected node or determining what objects + * are relevant there is entirely up to the component. You probably do not need this interface if + * you have implemented your own TransferHandler. + * + * @author Chris Koeritz + * @copyright Copyright (c) 2012-$now By University of Virginia + * @license This file is free software; you can modify and redistribute it under the terms of the + * Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +public interface IDragonDropDataProvider +{ + /** + * A function that is invoked by the handler when some files or other objects are being dragged + * out of the parent. The handler expects the real provider to come up with a useful set of + * things to deliver at the drag target. + */ + public List provideDragList(); + + /** + * A function that is invoked by the d&d manager when a passel of objects have been dropped on + * the parent object. + */ + public boolean consumeDropList(List dropSet, Point cursor); +} diff --git a/kona/src/org/feistymeow/dragdrop/ListTransferable.java b/kona/src/org/feistymeow/dragdrop/ListTransferable.java new file mode 100644 index 00000000..76b4c361 --- /dev/null +++ b/kona/src/org/feistymeow/dragdrop/ListTransferable.java @@ -0,0 +1,311 @@ +package org.feistymeow.dragdrop; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; +import java.util.StringTokenizer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements a transferable object that understands URI lists as well as java file lists. This is + * useful for implementing file drag and drop that will work across different platforms (such as + * Gnome on Linux). + * + * @author Chris Koeritz + * @copyright Copyright (c) 2012-$now By University of Virginia + * @license This file is free software; you can modify and redistribute it under the terms of the + * Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +@SuppressWarnings("serial") +public class ListTransferable extends Vector implements Transferable +{ + static private Log logger = LogFactory.getLog(ListTransferable.class); + + public ListTransferable() + { + } + + public ListTransferable(Object initial) + { + if (initial != null) add(initial); + } + + public ListTransferable(List initial) + { + if (initial != null) addAll(initial); + } + + /** + * create a new flavor. this one understands URI lists, such as: file:///home/fred/arf.txt\r\n + * file:///etc/inputrc\r\n http://gruntose.com\r\n ... + */ + private static DataFlavor URIListFlavor; + static { + try { + URIListFlavor = new DataFlavor("text/uri-list;class=java.lang.String"); + } catch (ClassNotFoundException e) { + logger.error("should never happen", e); + } + } + private static DataFlavor AltURIListFlavor; + static { + try { + AltURIListFlavor = new DataFlavor("text/uri-list;representationclass=java.lang.String"); + } catch (ClassNotFoundException e) { + logger.error("should never happen", e); + } + } + + /** + * accessors for our special featured flavors of URI lists. + */ + public static DataFlavor getURIListFlavor1() + { + return URIListFlavor; + } + + public static DataFlavor getURIListFlavor2() + { + return AltURIListFlavor; + } + + /** + * register the types of transfers that we understand. this is really only the normal java file + * list and our new URI list. + */ + protected ArrayList FLAVORS = new ArrayList(Arrays.asList( + DataFlavor.javaFileListFlavor, URIListFlavor, AltURIListFlavor)); + + /** + * a function that must be overridden by derived classes if they are not initially seeding the + * vector of objects that we hold. the caller of this function expects it will populate the + * vector held here with usable objects. + */ + public boolean loadDataJustInTime(DataFlavor flavor) + { + logger.warn("base loadDataJustInTime. derived class should have implemented this."); + return false; + } + + /** + * using the set of files that we've been handed, we can do transfers using our two supported + * flavors. + */ + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, + java.io.IOException + { + if (flavor == null) return null; + if (size() == 0) { + logger.debug("size was zero, so loading data just in time"); + boolean worked = loadDataJustInTime(flavor); + if (!worked || (size() == 0)) { + logger.warn("failed to retrieve data just in time for getTransferData."); + return null; + } + } + // help from workaround at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4899516 + logger.debug("responding to flavor: " + flavor.toString()); + if (flavor.equals(DataFlavor.javaFileListFlavor)) { + logger.debug("java file list flavor..."); + List data = new java.util.ArrayList(); + data.addAll(this); + return data; + } else if (flavor.equals(URIListFlavor) || flavor.equals(AltURIListFlavor)) { + logger.debug("uri list flavor..."); + StringBuilder data = new StringBuilder(); + Iterator iter = iterator(); + while (iter.hasNext()) { + Object x = iter.next(); + if (x instanceof File) { + File elem = (File) x; + data.append(elem.toURI() + "\r\n"); + } else if (x instanceof String) { + data.append((String) x + "\r\n"); + } else { + logger.debug("did not know how to handle type in transfer: " + x.toString()); + } + } + logger.debug("returning URI string: " + data.toString()); + return data.toString(); + } else { + logger.debug("getTransferData: didn't know how to handle the requested flavor."); + throw new UnsupportedFlavorException(flavor); + } + } + + /** + * returns the list of all transfer flavors we understand. + */ + public DataFlavor[] getTransferDataFlavors() + { + return (DataFlavor[]) FLAVORS.toArray(new DataFlavor[FLAVORS.size()]); + } + + /** + * reports if a particular flavor is handled here. + */ + public boolean isDataFlavorSupported(DataFlavor flavor) + { + if (flavor == null) return false; + for (int i = 0; i < FLAVORS.size(); i++) { + if (flavor.equals((DataFlavor) FLAVORS.get(i))) { + return true; + } + } + logger.debug("failed to find flavor: " + flavor.toString()); + return false; + } + + /** + * a helper method that can process transfer data from either a java file list or a URI list. + */ + @SuppressWarnings("unchecked") + static public List extractData(Transferable tran) { + if (tran == null) return null; + if (tran.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { + logger.debug("extractData seeing java files flavor."); + try { + return (List) tran.getTransferData(DataFlavor.javaFileListFlavor); + } catch (Throwable cause) { + logger.error("extractData caught exception for java file list.", cause); + return null; + } + } else if (tran.isDataFlavorSupported(ListTransferable.getURIListFlavor1()) + || tran.isDataFlavorSupported(ListTransferable.getURIListFlavor2())) { + logger.debug("extractData seeing uri list flavor."); + try { + return textURIListToFileList((String) tran.getTransferData(getURIListFlavor1())); + } catch (Throwable cause) { + logger.error("extractData caught exception for URI list.", cause); + return null; + } + } + logger.error("extractData: Transferable did not support known data flavor."); + return null; + } + + /** + * translates the string in "data" into a list of Files. + * + * @param data + * a string formatted with possibly multiple URIs separated by CRLF. + * @return a list of the files as java File objects. many thanks to + * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4899516 + */ + public static List textURIListToFileList(String data) + { + if (data == null) return null; + List list = new ArrayList(0); + for (StringTokenizer st = new StringTokenizer(data, "\r\n"); st.hasMoreTokens();) { + String s = st.nextToken(); + if (s.startsWith("#")) { + // the line is a comment (as per the RFC 2483) + continue; + } + try { + java.net.URI uri = new java.net.URI(s); + java.io.File file = new java.io.File(uri); + list.add(file); + } catch (java.net.URISyntaxException e) { + // this is a malformed URI. + logger.error("Found a malformed URI of: " + data); + } catch (IllegalArgumentException e) { + // the URI is not a valid 'file:' URI + logger.error("Found invalid 'file:' URI of: " + data); + } + } + return list; + } + + /** + * This function will retrieve the file list from a standard file list flavor. + */ + @SuppressWarnings("unchecked") + public static List processStandardFileList(Transferable tran) + { + if (tran == null) return null; + logger.debug("trying java file list flavor."); + try { + return (List) tran.getTransferData(DataFlavor.javaFileListFlavor); + } catch (Throwable cause) { + logger.debug("failed to retrieve transfer data for standard java file list flavor.", + cause); + } + return new ArrayList(); + } + + /** + * checks if the transferable is appropriate to try to use as a java Reader. + */ + public static boolean checkReaderFlavor(Transferable tran) + { + if (tran == null) return false; + DataFlavor[] flavors = tran.getTransferDataFlavors(); + for (int i = 0; i < flavors.length; i++) { + if (flavors[i].isRepresentationClassReader()) + return true; + } + return false; + } + + /** + * Use a Reader to handle an incoming transferable. + */ + public static List processReaderFlavor(Transferable tran) + { + if (tran == null) return null; + logger.debug("trying URI list flavor."); + DataFlavor[] flavors = tran.getTransferDataFlavors(); + for (int i = 0; i < flavors.length; i++) { + if (flavors[i].isRepresentationClassReader()) { + // it looks like we can work with this flavor just fine. + logger.debug("found a reader flavor."); + try { + Reader reader = flavors[i].getReaderForText(tran); + BufferedReader br = new BufferedReader(reader); + return createFileArray(br); + } catch (Throwable cause) { + logger.debug("failed to scan reader for file list."); + } + } + } + return new ArrayList(); + } + + private static String ZERO_CHAR_STRING = "" + (char) 0; + + public static List createFileArray(BufferedReader bReader) { + if (bReader == null) return null; + try { + List list = new ArrayList(); + String line = null; + while ((line = bReader.readLine()) != null) { + try { + // kde seems to append a 0 char to the end of the reader + if (ZERO_CHAR_STRING.equals(line)) + continue; + File file = new java.io.File(new java.net.URI(line)); + list.add(file); + } catch (Exception ex) { + logger.error("Error with " + line + ": " + ex.getMessage()); + } + } + + return list; + } catch (IOException ex) { + logger.error("IOException while working on file list"); + } + return new ArrayList(); + } + +} diff --git a/kona/src/org/feistymeow/dragdrop/dragdrop_list_test.java b/kona/src/org/feistymeow/dragdrop/dragdrop_list_test.java new file mode 100644 index 00000000..afe63029 --- /dev/null +++ b/kona/src/org/feistymeow/dragdrop/dragdrop_list_test.java @@ -0,0 +1,183 @@ +package org.feistymeow.dragdrop; + +import java.awt.*; +import java.io.*; +import java.util.*; +import java.util.List; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.PropertyConfigurator; + +/** + * A demo of the DragonDropHandler being used with a JList. Much love to the internet for lots of + * examples. + * + * @author Chris Koeritz + * @copyright Copyright (c) 2012-$now By University of Virginia + * @license This file is free software; you can modify and redistribute it under the terms of the + * Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +@SuppressWarnings("serial") +public class dragdrop_list_test extends JFrame implements ListSelectionListener +{ + private DraggableDroppableList list; + private JTextField fileName; + static private Log logger = LogFactory.getLog(dragdrop_list_test.DraggableDroppableList.class); + + public dragdrop_list_test(String startPath) + { + super("dragdrop_test"); + + // Create the list and put it in a scroll pane + list = new DraggableDroppableList(); + DefaultListModel listModel = (DefaultListModel) list.getModel(); + list.setCellRenderer(new CustomCellRenderer()); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setSelectedIndex(0); + list.addListSelectionListener(this); + JScrollPane listScrollPane = new JScrollPane(list); + + String dirName = startPath + "/"; // make sure we think of it as a directory. + String filelist[] = new File(dirName).list(); + for (int i = 0; i < filelist.length; i++) { + String thisFileSt = dirName + filelist[i]; + File thisFile = new File(thisFileSt); + // skip directories for now. + if (thisFile.isDirectory()) + continue; + // skip dot files. + if (filelist[i].startsWith(".")) + continue; + try { + listModel.addElement(makeNode(thisFile.getName(), thisFile.toURI().toURL() + .toString(), thisFile.getAbsolutePath())); + } catch (java.net.MalformedURLException e) { + } + } + + fileName = new JTextField(50); + list.setSelectedIndex(0); + int sel_index = list.getSelectedIndex(); + Object obj_at_index = listModel.getElementAt(sel_index); + String name = obj_at_index.toString(); + fileName.setText(name); + + // Create a panel that uses FlowLayout (the default). + JPanel buttonPane = new JPanel(); + buttonPane.add(fileName); + + Container contentPane = getContentPane(); + contentPane.add(listScrollPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.NORTH); + } + + public void valueChanged(ListSelectionEvent e) + { + if (e.getValueIsAdjusting() == false) { + fileName.setText(""); + if (list.getSelectedIndex() != -1) { + String name = list.getSelectedValue().toString(); + fileName.setText(name); + } + } + } + + private static Hashtable makeNode(String name, String url, String strPath) + { + Hashtable hashtable = new Hashtable(); + hashtable.put("name", name); + hashtable.put("url", url); + hashtable.put("path", strPath); + return hashtable; + } + + public class DraggableDroppableList extends JList implements IDragonDropDataProvider + { + public DraggableDroppableList() + { + setModel(new DefaultListModel()); + setTransferHandler(new DragonTransferHandler(this)); + setDragEnabled(true); + } + + @Override + public boolean consumeDropList(List fileSet, Point location) + { + logger.debug("into consume dropped files, file set is:"); + for (int i = 0; i < fileSet.size(); i++) { + logger.debug(" " + ((File) fileSet.get(i)).getPath()); + } + return true; + } + + @Override + public List provideDragList() + { + ArrayList toReturn = new ArrayList(); + if (getSelectedIndex() == -1) + return toReturn; + Object obj = getSelectedValue(); + if (obj != null) { + @SuppressWarnings("unchecked") + Hashtable table = (Hashtable) obj; + toReturn.add(new File((String) table.get("path"))); + } + return toReturn; + } + } + + public class CustomCellRenderer implements ListCellRenderer + { + DefaultListCellRenderer listCellRenderer = new DefaultListCellRenderer(); + + public Component getListCellRendererComponent(JList list, Object value, int index, + boolean selected, boolean hasFocus) + { + listCellRenderer.getListCellRendererComponent(list, value, index, selected, hasFocus); + listCellRenderer.setText(getValueString(value)); + return listCellRenderer; + } + + private String getValueString(Object value) + { + String returnString = "null"; + if (value != null) { + if (value instanceof Hashtable) { + @SuppressWarnings("unchecked") + Hashtable h = (Hashtable) value; + String name = (String) h.get("name"); + String url = (String) h.get("url"); + returnString = name + " ==> " + url; + } else { + returnString = "X: " + value.toString(); + } + } + return returnString; + } + } + + public static void main(String s[]) + { + PropertyConfigurator.configure("log4j.properties"); + // starting with user's personal area. + String homedir = System.getenv("HOME"); + if ((homedir == null) || (homedir.length() == 0)) { + // fall back to the root if no home directory. + homedir = "/"; + } + JFrame frame = new dragdrop_list_test(homedir); + frame.addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + System.exit(0); + } + }); + frame.pack(); + frame.setVisible(true); + } +} diff --git a/kona/src/org/feistymeow/dragdrop/dragdrop_tree_test.java b/kona/src/org/feistymeow/dragdrop/dragdrop_tree_test.java new file mode 100644 index 00000000..5d425790 --- /dev/null +++ b/kona/src/org/feistymeow/dragdrop/dragdrop_tree_test.java @@ -0,0 +1,241 @@ +package org.feistymeow.dragdrop; + +import java.awt.*; +import java.io.*; +import java.util.*; +import java.util.List; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.DefaultTreeSelectionModel; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.PropertyConfigurator; + +/** + * A demo of the DragonDropHandler being used with a JTree. + * + * @author Chris Koeritz + * @copyright Copyright (c) 2012-$now By University of Virginia + * @license This file is free software; you can modify and redistribute it under the terms of the + * Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +@SuppressWarnings("serial") +public class dragdrop_tree_test extends JFrame implements TreeSelectionListener +{ + private DraggableDroppableTree larch; + private JTextField fileName; + static private Log logger = LogFactory.getLog(dragdrop_tree_test.DraggableDroppableTree.class); + + public dragdrop_tree_test(String startPath) + { + super("dragdrop_test"); + + // create the tree, configure it to show our hashtable nodes, and put it in + // a scroll pane. + larch = new DraggableDroppableTree(startPath); + DefaultTreeModel treeModel = (DefaultTreeModel) larch.getModel(); + larch.setCellRenderer(new CustomCellRenderer()); + TreeSelectionModel selmod = new DefaultTreeSelectionModel(); + selmod.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + larch.setSelectionModel(selmod); + larch.addTreeSelectionListener(this); + JScrollPane listScrollPane = new JScrollPane(larch); + // get the files that live in the specified directory. + String dirName = startPath + "/"; // make sure we think of it as a + // directory. + String filelist[] = new File(dirName).list(); + MutableTreeNode root_node = (MutableTreeNode) treeModel.getRoot(); + if (root_node == null) { + logger.error("something is not right about tree. has null root."); + System.exit(1); + } + // load up the tree with the files in the directory they passed. + for (int i = 0; i < filelist.length; i++) { + String thisFileSt = dirName + filelist[i]; + File thisFile = new File(thisFileSt); + // skip directories for now. + if (thisFile.isDirectory()) + continue; + // skip dot files. + if (filelist[i].startsWith(".")) + continue; + try { + // need to trap exceptions from the URI/URL functions. + DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(makeNode( + thisFile.getName(), thisFile.toURI().toURL().toString(), + thisFile.getAbsolutePath())); + treeModel.insertNodeInto(newNode, root_node, root_node.getChildCount()); + } catch (java.net.MalformedURLException e) { + logger.warn("caught an exception while trying to process path: " + + thisFile.getAbsolutePath()); + } + } + + // set our status bar to have the current path info. + fileName = new JTextField(50); + // select the root. + larch.setSelectionPath(larch.getPathForRow(0)); + + // pop out all the nodes. + larch.expandAll(); + + // Create a panel that uses FlowLayout (the default). + JPanel buttonPane = new JPanel(); + buttonPane.add(fileName); + + Container contentPane = getContentPane(); + contentPane.add(listScrollPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.NORTH); + } + + @SuppressWarnings("unchecked") + // given a mutable tree node, this will fetch out the embedded hash table. + Hashtable NodeToTable(Object node) + { + if (!(node instanceof DefaultMutableTreeNode)) + return null; + Object content = ((DefaultMutableTreeNode) node).getUserObject(); + if (content != null) { + if (content instanceof Hashtable) { + try { + return (Hashtable) content; + } catch (Throwable cause) { + logger.error("failed to cast our tree node to a hashtable."); + } + } + } + return null; + } + + public void valueChanged(TreeSelectionEvent e) + { + fileName.setText(""); + TreePath sel_path = larch.getSelectionPath(); + if (sel_path != null) { + Hashtable table = NodeToTable(sel_path.getLastPathComponent()); + if (table != null) { + String name = (String) table.get("name"); + fileName.setText(name); + } + } + } + + private static Hashtable makeNode(String name, String url, String strPath) + { + Hashtable hashtable = new Hashtable(); + hashtable.put("name", name); + hashtable.put("url", url); + hashtable.put("path", strPath); + return hashtable; + } + + public class DraggableDroppableTree extends JTree implements IDragonDropDataProvider + { + public DraggableDroppableTree(String startPath) + { + String url = ""; + try { + url = new File(startPath).toURI().toURL().toString(); + } catch (Throwable cause) { + logger.warn("failed to calculate URL for " + startPath); + } + setModel(new DefaultTreeModel(new DefaultMutableTreeNode( + makeNode("top", url, startPath)))); + setTransferHandler(new DragonTransferHandler(this)); + setDragEnabled(true); + } + + @Override + public boolean consumeDropList(List fileSet, Point location) + { + logger.debug("into consume dropped files, file set is:"); + for (int i = 0; i < fileSet.size(); i++) { + logger.debug(" " + ((File) fileSet.get(i)).getPath()); + } + return true; + } + + @Override + public List provideDragList() + { + ArrayList toReturn = new ArrayList(); + TreePath tsp = getSelectionPath(); + if (tsp == null) + return toReturn; + logger.debug("got the path..."); + Hashtable table = NodeToTable(tsp.getLastPathComponent()); + if (table != null) { + toReturn.add(new File(table.get("path"))); + } + return toReturn; + } + + public void expandAll() + { + int row = 0; + while (row < getRowCount()) { + expandRow(row); + row++; + } + } + + } + + public class CustomCellRenderer implements TreeCellRenderer + { + DefaultTreeCellRenderer defRend = new DefaultTreeCellRenderer(); + + private String getValueString(Object value) + { + String returnString = "empty"; + Hashtable table = NodeToTable(value); + if (table != null) { + returnString = table.get("name") + " -> " + table.get("url"); + } else { + returnString = "??: " + value.toString(); + } + return returnString; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, + boolean expanded, boolean leaf, int row, boolean hasFocus) + { + defRend.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, + hasFocus); + defRend.setText(getValueString(value)); + return defRend; + } + } + + public static void main(String s[]) + { + PropertyConfigurator.configure("log4j.properties"); + // starting with user's personal area. + String homedir = System.getenv("HOME"); + if ((homedir == null) || (homedir.length() == 0)) { + // fall back to the root if no home directory. + homedir = "/"; + } + JFrame frame = new dragdrop_tree_test(homedir); + frame.addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + System.exit(0); + } + }); + frame.pack(); + frame.setVisible(true); + } + +} diff --git a/kona/src/org/feistymeow/encryption/UnixCrypt.java b/kona/src/org/feistymeow/encryption/UnixCrypt.java new file mode 100644 index 00000000..3a94377a --- /dev/null +++ b/kona/src/org/feistymeow/encryption/UnixCrypt.java @@ -0,0 +1,604 @@ +package org.feistymeow.encryption; + +import java.util.ArrayList; + +/**************************************************************************** + * Java-based implementation of the unix UnixCrypt(3) command + * + * Based upon C source code written by Eric Young, eay@psych.uq.oz.au + * Java conversion by John F. Dumas, jdumas@zgs.com + * + * Found at http://locutus.kingwoodcable.com/jfd/UnixCrypt.html + * Minor optimizations by Wes Biggs, wes@cacas.org + * + * Eric's original code is licensed under the BSD license. As this is + * derivative, the same license applies. + * + * Note: UnixCrypt.class is much smaller when compiled with javac -O + ****************************************************************************/ + +public class UnixCrypt +{ + private UnixCrypt() {} // defined so class can't be instantiated. + + private static final int ITERATIONS = 16; + + private static final boolean shifts2[] = { + false, false, true, true, true, true, true, true, + false, true, true, true, true, true, true, false + }; + + private static final int skb[][] = { + { + /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000, 0x00000010, 0x20000000, 0x20000010, + 0x00010000, 0x00010010, 0x20010000, 0x20010010, + 0x00000800, 0x00000810, 0x20000800, 0x20000810, + 0x00010800, 0x00010810, 0x20010800, 0x20010810, + 0x00000020, 0x00000030, 0x20000020, 0x20000030, + 0x00010020, 0x00010030, 0x20010020, 0x20010030, + 0x00000820, 0x00000830, 0x20000820, 0x20000830, + 0x00010820, 0x00010830, 0x20010820, 0x20010830, + 0x00080000, 0x00080010, 0x20080000, 0x20080010, + 0x00090000, 0x00090010, 0x20090000, 0x20090010, + 0x00080800, 0x00080810, 0x20080800, 0x20080810, + 0x00090800, 0x00090810, 0x20090800, 0x20090810, + 0x00080020, 0x00080030, 0x20080020, 0x20080030, + 0x00090020, 0x00090030, 0x20090020, 0x20090030, + 0x00080820, 0x00080830, 0x20080820, 0x20080830, + 0x00090820, 0x00090830, 0x20090820, 0x20090830, + }, + { + /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000, 0x02000000, 0x00002000, 0x02002000, + 0x00200000, 0x02200000, 0x00202000, 0x02202000, + 0x00000004, 0x02000004, 0x00002004, 0x02002004, + 0x00200004, 0x02200004, 0x00202004, 0x02202004, + 0x00000400, 0x02000400, 0x00002400, 0x02002400, + 0x00200400, 0x02200400, 0x00202400, 0x02202400, + 0x00000404, 0x02000404, 0x00002404, 0x02002404, + 0x00200404, 0x02200404, 0x00202404, 0x02202404, + 0x10000000, 0x12000000, 0x10002000, 0x12002000, + 0x10200000, 0x12200000, 0x10202000, 0x12202000, + 0x10000004, 0x12000004, 0x10002004, 0x12002004, + 0x10200004, 0x12200004, 0x10202004, 0x12202004, + 0x10000400, 0x12000400, 0x10002400, 0x12002400, + 0x10200400, 0x12200400, 0x10202400, 0x12202400, + 0x10000404, 0x12000404, 0x10002404, 0x12002404, + 0x10200404, 0x12200404, 0x10202404, 0x12202404, + }, + { + /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000, 0x00000001, 0x00040000, 0x00040001, + 0x01000000, 0x01000001, 0x01040000, 0x01040001, + 0x00000002, 0x00000003, 0x00040002, 0x00040003, + 0x01000002, 0x01000003, 0x01040002, 0x01040003, + 0x00000200, 0x00000201, 0x00040200, 0x00040201, + 0x01000200, 0x01000201, 0x01040200, 0x01040201, + 0x00000202, 0x00000203, 0x00040202, 0x00040203, + 0x01000202, 0x01000203, 0x01040202, 0x01040203, + 0x08000000, 0x08000001, 0x08040000, 0x08040001, + 0x09000000, 0x09000001, 0x09040000, 0x09040001, + 0x08000002, 0x08000003, 0x08040002, 0x08040003, + 0x09000002, 0x09000003, 0x09040002, 0x09040003, + 0x08000200, 0x08000201, 0x08040200, 0x08040201, + 0x09000200, 0x09000201, 0x09040200, 0x09040201, + 0x08000202, 0x08000203, 0x08040202, 0x08040203, + 0x09000202, 0x09000203, 0x09040202, 0x09040203, + }, + { + /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000, 0x00100000, 0x00000100, 0x00100100, + 0x00000008, 0x00100008, 0x00000108, 0x00100108, + 0x00001000, 0x00101000, 0x00001100, 0x00101100, + 0x00001008, 0x00101008, 0x00001108, 0x00101108, + 0x04000000, 0x04100000, 0x04000100, 0x04100100, + 0x04000008, 0x04100008, 0x04000108, 0x04100108, + 0x04001000, 0x04101000, 0x04001100, 0x04101100, + 0x04001008, 0x04101008, 0x04001108, 0x04101108, + 0x00020000, 0x00120000, 0x00020100, 0x00120100, + 0x00020008, 0x00120008, 0x00020108, 0x00120108, + 0x00021000, 0x00121000, 0x00021100, 0x00121100, + 0x00021008, 0x00121008, 0x00021108, 0x00121108, + 0x04020000, 0x04120000, 0x04020100, 0x04120100, + 0x04020008, 0x04120008, 0x04020108, 0x04120108, + 0x04021000, 0x04121000, 0x04021100, 0x04121100, + 0x04021008, 0x04121008, 0x04021108, 0x04121108, + }, + { + /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000, 0x10000000, 0x00010000, 0x10010000, + 0x00000004, 0x10000004, 0x00010004, 0x10010004, + 0x20000000, 0x30000000, 0x20010000, 0x30010000, + 0x20000004, 0x30000004, 0x20010004, 0x30010004, + 0x00100000, 0x10100000, 0x00110000, 0x10110000, + 0x00100004, 0x10100004, 0x00110004, 0x10110004, + 0x20100000, 0x30100000, 0x20110000, 0x30110000, + 0x20100004, 0x30100004, 0x20110004, 0x30110004, + 0x00001000, 0x10001000, 0x00011000, 0x10011000, + 0x00001004, 0x10001004, 0x00011004, 0x10011004, + 0x20001000, 0x30001000, 0x20011000, 0x30011000, + 0x20001004, 0x30001004, 0x20011004, 0x30011004, + 0x00101000, 0x10101000, 0x00111000, 0x10111000, + 0x00101004, 0x10101004, 0x00111004, 0x10111004, + 0x20101000, 0x30101000, 0x20111000, 0x30111000, + 0x20101004, 0x30101004, 0x20111004, 0x30111004, + }, + { + /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000, 0x08000000, 0x00000008, 0x08000008, + 0x00000400, 0x08000400, 0x00000408, 0x08000408, + 0x00020000, 0x08020000, 0x00020008, 0x08020008, + 0x00020400, 0x08020400, 0x00020408, 0x08020408, + 0x00000001, 0x08000001, 0x00000009, 0x08000009, + 0x00000401, 0x08000401, 0x00000409, 0x08000409, + 0x00020001, 0x08020001, 0x00020009, 0x08020009, + 0x00020401, 0x08020401, 0x00020409, 0x08020409, + 0x02000000, 0x0A000000, 0x02000008, 0x0A000008, + 0x02000400, 0x0A000400, 0x02000408, 0x0A000408, + 0x02020000, 0x0A020000, 0x02020008, 0x0A020008, + 0x02020400, 0x0A020400, 0x02020408, 0x0A020408, + 0x02000001, 0x0A000001, 0x02000009, 0x0A000009, + 0x02000401, 0x0A000401, 0x02000409, 0x0A000409, + 0x02020001, 0x0A020001, 0x02020009, 0x0A020009, + 0x02020401, 0x0A020401, 0x02020409, 0x0A020409, + }, + { + /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000, 0x00000100, 0x00080000, 0x00080100, + 0x01000000, 0x01000100, 0x01080000, 0x01080100, + 0x00000010, 0x00000110, 0x00080010, 0x00080110, + 0x01000010, 0x01000110, 0x01080010, 0x01080110, + 0x00200000, 0x00200100, 0x00280000, 0x00280100, + 0x01200000, 0x01200100, 0x01280000, 0x01280100, + 0x00200010, 0x00200110, 0x00280010, 0x00280110, + 0x01200010, 0x01200110, 0x01280010, 0x01280110, + 0x00000200, 0x00000300, 0x00080200, 0x00080300, + 0x01000200, 0x01000300, 0x01080200, 0x01080300, + 0x00000210, 0x00000310, 0x00080210, 0x00080310, + 0x01000210, 0x01000310, 0x01080210, 0x01080310, + 0x00200200, 0x00200300, 0x00280200, 0x00280300, + 0x01200200, 0x01200300, 0x01280200, 0x01280300, + 0x00200210, 0x00200310, 0x00280210, 0x00280310, + 0x01200210, 0x01200310, 0x01280210, 0x01280310, + }, + { + /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000, 0x04000000, 0x00040000, 0x04040000, + 0x00000002, 0x04000002, 0x00040002, 0x04040002, + 0x00002000, 0x04002000, 0x00042000, 0x04042000, + 0x00002002, 0x04002002, 0x00042002, 0x04042002, + 0x00000020, 0x04000020, 0x00040020, 0x04040020, + 0x00000022, 0x04000022, 0x00040022, 0x04040022, + 0x00002020, 0x04002020, 0x00042020, 0x04042020, + 0x00002022, 0x04002022, 0x00042022, 0x04042022, + 0x00000800, 0x04000800, 0x00040800, 0x04040800, + 0x00000802, 0x04000802, 0x00040802, 0x04040802, + 0x00002800, 0x04002800, 0x00042800, 0x04042800, + 0x00002802, 0x04002802, 0x00042802, 0x04042802, + 0x00000820, 0x04000820, 0x00040820, 0x04040820, + 0x00000822, 0x04000822, 0x00040822, 0x04040822, + 0x00002820, 0x04002820, 0x00042820, 0x04042820, + 0x00002822, 0x04002822, 0x00042822, 0x04042822, + } + }; + + private static final int SPtrans[][] = { + { + /* nibble 0 */ + 0x00820200, 0x00020000, 0x80800000, 0x80820200, + 0x00800000, 0x80020200, 0x80020000, 0x80800000, + 0x80020200, 0x00820200, 0x00820000, 0x80000200, + 0x80800200, 0x00800000, 0x00000000, 0x80020000, + 0x00020000, 0x80000000, 0x00800200, 0x00020200, + 0x80820200, 0x00820000, 0x80000200, 0x00800200, + 0x80000000, 0x00000200, 0x00020200, 0x80820000, + 0x00000200, 0x80800200, 0x80820000, 0x00000000, + 0x00000000, 0x80820200, 0x00800200, 0x80020000, + 0x00820200, 0x00020000, 0x80000200, 0x00800200, + 0x80820000, 0x00000200, 0x00020200, 0x80800000, + 0x80020200, 0x80000000, 0x80800000, 0x00820000, + 0x80820200, 0x00020200, 0x00820000, 0x80800200, + 0x00800000, 0x80000200, 0x80020000, 0x00000000, + 0x00020000, 0x00800000, 0x80800200, 0x00820200, + 0x80000000, 0x80820000, 0x00000200, 0x80020200, + }, + { + /* nibble 1 */ + 0x10042004, 0x00000000, 0x00042000, 0x10040000, + 0x10000004, 0x00002004, 0x10002000, 0x00042000, + 0x00002000, 0x10040004, 0x00000004, 0x10002000, + 0x00040004, 0x10042000, 0x10040000, 0x00000004, + 0x00040000, 0x10002004, 0x10040004, 0x00002000, + 0x00042004, 0x10000000, 0x00000000, 0x00040004, + 0x10002004, 0x00042004, 0x10042000, 0x10000004, + 0x10000000, 0x00040000, 0x00002004, 0x10042004, + 0x00040004, 0x10042000, 0x10002000, 0x00042004, + 0x10042004, 0x00040004, 0x10000004, 0x00000000, + 0x10000000, 0x00002004, 0x00040000, 0x10040004, + 0x00002000, 0x10000000, 0x00042004, 0x10002004, + 0x10042000, 0x00002000, 0x00000000, 0x10000004, + 0x00000004, 0x10042004, 0x00042000, 0x10040000, + 0x10040004, 0x00040000, 0x00002004, 0x10002000, + 0x10002004, 0x00000004, 0x10040000, 0x00042000, + }, + { + /* nibble 2 */ + 0x41000000, 0x01010040, 0x00000040, 0x41000040, + 0x40010000, 0x01000000, 0x41000040, 0x00010040, + 0x01000040, 0x00010000, 0x01010000, 0x40000000, + 0x41010040, 0x40000040, 0x40000000, 0x41010000, + 0x00000000, 0x40010000, 0x01010040, 0x00000040, + 0x40000040, 0x41010040, 0x00010000, 0x41000000, + 0x41010000, 0x01000040, 0x40010040, 0x01010000, + 0x00010040, 0x00000000, 0x01000000, 0x40010040, + 0x01010040, 0x00000040, 0x40000000, 0x00010000, + 0x40000040, 0x40010000, 0x01010000, 0x41000040, + 0x00000000, 0x01010040, 0x00010040, 0x41010000, + 0x40010000, 0x01000000, 0x41010040, 0x40000000, + 0x40010040, 0x41000000, 0x01000000, 0x41010040, + 0x00010000, 0x01000040, 0x41000040, 0x00010040, + 0x01000040, 0x00000000, 0x41010000, 0x40000040, + 0x41000000, 0x40010040, 0x00000040, 0x01010000, + }, + { + /* nibble 3 */ + 0x00100402, 0x04000400, 0x00000002, 0x04100402, + 0x00000000, 0x04100000, 0x04000402, 0x00100002, + 0x04100400, 0x04000002, 0x04000000, 0x00000402, + 0x04000002, 0x00100402, 0x00100000, 0x04000000, + 0x04100002, 0x00100400, 0x00000400, 0x00000002, + 0x00100400, 0x04000402, 0x04100000, 0x00000400, + 0x00000402, 0x00000000, 0x00100002, 0x04100400, + 0x04000400, 0x04100002, 0x04100402, 0x00100000, + 0x04100002, 0x00000402, 0x00100000, 0x04000002, + 0x00100400, 0x04000400, 0x00000002, 0x04100000, + 0x04000402, 0x00000000, 0x00000400, 0x00100002, + 0x00000000, 0x04100002, 0x04100400, 0x00000400, + 0x04000000, 0x04100402, 0x00100402, 0x00100000, + 0x04100402, 0x00000002, 0x04000400, 0x00100402, + 0x00100002, 0x00100400, 0x04100000, 0x04000402, + 0x00000402, 0x04000000, 0x04000002, 0x04100400, + }, + { + /* nibble 4 */ + 0x02000000, 0x00004000, 0x00000100, 0x02004108, + 0x02004008, 0x02000100, 0x00004108, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x00004100, + 0x02000108, 0x02004008, 0x02004100, 0x00000000, + 0x00004100, 0x02000000, 0x00004008, 0x00000108, + 0x02000100, 0x00004108, 0x00000000, 0x02000008, + 0x00000008, 0x02000108, 0x02004108, 0x00004008, + 0x02004000, 0x00000100, 0x00000108, 0x02004100, + 0x02004100, 0x02000108, 0x00004008, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x02000100, + 0x02000000, 0x00004100, 0x02004108, 0x00000000, + 0x00004108, 0x02000000, 0x00000100, 0x00004008, + 0x02000108, 0x00000100, 0x00000000, 0x02004108, + 0x02004008, 0x02004100, 0x00000108, 0x00004000, + 0x00004100, 0x02004008, 0x02000100, 0x00000108, + 0x00000008, 0x00004108, 0x02004000, 0x02000008, + }, + { + /* nibble 5 */ + 0x20000010, 0x00080010, 0x00000000, 0x20080800, + 0x00080010, 0x00000800, 0x20000810, 0x00080000, + 0x00000810, 0x20080810, 0x00080800, 0x20000000, + 0x20000800, 0x20000010, 0x20080000, 0x00080810, + 0x00080000, 0x20000810, 0x20080010, 0x00000000, + 0x00000800, 0x00000010, 0x20080800, 0x20080010, + 0x20080810, 0x20080000, 0x20000000, 0x00000810, + 0x00000010, 0x00080800, 0x00080810, 0x20000800, + 0x00000810, 0x20000000, 0x20000800, 0x00080810, + 0x20080800, 0x00080010, 0x00000000, 0x20000800, + 0x20000000, 0x00000800, 0x20080010, 0x00080000, + 0x00080010, 0x20080810, 0x00080800, 0x00000010, + 0x20080810, 0x00080800, 0x00080000, 0x20000810, + 0x20000010, 0x20080000, 0x00080810, 0x00000000, + 0x00000800, 0x20000010, 0x20000810, 0x20080800, + 0x20080000, 0x00000810, 0x00000010, 0x20080010, + }, + { + /* nibble 6 */ + 0x00001000, 0x00000080, 0x00400080, 0x00400001, + 0x00401081, 0x00001001, 0x00001080, 0x00000000, + 0x00400000, 0x00400081, 0x00000081, 0x00401000, + 0x00000001, 0x00401080, 0x00401000, 0x00000081, + 0x00400081, 0x00001000, 0x00001001, 0x00401081, + 0x00000000, 0x00400080, 0x00400001, 0x00001080, + 0x00401001, 0x00001081, 0x00401080, 0x00000001, + 0x00001081, 0x00401001, 0x00000080, 0x00400000, + 0x00001081, 0x00401000, 0x00401001, 0x00000081, + 0x00001000, 0x00000080, 0x00400000, 0x00401001, + 0x00400081, 0x00001081, 0x00001080, 0x00000000, + 0x00000080, 0x00400001, 0x00000001, 0x00400080, + 0x00000000, 0x00400081, 0x00400080, 0x00001080, + 0x00000081, 0x00001000, 0x00401081, 0x00400000, + 0x00401080, 0x00000001, 0x00001001, 0x00401081, + 0x00400001, 0x00401080, 0x00401000, 0x00001001, + }, + { + /* nibble 7 */ + 0x08200020, 0x08208000, 0x00008020, 0x00000000, + 0x08008000, 0x00200020, 0x08200000, 0x08208020, + 0x00000020, 0x08000000, 0x00208000, 0x00008020, + 0x00208020, 0x08008020, 0x08000020, 0x08200000, + 0x00008000, 0x00208020, 0x00200020, 0x08008000, + 0x08208020, 0x08000020, 0x00000000, 0x00208000, + 0x08000000, 0x00200000, 0x08008020, 0x08200020, + 0x00200000, 0x00008000, 0x08208000, 0x00000020, + 0x00200000, 0x00008000, 0x08000020, 0x08208020, + 0x00008020, 0x08000000, 0x00000000, 0x00208000, + 0x08200020, 0x08008020, 0x08008000, 0x00200020, + 0x08208000, 0x00000020, 0x00200020, 0x08008000, + 0x08208020, 0x00200000, 0x08200000, 0x08000020, + 0x00208000, 0x00008020, 0x08008020, 0x08200000, + 0x00000020, 0x08208000, 0x00208020, 0x00000000, + 0x08000000, 0x08200020, 0x00008000, 0x00208020 + } + }; + + private static final int byteToUnsigned(byte b) { + int value = (int) b; + return (value >= 0) ? value : value + 256; + } + + private static int fourBytesToInt(byte b[], int offset) { + return byteToUnsigned(b[offset++]) + | (byteToUnsigned(b[offset++]) << 8) + | (byteToUnsigned(b[offset++]) << 16) + | (byteToUnsigned(b[offset]) << 24); + } + + private static final void intToFourBytes(int iValue, byte b[], int offset) { + b[offset++] = (byte)((iValue) & 0xff); + b[offset++] = (byte)((iValue >>> 8 ) & 0xff); + b[offset++] = (byte)((iValue >>> 16) & 0xff); + b[offset] = (byte)((iValue >>> 24) & 0xff); + } + + private static final void PERM_OP(int a, int b, int n, int m, int results[]) { + int t; + + t = ((a >>> n) ^ b) & m; + a ^= t << n; + b ^= t; + + results[0] = a; + results[1] = b; + } + + private static final int HPERM_OP(int a, int n, int m) { + int t; + + t = ((a << (16 - n)) ^ a) & m; + a = a ^ t ^ (t >>> (16 - n)); + + return a; + } + + private static int [] des_set_key(byte key[]) { + int schedule[] = new int [ITERATIONS * 2]; + + int c = fourBytesToInt(key, 0); + int d = fourBytesToInt(key, 4); + + int results[] = new int[2]; + + PERM_OP(d, c, 4, 0x0f0f0f0f, results); + d = results[0]; c = results[1]; + + c = HPERM_OP(c, -2, 0xcccc0000); + d = HPERM_OP(d, -2, 0xcccc0000); + + PERM_OP(d, c, 1, 0x55555555, results); + d = results[0]; c = results[1]; + + PERM_OP(c, d, 8, 0x00ff00ff, results); + c = results[0]; d = results[1]; + + PERM_OP(d, c, 1, 0x55555555, results); + d = results[0]; c = results[1]; + + d = (((d & 0x000000ff) << 16) | (d & 0x0000ff00) | + ((d & 0x00ff0000) >>> 16) | ((c & 0xf0000000) >>> 4)); + c &= 0x0fffffff; + + int s, t; + int j = 0; + + for(int i = 0; i < ITERATIONS; i ++) { + if(shifts2[i]) { + c = (c >>> 2) | (c << 26); + d = (d >>> 2) | (d << 26); + } else { + c = (c >>> 1) | (c << 27); + d = (d >>> 1) | (d << 27); + } + + c &= 0x0fffffff; + d &= 0x0fffffff; + + s = skb[0][ (c ) & 0x3f ]| + skb[1][((c >>> 6) & 0x03) | ((c >>> 7) & 0x3c)]| + skb[2][((c >>> 13) & 0x0f) | ((c >>> 14) & 0x30)]| + skb[3][((c >>> 20) & 0x01) | ((c >>> 21) & 0x06) | + ((c >>> 22) & 0x38)]; + + t = skb[4][ (d ) & 0x3f ]| + skb[5][((d >>> 7) & 0x03) | ((d >>> 8) & 0x3c)]| + skb[6][ (d >>>15) & 0x3f ]| + skb[7][((d >>>21) & 0x0f) | ((d >>> 22) & 0x30)]; + + schedule[j++] = ((t << 16) | (s & 0x0000ffff)) & 0xffffffff; + s = ((s >>> 16) | (t & 0xffff0000)); + + s = (s << 4) | (s >>> 28); + schedule[j++] = s & 0xffffffff; + } + return schedule; + } + + private static final int D_ENUnixCrypt(int L, int R, int S, int E0, int E1, int s[]) { + int t, u, v; + + v = R ^ (R >>> 16); + u = v & E0; + v = v & E1; + u = (u ^ (u << 16)) ^ R ^ s[S]; + t = (v ^ (v << 16)) ^ R ^ s[S + 1]; + t = (t >>> 4) | (t << 28); + + L ^= SPtrans[1][(t ) & 0x3f] | + SPtrans[3][(t >>> 8) & 0x3f] | + SPtrans[5][(t >>> 16) & 0x3f] | + SPtrans[7][(t >>> 24) & 0x3f] | + SPtrans[0][(u ) & 0x3f] | + SPtrans[2][(u >>> 8) & 0x3f] | + SPtrans[4][(u >>> 16) & 0x3f] | + SPtrans[6][(u >>> 24) & 0x3f]; + + return L; + } + + private static final int [] body(int schedule[], int Eswap0, int Eswap1) + { + int left = 0; + int right = 0; + int t = 0; + + for (int j = 0; j < 25; j ++) { + for (int i = 0; i < ITERATIONS * 2; i += 4) { + left = D_ENUnixCrypt(left, right, i, Eswap0, Eswap1, schedule); + right = D_ENUnixCrypt(right, left, i + 2, Eswap0, Eswap1, schedule); + } + t = left; + left = right; + right = t; + } + + t = right; + + right = (left >>> 1) | (left << 31); + left = (t >>> 1) | (t << 31); + + left &= 0xffffffff; + right &= 0xffffffff; + + int results[] = new int[2]; + + PERM_OP(right, left, 1, 0x55555555, results); + right = results[0]; left = results[1]; + + PERM_OP(left, right, 8, 0x00ff00ff, results); + left = results[0]; right = results[1]; + + PERM_OP(right, left, 2, 0x33333333, results); + right = results[0]; left = results[1]; + + PERM_OP(left, right, 16, 0x0000ffff, results); + left = results[0]; right = results[1]; + + PERM_OP(right, left, 4, 0x0f0f0f0f, results); + right = results[0]; left = results[1]; + + int out[] = new int[2]; + + out[0] = left; + out[1] = right; + + return out; + } + + public static final String alphabet = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + public static final String encrypt(String salt, String original) + { + // wwb -- Should do some sanity checks: salt needs to be 2 chars, in alpha. + while(salt.length() < 2) + salt += "A"; + + char[] buffer = new char [13]; + + char charZero = salt.charAt(0); + char charOne = salt.charAt(1); + + buffer[0] = charZero; + buffer[1] = charOne; + + int Eswap0 = alphabet.indexOf(charZero); + int Eswap1 = alphabet.indexOf(charOne) << 4; + byte key[] = new byte[8]; + + for(int i = 0; i < key.length; i ++) + key[i] = (byte)0; + + for(int i = 0; i < key.length && i < original.length(); i ++) + key[i] = (byte) (((int) original.charAt(i)) << 1); + + int schedule[] = des_set_key(key); + int out[] = body(schedule, Eswap0, Eswap1); + + byte b[] = new byte[9]; + + intToFourBytes(out[0], b, 0); + intToFourBytes(out[1], b, 4); + b[8] = 0; + + for(int i = 2, y = 0, u = 0x80; i < 13; i ++) { + for(int j = 0, c = 0; j < 6; j ++) { + c <<= 1; + + if(((int)b[y] & u) != 0) + c |= 1; + + u >>>= 1; + + if (u == 0) { + y++; + u = 0x80; + } + buffer[i] = alphabet.charAt(c); + } + } + return new String(buffer); + } + + public static void main(String [] args) + { + if ( (1 == args.length) && ("list".equalsIgnoreCase(args[0])) ) + { + StringBuffer listChars = new StringBuffer(alphabet); + final String password = "italianroast"; + int salt = 1; + ArrayList pws = new ArrayList(); + while( listChars.length() > 0 ) + { + int startLen = listChars.length(); + String pw = UnixCrypt.encrypt(Integer.toString(salt), password); + for( int i = 0; i < pw.length(); ++i ) + { + int pos = listChars.indexOf(pw.substring(i, i+1)); + if( pos >= 0 ) + listChars.deleteCharAt(pos); + } + if( listChars.length() == startLen ) + ++salt; + else + pws.add(new String [] { password, pw }); + } + for( String [] pw : pws ) + System.out.println(pw[0] + " : " + pw[1]); + } + else if ( 2 == args.length ) + { + System.out.println(UnixCrypt.encrypt(args[0], args[1])); + } + else + { + System.out.println("usage: UnixCrypt "); + System.out.println("or: \"UnixCrypt list\" to generate a list of password with all possible characters."); + } + } + +} diff --git a/kona/src/org/feistymeow/filesystem/PathHelper.java b/kona/src/org/feistymeow/filesystem/PathHelper.java new file mode 100644 index 00000000..eadd42c7 --- /dev/null +++ b/kona/src/org/feistymeow/filesystem/PathHelper.java @@ -0,0 +1,38 @@ +package org.feistymeow.filesystem; + +import java.net.URLDecoder; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/* + * Provides access to the relevant paths for a Java application. + * This class cannot provide static members due to runtime constraints. + * + * @author Chris Koeritz + */ +public class PathHelper { + private static Log c_logger = LogFactory.getLog(PathHelper.class); + + // locates the home directory where *this* application is installed. + // this can be used as a root path for finding configuration files + // needed by the application. + public String findHome() { + String path = "."; + try { + path = URLDecoder.decode(getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "x-www-form-urlencoded"); + // we remove the leading slash that is sometimes present, but only if the path looks. + // like a dos path. + if ( (path.length() >=3) && (path.charAt(0) == '/') && (path.charAt(2) == ':') ) + path = path.substring(1); + // we chop the last component off, because we want an actual path. + int lastSlash = path.lastIndexOf('/'); + path = path.substring(0, lastSlash); + } catch (Exception ex) { + c_logger.error("caught exception during path calculation: " + ex.toString()); + // unknown what we should say here, so we return the default. + } + return path; + } +}; + diff --git a/kona/src/org/feistymeow/networking/BasicWebServer.java b/kona/src/org/feistymeow/networking/BasicWebServer.java new file mode 100644 index 00000000..7e374298 --- /dev/null +++ b/kona/src/org/feistymeow/networking/BasicWebServer.java @@ -0,0 +1,251 @@ +package org.feistymeow.networking; + +import java.util.*; +import java.io.*; +import java.net.*; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.feistymeow.dragdrop.ListTransferable; + +/** + * Provides a lightweight way for RNS structures to be accessible over http. + * + * @Author Chris Koeritz + */ + +/* + * original example thanks to Matt Mahoney, at + * http://cs.fit.edu/~mmahoney/cse3103/java/Webserver.java + */ + +public class BasicWebServer { + static private Log logger = LogFactory.getLog(BasicWebServer.class); + + private int port; + private boolean leaving = false; // turns to true when should stop serving. + servingThread socketThread; + private ServerSocket realSocket; + + BasicWebServer(int portIn) { + port = portIn; + } + + public void shutDown() { + leaving = true; + if (realSocket != null) { + try { + realSocket.close(); + } catch (IOException e) { + } + } + if (socketThread != null) { + // stop it? + } + } + + public class servingThread implements Runnable { + private Thread thread; + private ServerSocket serverSocket; + + servingThread(ServerSocket socket) { + serverSocket = socket; + thread = new Thread(this); + thread.start(); + } + + @Override + public void run() { + while (!leaving) { + try { + logger.debug("about to accept on server socket."); + Socket s = serverSocket.accept(); // Wait for a client to + // connect + logger.debug("accepted client, spawning handler."); + new ClientHandler(s); // Handle the client in a separate + // thread + } catch (Throwable cause) { + logger.error( + "exception raised while handling accepted socket", + cause); + } + } + } + } + + // enums for outcomes? really need better reporting. + public int startServing() { + if (socketThread != null) + return 1; // already running outcome. + try { + realSocket = new ServerSocket(port); + } catch (Throwable cause) { + logger.error("failure to start server on port " + port, cause); + return 1; + // socket failure outcome. + } + socketThread = new servingThread(realSocket); + return 0; + } + + public String predictMimeType(String filename) { + + // kludge to try one type: + return "text/plain;charset=utf-8"; + + /* + * + * if (filename.endsWith(".html") || filename.endsWith(".htm")) return + * "text/html"; if (filename.endsWith(".jpg") || + * filename.endsWith(".jpeg")) return "image/jpeg"; if + * (filename.endsWith(".gif")) return "image/gif"; if + * (filename.endsWith(".class")) return "application/octet-stream"; + * return "text/plain"; + */ + } + + // A ClientHandler reads an HTTP request and responds + class ClientHandler extends Thread { + private Socket socket; // The accepted socket from the Webserver + + // Start the thread in the constructor + public ClientHandler(Socket s) { + socket = s; + start(); + } + + // Read the HTTP request, respond, and close the connection + public void run() { + try { + logger.debug("into client run(): listening for gets."); + + // Open connections to the socket + BufferedReader in = new BufferedReader(new InputStreamReader( + socket.getInputStream())); + PrintStream out = new PrintStream(new BufferedOutputStream( + socket.getOutputStream())); + + // Read filename from first input line "GET /filename.html ..." + // or if not in this format, treat as a file not found. + String s = in.readLine(); + logger.debug("request is: " + s); // Log the request + + // Attempt to serve the file. Catch FileNotFoundException and + // return an HTTP error "404 Not Found". Treat invalid requests + // the same way. + String filename = ""; + StringTokenizer st = new StringTokenizer(s); + try { + + boolean transferFile = true; + // get the command first. + String command = st.nextToken(); + // Parse the filename from the command. + if (st.hasMoreElements() && command.equalsIgnoreCase("GET") + && st.hasMoreElements()) { + filename = st.nextToken(); + } else if (st.hasMoreElements() + && command.equalsIgnoreCase("HEAD") + && st.hasMoreElements()) { + filename = st.nextToken(); + transferFile = false; // don't need to do that, just the + // header. + } else { + logger.error("going to blow file not found exception now."); + throw new FileNotFoundException(); // Bad request + } + logger.info("filename to handle is now: " + filename); + + // Append trailing "/" with "index.html" + // /hmmm: may want to make this assume directory. + if (filename.endsWith("/")) + logger.error("unhandled attempt to get item ending in slash"); + // if (filename.endsWith("/")) + // filename += "index.html"; + + // Remove leading / from filename + // / while (filename.indexOf("/") == 0) + // / filename = filename.substring(1); + + // Replace "/" with "\" in path for PC-based servers + filename = filename.replace('/', File.separator.charAt(0)); + + logger.info("asking for rns path of " + filename); + + // Check for illegal characters to prevent access to + // superdirectories + if (filename.indexOf("..") >= 0 + || filename.indexOf(':') >= 0 + || filename.indexOf('|') >= 0) + throw new FileNotFoundException(); + + logger.info("got past filename checks for: " + filename); + + /* + * this doesn't actually check that trailing slash is + * missing! // If a directory is requested and the trailing + * / is missing, // send the client an HTTP request to + * append it. (This is // necessary for relative links to + * work correctly in the client). if ((new + * GeniiPath(filename)).isDirectory()) { + * out.print("HTTP/1.0 301 Moved Permanently\r\n" + + * "Location: /" + filename + "/\r\n\r\n"); out.close(); + * return; } + */ + + // trying to get around worrying about mime types by saying + // "just get this there". + String mimeType = predictMimeType(filename); + // //"application/octet-stream"; + + File source = new File(filename); + if (!source.exists()) { + logger.error("source does not exist for serving: " + + filename); + // do something! + // hmmm: below could be abstracted to more general + // denial method. + out.println("HTTP/1.1 404 Not Found\r\n" + + "Content-type: text/html\r\n\r\n" + + "" + filename + + " not found\n"); + out.close(); + + } + out.print("HTTP/1.1 200 OK\r\n" + "Content-type: " + + mimeType + "\r\n" + "Connection: close" + "\r\n" + // // + "\r\nContent-Length: " + source.size? + + // "\r\n" + + "\r\n"); + if (!transferFile) { + logger.debug("closing stream for finished HEAD request."); + out.close(); + return; + } + logger.debug("moving to handle GET request."); + InputStream f = source.openInputStream(); + logger.debug("opened stream on source"); + // Send file contents to client, then close the connection. + byte[] a = new byte[4096]; + int n; + while ((n = f.read(a)) > 0) + out.write(a, 0, n); + logger.debug("wrote file back for request, closing stream."); + out.close(); + } catch (FileNotFoundException x) { + logger.error("failed to find requested file: " + filename); + out.println("HTTP/1.1 404 Not Found\r\n" + + "Content-type: text/html\r\n\r\n" + + "" + filename + + " not found\n"); + out.close(); + } + } catch (IOException x) { + logger.error("exception blew out in outer area of web server", + x); + // / System.out.println(x); + } + } + } +} diff --git a/kona/src/org/feistymeow/process/ThreadSpawnerAndWatcher.java b/kona/src/org/feistymeow/process/ThreadSpawnerAndWatcher.java new file mode 100644 index 00000000..5b70f20f --- /dev/null +++ b/kona/src/org/feistymeow/process/ThreadSpawnerAndWatcher.java @@ -0,0 +1,147 @@ +package org.feistymeow.process; + +////////////// +//Name : ThreadSpawnerAndWatcher +//Author : Chris Koeritz +//Rights : Copyright (c) 2012-$now By University of Virginia +////////////// +//This file is free software; you can modify/redistribute it under the terms +//of the Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 +//Feel free to send updates to: [ koeritz@virginia.edu ] +////////////// + + +// test app by Chris Koeritz. + +import java.io.IOException; +import java.lang.ProcessBuilder; +import java.lang.Process; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.PropertyConfigurator; + +class Defaults +{ + public static int CONCURRENT_LAUNCHES = 1000; +}; + +// will be spawned multiply and each one will check its one process. +class ThreadSpawnerAndWatcher implements Runnable +{ + private static Log c_logger = LogFactory.getLog(ThreadSpawnerAndWatcher.class); + + private volatile Thread myThread; + + private Vector cmdline; + + private ProcessBuilder procbuild; + + @SuppressWarnings("unchecked") + public ThreadSpawnerAndWatcher(Vector command_line) + { + cmdline = (Vector) command_line.clone(); + procbuild = new ProcessBuilder(cmdline); + } + + /** + * Launches the thread and waits for its results. + */ + public void start() + { + if (null == this.myThread) { + this.myThread = new Thread(this); + this.myThread.start(); + } + } + + /** + * Stops the execution of the ProcessWatchingThread - or tries to. + */ + public void stop() + { + Thread goAway = myThread; + myThread = null; + if (null != goAway) { + goAway.interrupt(); + } + } + + /** + * Returns true if the thread isn't null, i.e. it is still running. + */ + public boolean threadRunning() + { + return (null != this.myThread); + } + + public void run() + { + if (false == threadRunning()) { + return; // stopped before it ever started + } + + try { + // c_logger.info("about to start process: " + cmdline); + Process p = procbuild.start(); + p.waitFor(); + // c_logger.info("returned from awaiting process: " + cmdline); + } catch (IOException e) { + c_logger.debug("thread caught io exception on: " + cmdline); + } catch (InterruptedException ie) { + c_logger.debug("thread interrupted for: " + cmdline); + } finally { + this.myThread = null; // thread is exiting + } + } + + static public void main(String[] args) throws Throwable + { + PropertyConfigurator.configure("log4j.properties"); // hard-coded for + // eclipse based run. + + Vector cmds = new Vector(); + + cmds.add("/bin/echo"); + cmds.add("hello jupiter"); + + // cmds.add("/bin/sleep"); + // cmds.add("10"); + + Vector watchers = new Vector(); + + c_logger.info("revving up the process launching test."); + + // create all the threads and get them ready to go. + for (int i = 0; i < Defaults.CONCURRENT_LAUNCHES; i++) { + ThreadSpawnerAndWatcher newby = new ThreadSpawnerAndWatcher(cmds); + watchers.add(newby); + } + + // randomize start order? + // now start all the threads, which will cause all our process launches. + for (int i = 0; i < Defaults.CONCURRENT_LAUNCHES; i++) { + ThreadSpawnerAndWatcher curr = watchers.get(i); + curr.start(); + } + + // now wait for them all to finish. if we never get out, then there's a bug + // someplace. + for (int i = 0; i < Defaults.CONCURRENT_LAUNCHES; i++) { + ThreadSpawnerAndWatcher curr = watchers.get(i); + while (curr.threadRunning()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // ignore for now. + } + } + } + + // currently test will never come back out to finish, if there's a failure + // seen. + c_logger.info("Test Succeeded: all spawned processes came back as expected."); + System.exit(0); + } +} diff --git a/kona/src/org/feistymeow/system/RegistryEditor.java b/kona/src/org/feistymeow/system/RegistryEditor.java new file mode 100644 index 00000000..32bb7dc8 --- /dev/null +++ b/kona/src/org/feistymeow/system/RegistryEditor.java @@ -0,0 +1,175 @@ + +package org.feistymeow.system; + +import java.io.*; + +/* + * this class supports reading and setting values in the Windows registry. + * + * some example code came from http://www.rgagnon.com/javadetails/java-0480.html + * @author Chris Koeritz + */ +public class RegistryEditor { + + // the values below can be used for the expected type in the registry calls. + public static final String STRING_TYPE = "REG_SZ"; + public static final String DOUBLEWORD_TYPE = "REG_DWORD"; + + // looks up the key provided in the registry and returns true if the key seems to exist. + // this is just a check for presence; it could have no subkeys or values under it, but it at + // least seems to be there. + public static boolean checkKey(String keyName) { + try { + // make a command to run in windows that will query the value. + StringBuilder command = new StringBuilder(QUERY_COMMAND); + command.append("\""); + command.append(keyName); + command.append("\""); + // start the command running and trap its output. + Process process = Runtime.getRuntime().exec(command.toString()); + StreamReader reader = new StreamReader(process.getInputStream()); + reader.start(); + process.waitFor(); // let the system call finish up. + reader.join(); // let the stream reader finish also. + return process.exitValue() == 0; + } catch (Exception e) { + return false; + } + } + + // retrieves the key provided from the registry and selects out the value requested. + // it is necessary to know the expected type, such as REG_SZ or REG_DWORD. + // the value is always returned as a string and needs to be cast to different types as appropriate. + public static String getValue(String keyName, String valueName, String typeExpected) { + try { + // make a command to run in windows that will query the value. + StringBuilder command = new StringBuilder(QUERY_COMMAND); + command.append("\""); + command.append(keyName); + command.append("\""); + command.append(VALUE_FLAG); + command.append(valueName); + // start the command running and trap its output. + Process process = Runtime.getRuntime().exec(command.toString()); + StreamReader reader = new StreamReader(process.getInputStream()); + reader.start(); + process.waitFor(); // let the system call finish up. + reader.join(); // let the stream reader finish also. + // now grab the results from running the command and extract the answer. + String result = reader.getResult(); + int p = result.indexOf(typeExpected); + if (p == -1) return null; + // return the result with the stuff before the type chopped off. + return result.substring(p + typeExpected.length()).trim(); + } catch (Exception e) { + return null; + } + } + + // makes a change to the specified "keyName" value called "valueName". the old value will be replaced + // with the "newValue" provided. the key and the value do not have to exist prior to the call, but if + // they already did exist, they'll be updated. + public static boolean setValue(String keyName, String valueName, String typeExpected, String newValue) { + try { + // make a command to run in windows that will set the value. + StringBuilder command = new StringBuilder(SET_COMMAND); + command.append("\""); + command.append(keyName); + command.append("\""); + command.append(VALUE_FLAG); + command.append(valueName); + command.append(TYPE_FLAG); + command.append(typeExpected); + command.append(FORCE_FLAG); + command.append(DATA_FLAG); + command.append(newValue); + //System.out.println("command to run: " + command); + // start the command running and trap its output. + Process process = Runtime.getRuntime().exec(command.toString()); + StreamReader reader = new StreamReader(process.getInputStream()); + reader.start(); + process.waitFor(); // let the system call finish up. + reader.join(); // let the stream reader finish also. + return (process.exitValue() == 0); // zero exit is a success. + } catch (Exception e) { + return false; + } + } + + // removes the "valueName" value from the key "keyName". true is returned on success. + public static boolean deleteValue(String keyName, String valueName) { + try { + // make a command to run in windows that will set the value. + StringBuilder command = new StringBuilder(DELETE_COMMAND); + command.append("\""); + command.append(keyName); + command.append("\""); + command.append(VALUE_FLAG); + command.append(valueName); + command.append(FORCE_FLAG); + //System.out.println("command to run: " + command); + // start the command running and trap its output. + Process process = Runtime.getRuntime().exec(command.toString()); + StreamReader reader = new StreamReader(process.getInputStream()); + reader.start(); + process.waitFor(); // let the system call finish up. + reader.join(); // let the stream reader finish also. + return (process.exitValue() == 0); // zero exit is a success. + } catch (Exception e) { + return false; + } + } + + // removes the entire key "keyName" from the registry. true is returned on success. + public static boolean deleteKey(String keyName) { + try { + // make a command to run in windows that will set the value. + StringBuilder command = new StringBuilder(DELETE_COMMAND); + command.append("\""); + command.append(keyName); + command.append("\""); + command.append(FORCE_FLAG); + //System.out.println("command to run: " + command); + // start the command running and trap its output. + Process process = Runtime.getRuntime().exec(command.toString()); + StreamReader reader = new StreamReader(process.getInputStream()); + reader.start(); + process.waitFor(); // let the system call finish up. + reader.join(); // let the stream reader finish also. + return (process.exitValue() == 0); // zero exit is a success. + } catch (Exception e) { + return false; + } + } + + // constants used in the registry code for talking to windows' reg application. + private static final String QUERY_COMMAND = "reg query "; + private static final String VALUE_FLAG = " /v "; + + private static final String SET_COMMAND = "reg add "; + private static final String TYPE_FLAG = " /t "; + private static final String DATA_FLAG = " /d "; + private static final String FORCE_FLAG = " /f "; + + private static final String DELETE_COMMAND = "reg delete "; + + // wrapper class for stream reading came from web example mentioned above. + static class StreamReader extends Thread { + private InputStream is; + private StringWriter sw; + + StreamReader(InputStream is) { + this.is = is; + sw = new StringWriter(); + } + + public void run() { + int c; + try { + while ((c = is.read()) != -1) sw.write(c); + } catch (IOException e) { /*nothing*/ } + } + + String getResult() { return sw.toString(); } + } +} diff --git a/kona/src/org/feistymeow/system/RegistryEditorTestCase.java b/kona/src/org/feistymeow/system/RegistryEditorTestCase.java new file mode 100644 index 00000000..e26927b8 --- /dev/null +++ b/kona/src/org/feistymeow/system/RegistryEditorTestCase.java @@ -0,0 +1,93 @@ +package org.feistymeow.system; + +import static org.junit.Assert.*; +import org.junit.*; + +import org.feistymeow.system.RegistryEditor; + +/** + * RegistryEditor junit tests. + * + * @author Chris Koeritz + * + */ +public class RegistryEditorTestCase +{ + @Before + public void setUp() throws Exception + { + } + + @After + public void tearDown() throws Exception + { + } + + @Test + public void testCheckKey_missing() { + // this key cannot exist, since we're not allowed to write at that + // top level hive (as far as we know). + assertFalse(RegistryEditor.checkKey("HKLM\\flaubert\\maximus")); + } + + @Test + public void testCheckKey_present() { + // this key must always exist as far as we know. + assertTrue(RegistryEditor.checkKey("HKLM\\Software")); + } + + @Test + public void testCheckKey_bad() { + assertFalse(RegistryEditor.checkKey(null)); + } + + @Test + public void testGetValue_present() { + String PERSONAL_FOLDER_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; + String PERSONAL_FOLDER_VALUE = "Personal"; + assertNotNull(RegistryEditor.getValue(PERSONAL_FOLDER_KEY, PERSONAL_FOLDER_VALUE, + RegistryEditor.STRING_TYPE)); + } + + @Test + public void testGetValue_missing() { + String PERSONAL_FOLDER_KEY = "HKCU\\Flombix\\Gruntnork"; + String PERSONAL_FOLDER_VALUE = "Personalish"; + assertNull(RegistryEditor.getValue(PERSONAL_FOLDER_KEY, PERSONAL_FOLDER_VALUE, + RegistryEditor.STRING_TYPE)); + } + + @Test + public void testSetValueAndRemove_AllWork() + { + String EXAMPLE_KEY_ROOT = "HKCU\\Software\\SpunkMaster5000"; + String EXAMPLE_KEY = EXAMPLE_KEY_ROOT + "\\traumix"; + String EXAMPLE_VALUE = "glonkish"; + String EXAMPLE_CONTENTS1 = "ralphWiggum!"; + String EXAMPLE_CONTENTS2 = "moeSzyslak?"; + + // first try deleting the value. this should fail to start with. + assertFalse(RegistryEditor.deleteValue(EXAMPLE_KEY, EXAMPLE_VALUE)); + // remove the entire key if present. + assertFalse(RegistryEditor.deleteKey(EXAMPLE_KEY_ROOT)); + // now test that it really doesn't seem to be there. + assertFalse(RegistryEditor.checkKey(EXAMPLE_KEY)); +//System.out.println("now setting key [" + EXAMPLE_KEY + "] value [" + EXAMPLE_VALUE + "] to '" + EXAMPLE_CONTENTS1 + "'"); + // now try adding the example value. + assertTrue(RegistryEditor.setValue(EXAMPLE_KEY, EXAMPLE_VALUE, RegistryEditor.STRING_TYPE, EXAMPLE_CONTENTS1)); + // check that the contents are what we expect. + assertEquals(RegistryEditor.getValue(EXAMPLE_KEY, EXAMPLE_VALUE, RegistryEditor.STRING_TYPE), + EXAMPLE_CONTENTS1); + // now change the value's contents to a new setting. + assertTrue(RegistryEditor.setValue(EXAMPLE_KEY, EXAMPLE_VALUE, RegistryEditor.STRING_TYPE, EXAMPLE_CONTENTS2)); + // make sure the update has succeeded. + assertEquals(RegistryEditor.getValue(EXAMPLE_KEY, EXAMPLE_VALUE, RegistryEditor.STRING_TYPE), + EXAMPLE_CONTENTS2); + // now whack the value we had added. + assertTrue(RegistryEditor.deleteValue(EXAMPLE_KEY, EXAMPLE_VALUE)); + // now remove the entire key we added. + assertTrue(RegistryEditor.deleteKey(EXAMPLE_KEY_ROOT)); + } + +} + diff --git a/kona/src/org/feistymeow/utility/Extemporizer.java b/kona/src/org/feistymeow/utility/Extemporizer.java new file mode 100644 index 00000000..b271ab18 --- /dev/null +++ b/kona/src/org/feistymeow/utility/Extemporizer.java @@ -0,0 +1,51 @@ +package org.feistymeow.utility; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +////////////// +// Name : Extemporizer +// Author : Chris Koeritz +// Rights : Copyright (c) 2012-$now By University of Virginia +////////////// +// This file is free software; you can modify/redistribute it under the terms +// of the Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0 +// Feel free to send updates to: [ koeritz@virginia.edu ] +////////////// + +/** + * A set of useful utilities for dealing with temporary items. + */ +public class Extemporizer +{ + static private Log _logger = LogFactory.getLog(Extemporizer.class); + + /** + * creates a uniquely named temporary directory. thanks for guidance to article at: + * http://stackoverflow.com/questions/617414/create-a-temporary-directory-in-java + * + * @return a File object pointing at the new temporary directory. + * @throws IOException + */ + public static File createTempDirectory(String prefix, String suffix) + { + if ((prefix == null) || (suffix == null)) + return null; + try { + final File temp = File.createTempFile(prefix, suffix); + if (!temp.delete()) + throw new IOException("failed to delete temporary file: " + temp.getAbsolutePath()); + if (!temp.mkdir()) + throw new IOException("failed to create temporary directory: " + + temp.getAbsolutePath()); + temp.deleteOnExit(); // set for cleanup. + return temp; + } catch (Throwable cause) { + _logger.error("caught exception while creating temporary directory", cause); + return null; + } + } +} diff --git a/kona/src/org/feistymeow/utility/Naming.java b/kona/src/org/feistymeow/utility/Naming.java new file mode 100644 index 00000000..025b2c35 --- /dev/null +++ b/kona/src/org/feistymeow/utility/Naming.java @@ -0,0 +1,109 @@ +package org.feistymeow.utility; + +/* + * Some helper methods that retrieve the function and class names where code is executing. + * This can be helpful for doing very specific logging, and will work even if the log4j + * settings have turned off the function names and such (given that you really want to + * see those in a log entry). + * + * @author Chris Koeritz + */ +public class Naming { + + // returns the name of the function invoking this method. + public static String thisFunctionName() { + Throwable ex = new Throwable(); + StackTraceElement[] trace = ex.getStackTrace(); + // StackTrace trace = new StackTrace(0, true); + String meth = trace[0].getMethodName(); // this should be *this* + // function. + for (int i = 1; i < trace.length; i++) { + if ((trace[i].getMethodName() != meth) + && (!trace[i].getMethodName().contains("formatted_names"))) { + // we've gone back far enough. + return trace[i].getMethodName(); + } + } + return "unknown"; + } + + // provides a method to get the current class name and function name without + // needing to embed a lot of code into individual functions. + public static String thisClassName() { + Throwable ex = new Throwable(); + StackTraceElement[] trace = ex.getStackTrace(); + // StackTrace trace = new StackTrace(0, true); + + String meth = trace[0].getMethodName(); // this should be *this* + // function. + for (int i = 1; i < trace.length; i++) { + String currClass = trace[i].getClassName(); + if ((trace[i].getMethodName() != meth) + && (!trace[i].getMethodName().contains("formatted_names"))) { + // we've gone back far enough. + String simpleClassName = extractSimpleClassName(currClass); + return simpleClassName; + } + } + return "unknown"; + } + + public String thisPackageName() { + Throwable ex = new Throwable(); + StackTraceElement[] trace = ex.getStackTrace(); + // StackTrace trace = new StackTrace(0, true); + + String meth = trace[0].getMethodName(); // this should be *this* + // function. + for (int i = 1; i < trace.length; i++) { + String currClass = trace[i].getClassName(); + if ((trace[i].getMethodName() != meth) + && (!trace[i].getMethodName().contains("formatted_names"))) { + // we've gone back far enough. + String packageName = extractPackageName(currClass); + return packageName; + } + } + return "unknown"; + } + + public static String extractPackageName(String fullClassName) { + if ((null == fullClassName) || ("".equals(fullClassName))) + return ""; + + // The package name is everything preceding the last dot. + // Is there a dot in the name? + int lastDot = fullClassName.lastIndexOf('.'); + + // Note that by fiat, I declare that any class name that has been + // passed in which starts with a dot doesn't have a package name. + if (0 >= lastDot) + return ""; + + // Otherwise, extract the package name. + return fullClassName.substring(0, lastDot); + } + + public static String extractSimpleClassName(String fullClassName) { + if ((null == fullClassName) || ("".equals(fullClassName))) + return ""; + + // The simple class name is everything after the last dot. + // If there's no dot then the whole thing is the class name. + int lastDot = fullClassName.lastIndexOf('.'); + if (0 > lastDot) + return fullClassName; + + // Otherwise, extract the class name. + return fullClassName.substring(++lastDot); + } + + // returns a nicely formatted string containing the class and function name. + // the string also contains a colon and space on the end so other text + // can be concatenated right up against it while still being readable. + public static String formatted_names() { + String class_name = thisClassName(); + String function_name = thisFunctionName(); + return class_name + "." + function_name + ": "; + } +}; diff --git a/kona/src/org/feistymeow/windowing/ExitListener.java b/kona/src/org/feistymeow/windowing/ExitListener.java new file mode 100644 index 00000000..f53b0e29 --- /dev/null +++ b/kona/src/org/feistymeow/windowing/ExitListener.java @@ -0,0 +1,15 @@ +package org.feistymeow.windowing; + +import java.awt.*; +import java.awt.event.*; + +/** A listener that you attach to the top-level Frame or JFrame of + * your application, so quitting the frame exits the application. + * 1998-99 Marty Hall, http://www.apl.jhu.edu/~hall/java/ + */ + +public class ExitListener extends WindowAdapter { + public void windowClosing(WindowEvent event) { + System.exit(0); + } +} diff --git a/kona/src/org/feistymeow/windowing/WindowUtilities.java b/kona/src/org/feistymeow/windowing/WindowUtilities.java new file mode 100644 index 00000000..8174cef7 --- /dev/null +++ b/kona/src/org/feistymeow/windowing/WindowUtilities.java @@ -0,0 +1,79 @@ +package org.feistymeow.windowing; + +import javax.swing.*; +import java.awt.*; + +/** A few utilities that simplify using windows in Swing. + * 1998-99 Marty Hall, http://www.apl.jhu.edu/~hall/java/ + */ + +public class WindowUtilities { + + /** Tell system to use native look and feel, as in previous + * releases. Metal (Java) LAF is the default otherwise. + */ + + public static void setNativeLookAndFeel() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch(Exception e) { + System.out.println("Error setting native LAF: " + e); + } + } + + public static void setJavaLookAndFeel() { + try { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } catch(Exception e) { + System.out.println("Error setting Java LAF: " + e); + } + } + + public static void setMotifLookAndFeel() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch(Exception e) { + System.out.println("Error setting Motif LAF: " + e); + } + } + + /** A simplified way to see a JPanel or other Container. + * Pops up a JFrame with specified Container as the content pane. + */ + + public static JFrame openInJFrame(Container content, + int width, + int height, + String title, + Color bgColor) { + JFrame frame = new JFrame(title); + frame.setBackground(bgColor); + content.setBackground(bgColor); + frame.setSize(width, height); + frame.setContentPane(content); + frame.addWindowListener(new ExitListener()); + frame.setVisible(true); + return(frame); + } + + /** Uses Color.white as the background color. */ + + public static JFrame openInJFrame(Container content, + int width, + int height, + String title) { + return(openInJFrame(content, width, height, title, Color.white)); + } + + /** Uses Color.white as the background color, and the + * name of the Container's class as the JFrame title. + */ + + public static JFrame openInJFrame(Container content, + int width, + int height) { + return(openInJFrame(content, width, height, + content.getClass().getName(), + Color.white)); + } +} diff --git a/kona/src/test/java/semantics/instance_of.java b/kona/src/test/java/semantics/instance_of.java new file mode 100644 index 00000000..39008566 --- /dev/null +++ b/kona/src/test/java/semantics/instance_of.java @@ -0,0 +1,29 @@ + + +package test.java.semantics; + +import java.util.List; + +class instance_of +{ + public instance_of() {} + + public Object cogitate() { + return null; + } + + public static void main(String s[]) throws Exception + { + // we are just asserting that it is safe to do instanceof on an object that is null. + // let's test that theory. + instance_of tony = new instance_of(); + Object fred = tony.cogitate(); // will produce null. + if (fred instanceof List) { + throw new Exception("that should not have happened!"); + } else { + System.out.println("told us null is not an instance of List, which is correct."); + } + + } + +} \ No newline at end of file