Skip to content
accelerando

Find all non “.java” files but not in .svn directories

19-Aug-10

I’m migrating some old projects to Maven and i need to move all resources out of the source tree.

find . -type d -name '\.svn' -prune -o -type f -not -iname "*.java" -print
  • Prune every directory named ‘.svn’
  • Or
  • Type is file and the name ends not with “*.java”

I tried to create the necessary directories within the same command but after about half an hour xargs trial and error, i’ll do it manually, the list of files is small enough ;)

Oracle NLS-Lang Settings

13-Aug-10

To use SQL*Plus Windows correctly, export NLS_LANG like so:

set NLS_LANG=GERMAN_GERMANY.WE8MSWIN1252

If you prefer the command line client SQL*Plus, export NLS_LANG like so:

set NLS_LANG=GERMAN_GERMANY.WE8PC850

J2SE: Cut/Copy/Paste Helper

09-Jul-10

You wouldn’t think that having a standard edit menü with Cut, Copy and Paste buttons would be much of a problem in the J2SE world, especially regarding the fact that most standard Swing components have TransferHandlers that support the 3 operations with the standard keyboard shortcuts.

First try was to user TransferHandler.getCopyAction() etc. and create menuitems from the actions. The actions will actually be called but they use the source of the action event to determine the component whose contents should be transfered.

After some searching i found this tutorial. The idea is to have a global property change handler on the global KeyboardFocusManager that tracks the current component that has the focus. The handler than updates the 3 actions with the new target.

I have changed the code a little bit. I removed the methods for adding special client parameters to determine whether cut/copy/paste should be enabled completely. Instead i check whether the component has a TransferHandler installed and if so, whether that handler supports the current action. By doing so my actions have the same behavior like the ones that are the swing components have.

The following code can be used to create menuitems or buttons that mimic the default cut/copy/paste actions on Swing components:

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
 
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.TransferHandler;
 
public final class CutCopyPasteHelper {
	private static final FocusedAction CUT_INSTANCE;
	private static final FocusedAction COPY_INSTANCE;
	private static final FocusedAction PASTE_INSTANCE;
 
	private static final Clipboard CLIPBOARD;
 
	private static final List<FocusedAction> FOCUSED_ACTIONS = new ArrayList<FocusedAction>();
 
	static {
		Clipboard clipboard;
		try {
			clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
		} catch (SecurityException e) {
			// Don't have access to the clipboard, create a new one
			clipboard = new Clipboard("Sandboxed Clipboard");
		}
		CLIPBOARD = clipboard;
 
		FOCUSED_ACTIONS.add(CUT_INSTANCE = new CutAction());
		FOCUSED_ACTIONS.add(COPY_INSTANCE = new CopyAction());
		FOCUSED_ACTIONS.add(PASTE_INSTANCE = new PasteAction());		
		KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(new PropertyChangeHandler());
	}
 
	private static Clipboard getClipboard() {
		return CLIPBOARD;
	}
 
	/**
	 * Returns an action to perform a cut operation.
	 *
	 * @return the cut action
	 */
	public static Action getCutAction() {
		return CUT_INSTANCE;
	}
 
	/**
	 * Returns an action to perform a copy operation.
	 *
	 * @return the copy action
	 */
	public static Action getCopyAction() {
		return COPY_INSTANCE;
	}
 
	/**
	 * Returns an action to perform a paste operation.
	 *
	 * @return the paste action
	 */
	public static Action getPasteAction() {
		return PASTE_INSTANCE;
	}
 
	private static void updateActions(Component focusedComponent) {
		for(FocusedAction action : FOCUSED_ACTIONS)						
			action.update(focusedComponent);					
	}
 
	private static final class PropertyChangeHandler implements PropertyChangeListener {
		public void propertyChange(PropertyChangeEvent e) {
			if (e.getPropertyName() == "permanentFocusOwner") {
				updateActions((Component)e.getNewValue());
			}
		}
	}
 
	private CutCopyPasteHelper() {
	}
 
 
	private static abstract class FocusedAction extends AbstractAction {        
		private static final long serialVersionUID = 9134168335741527777L;		
		protected JComponent focusedComponent;
 
		public FocusedAction(String name) {
			super(name);
		}		
 
		protected void update(Component permanentFocusOwner) {
			this.focusedComponent = (permanentFocusOwner instanceof JComponent) ? (JComponent)permanentFocusOwner : null; 			
			this.checkTarget();
		}
 
		public JComponent getFocusedComponent() {
			return focusedComponent;
		}		
 
		public boolean actionSupported(int actionMap, int action) {	
			return (actionMap & action) != 0;
		}
 
		abstract protected void checkTarget();	
	}
 
	protected static void export(final int exportAction, final JComponent component) {
		final Clipboard clipboard = getClipboard();		
		component.getTransferHandler().exportToClipboard(component, clipboard, exportAction);
	}
 
	private static final class CopyAction extends FocusedAction {		
		private static final long serialVersionUID = 1765740238724009255L;
 
		public CopyAction() {
			super("Kopieren");	
			super.setEnabled(false);
			super.putValue(ACTION_COMMAND_KEY, "a6f9f030-c408-4531-857f-dd3aad7b43f6");
			super.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK));
		}
 
		@Override
		public void actionPerformed(ActionEvent e) {			
			export(TransferHandler.COPY, focusedComponent);
		}
 
		@Override
		public void checkTarget() {
			super.setEnabled(focusedComponent != null && focusedComponent.getTransferHandler()!= null && actionSupported(focusedComponent.getTransferHandler().getSourceActions(focusedComponent), TransferHandler.COPY));
		}		
	}
 
	private static final class CutAction extends FocusedAction {		
		private static final long serialVersionUID = 1765740238724009255L;
 
		public CutAction() {
			super("Ausschneiden");	
			super.setEnabled(false);
			super.putValue(ACTION_COMMAND_KEY, "aa33f95a-c741-407a-a0ca-0c3aedd33c4d");
			super.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK));
		}
 
		@Override
		public void actionPerformed(ActionEvent e) {			
			export(TransferHandler.MOVE, focusedComponent);
		}
 
		@Override
		public void checkTarget() {
			super.setEnabled(focusedComponent != null && focusedComponent.getTransferHandler()!= null && actionSupported(focusedComponent.getTransferHandler().getSourceActions(focusedComponent), TransferHandler.MOVE));
		}		
	}
 
 
	private static final class PasteAction extends FocusedAction {		
		private static final long serialVersionUID = -2117467682323608417L;
 
		public PasteAction() {
			super("Einfügen");	
			super.setEnabled(false);
			super.putValue(ACTION_COMMAND_KEY, "2676413d-8b9e-4d64-b59a-800db6747d80");
			super.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK));
		}
 
		public void checkTarget() {			
			super.setEnabled(focusedComponent != null && focusedComponent.getTransferHandler() != null && focusedComponent.getTransferHandler().canImport(focusedComponent, getClipboard().getAvailableDataFlavors()));			
		}
 
		public void actionPerformed(ActionEvent e) {
			Clipboard clipboard = getClipboard();
			JComponent target = getFocusedComponent();
			target.getTransferHandler().importData(target, clipboard.getContents(null));
		}		
	}
}

What’s missing: The actions aren’t localized and they use Ctrl+? on every system. One could use the default Swing bundles to determine the correct modifier.

Extended Live Archives and WordPress 3.0

21-Jun-10

The Extended Live Archives Plugin does not work with WordPress 3.0, opposed to the plugin page. I still like this plugin as seen here, so here is my solution:

  • Download the archive
  • Open includes/af-extended-live-archive.js.php and includes/af-ela.php in your favorite editor
  • Replace in both files
    require('../../../../wp-blog-header.php');

    with

    require_once('../../../../wp-config.php'); 		
    $wp_did_header = true;
    $wp->init();

    and you’re good to go.

If anyone has a better idea, please write a comment.

Using SQL*Plus without tnsnames.ora

29-Mar-10

As often, a quick reminder for me. I’m using the Oracle Instaclient on my Mac without a tnsnames.ora and i keep forgetting the connectstring syntax:

sqlplus USER/PASS@//HOST:PORT/SID

Extra bonus points: Through in rlwrap to get a nice commandline history and completion as used to in a standard shell:

rlwrap sqlplus USER/PASS@//HOST:PORT/SID

Linux: Persistent wake-on-lan

03-Mar-10

Just a quick reminder for myself: You need to enable wake-on-lan on the nic in most linux distributions via ethtool.

If your nic supports WOL, it probably needs to be enabled in your computers BIOS first.

Most WOL tools use the “MagicPacket(tm)” method, so the right command to enable it on the nic “eth0″ would be

ethtool -s eth0 wol g

This is not a persistent setting and it is gone after a reboot. Most tips around recommend creating a runlevel script for executing this command after boot or before shutdown.

I’ve added the command as a hook in my network scripts:

auto eth0
iface eth0 inet dhcp
        pre-down ethtool -s eth0 wol g

You can also use post-up. I like this method because i tend to forget about my runlevel scripts and so i keep the network stuff in one place ;)

If you are a debian user, you maybe need to stop your system from turning off the nic on HALT. To do so, add

NETDOWN=no

to “/etc/default/halt”.

Oracle: Drop table if exists replacement

16-Feb-10

Mysql has a nice “if exists” addition to the drop table statement. If the table to be dropped does not exists, it doesn’t raise an exception but only creates a warning.

In Oracle RDMBS you can emulate this behavior like so:

BEGIN execute immediate 'drop table INSERT_TABLE_NAME_HERE'; EXCEPTION WHEN others THEN IF SQLCODE != -942 THEN RAISE; END IF; END;
/

Ugly, but it works very well.

An iterable array

12-Jan-10

Java has the nice Iterable interface (since Java 5, i guess) that allows object oriented loops like

List<String> strings = new ArrayList<String>();
for(String string : strings) 
	System.out.println(string);

but guess what, a simple array is not iterable…

In case you need one, feel free to use this one:

package ac.simons;
 
import java.util.Iterator;
 
public class IterableArray<T> implements Iterable<T> {
	private class ArrayIteratorImpl implements Iterator<T> {
		private int position = 0;
		@Override
		public boolean hasNext() {
			return data != null && this.position < data.length;
		}
 
		@Override
		public T next() {
			return data[position++];
		}
 
		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}		
	}
 
	private final T[] data;
 
	public IterableArray(T[] data) {
		this.data = data;
	}
 
	@Override
	public Iterator<T> iterator() {
		return new ArrayIteratorImpl();
	}	
}

Create ZIP Archives containing Unicode filenames with Java

05-Jan-10

It is harder than i thought to create a simple Zip Archive from within Java that contains entries with unicode names in it.

I’m actually to lazy to read all the specs, but it says something that the entries in a zip archive are encoded using “Cp437″. The buildin Java compressing api has nothing to offer for setting the encoding so i tried Apache Commons Compress.

The manual says the following about interop :

For maximum interop it is probably best to set the encoding to UTF-8, enable the language encoding flag and create Unicode extra fields when writing ZIPs. Such archives should be extracted correctly by java.util.zip, 7Zip, WinZIP, PKWARE tools and most likely InfoZIP tools. They will be unusable with Windows’ “compressed folders” feature and bigger than archives without the Unicode extra fields, though.

That didn’t work for me.

After some cursing, this is my solution:

final ZipArchiveOutputStream zout = new ZipArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(fc.getSelectedFile())));
zout.setEncoding("Cp437");
zout.setFallbackToUTF8(true);
zout.setUseLanguageEncodingFlag(true);								
zout.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NOT_ENCODEABLE);

I specifying explicitly the encoding but instead of using utf-8, which didn’t work for my utf-8 strings (wtf??), i’m using the Cp437 from the specs and some other magic options and it works for me in 7zip, WinZip and even Windows’ “compressed folders”.

Edit: Unfortunately, in Mac OS X’s Unzip utility, the non Cp437 are broken. If anyone has a good idea, feel free to leave a comment.

Today: Fun with Unicode, Regex and Java.

03-Nov-09

Some would say, i have 3 problems ;)

private final static Pattern placeholder = Pattern.compile("#\\{(\\w+?)\\}");

won’t match “Mot#{ö}rhead” for example.

To replace the word character \w you either need the list of possible unicodeblocks like [\p{InLatin}|\p{InEtc}] (you get the codes for the blocks through “Character.UnicodeBlock.forName” or you’re lazy like me and just use the dot:

private final static Pattern placeholder = Pattern.compile("#\\{(.+?)\\}");

Oh what a day… :/

Close
E-mail It