snippets

Monday, September 14, 2009

maven-release-plugin with git

If you want to use Maven's release management with git have a look at this URL
Don Brown's Weblog

However there are a few maven dependency management quirks to iron out in partcular the
maven-scm-provider-gitexe needs later (1.2) version of the maven-scm-api but other parts of maven use the older version which results in the following error:-

java.lang.NoClassDefFoundError: org/apache/maven/scm/ScmTagParameters at org.apache.maven.scm.provider.git.gitexe.command.tag.GitTagCommand.
executeTagCommand(GitTagCommand.java:56) at 
org.apache.maven.scm.command.tag.AbstractTagCommand.
executeCommand(AbstractTagCommand.java:51) at 
org.apache.maven.scm.command.AbstractCommand.
execute(AbstractCommand.java:59)

the way to get around this is to force the release plugin to use the same version
that maven-scm-provider-gitexe uses


I got this working by editing the
<build><pluginmanagement></pluginmanagement></build>
section of my pom to use:

${scmVersion} = 1.2


<project>
....
<properties>
<scmversion>1.2</scmversion>
</properties>
...

<build>
...
<pluginmanagement>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-release-plugin</artifactid>
<version>2.0-beta-9</version>
<dependencies>
<dependency></dependency>
<groupid>org.apache.maven.scm</groupid>
<artifactid>maven-scm-api</artifactid>
<version>${scmVersion}</version>

<dependency>
<groupid>org.apache.maven.scm</groupid>
<artifactid>maven-scm-provider-gitexe</artifactid>
<version>${scmVersion}</version>
</dependency>
</dependencies>

<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-scm-plugin</artifactid>
<version>${scmVersion}</version>
<dependencies>
<dependency>
<groupid>org.apache.maven.scm</groupid>
<artifactid>maven-scm-provider-gitexe</artifactid>
<version>${scmVersion}</version>
</dependency>
</dependencies>
</plugin><
...
</pluginmanagement>
...
</build>
...
</project> 
 
Cheers. Karl

Wednesday, June 01, 2005

Java like Property object written in Python - properties.py

I've been learning the python scripting language recently and decided to knock up a small script to kick off a daemon on my linux box.
I quickly got the script working, but it had a lot of hard coded values in it. I decided that I should use a properties file to initialise all those hard coded values as variables.
I wanted an object that behaved like the Java Property object that could be initialised from a property file and then queried in my script.
After a few days searching for such a thing I admitted defeat and decided to write my own, I was learning the language anyway so this could only help.

Python has a Map/Dictionary type object called a dictionary that you can create using the built-in function "dict()" I decided to extend it to have methods similar to Java's Properties object.

The following module - properties.py can be imported into a script and the Property object used to read a property file that ignors blank lines, lines begining with a "#" and leading white space on property names and values.

Properties are defined as "key value" pairs with the key and value being seperated with a ":" or a "=" character. A valid property file could look like:


# /var/tmp/testPropFile.properties file
# This is a sample
# properties file. lines
# begining with '#' are comments white space is ignored

propertyName1=value1
propertyName2 = value2
propertyName3 : value3

# this is a comment
#so is this
propertyName4:value4


The Property object could be used in a script like this:

#!/usr/bin/python
#
# test the properties.py module
#
from properties import Property

props = Property()
props.loadProperties("/var/tmp/testPropFile.properties")

for n, v in props.iteritems():
print n, " : ", v

print "the value of property propertyName3 is", props.getProperty("propertyName3")

props.setproperty("newKey","newkeyValue")

props.store("/var/tmp/testpropertyFile2.properties", "This is a test comment");
print "the value of name2 is ", props.getProperty("name2")
print "the value of newKeyis ", props.getProperty("newKey")



So here is my properties.py


#!/usr/bin/python
# Author: Karl Roberts
#
# python implementation of a Java Property object
#
# This file is in the public domain
# please feel free to use and edit it
# If you improove it please post a comment showing me how and I'll probably add
# it to this demo. cheers
#
import sys, os, string, re

class Property(dict):

#dict of properties
nvseppattern = re.compile("=|:")
__commentre = re.compile("^\s*#|^\s*\n")

def __init__(self,properties=None):
"constructor. can be created by passing in another properties object if you want"
if properties is not None:
self.update(properties)

def getProperty(self, key):
"Searches for the property with the specified key in this property list."
return self[key]

def list(self,out):
"Prints this property list out to the specified output stream. This method is useful for debugging."
return self.items()

def loadProperties(self,propsFileName):
"Reads a property list (key and element pairs) from the properties file"
#read the properties file defined in init
f = file(propsFileName)
pList = f.readlines()
#populate the dict with key value pairs (readline split on = or :
# need to strip the keys and values & remove \n
#wanted to do this with a generator majic but not got version 4 of python yet
#so do it with a loop.
i=0
l=len(pList)
while i < l:
if re.match(self.__commentre,pList[i]):
del(pList[i])
l=len(pList)
continue
i=i+1

mydic=dict([(l[0].strip(),l[1].strip()) for l in ([re.split(self.__nvseppattern,s,1) for s in pList])])
self.update(mydic)
return self

def propertyNames(self):
"Returns an iterator of all the keys in this property list, including distinct keys in the default property list if a key of the same name has not already been found from the main properties list."
return self.iterkeys()

def setProperty(self, key, value):
"add a property to this object"
self.update({key: value})

def store(self, outputFileName, comment):
"Outputs the properties to a file in a manner that can be read with load(). comment is a comment added to the top of the file"
f = file(outputFileName, 'w+')
f.write("# "+comment+"\n");
for key, value in self.iteritems():
f.write(key+"="+value + "\n")
f.close()

#END of File



Cheers

Friday, March 11, 2005

Base64Helper.java


Having read this tip by Tom Daley which shows and explains a nice Base64 encoding algorithm I was intrigued by the fact that it didn't show the reverse or Base64 decodeing algorithm. So in the spirit of Open Source, if you have an itch, scratch it yourself I created one as shown below.

To proove that the algorithm works the java class comes with a main method so you can run it and see. It also compares the output of the decode method against the output generated by Sun Microsystems own undocumented Base64 decoder sun.misc.BASE64Decoder which is found in their SDK

to test it:

Usage: java Base64Helper


/**
* Author: karl roberts
* Date: 2-Mar-2005
* Time: 15:34:26
*
* Thanks to Tom Daley who posted the
* Base 64encode algorithm at
* http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.html
*/
import java.io.IOException;
import sun.misc.BASE64Decoder;

public class Base64 {

/*
* The methods of this class are static. Do not instantiate this class. Use
* its static methods to get the encoded/decoded results
*/

public final static String base64Encode(String strInput) {
if (strInput == null)
return null;
byte byteData[] = strInput.getBytes();
return new String(base64Encode(byteData));
}

public final static String base64Decode(String strInput) {
if (strInput == null)
return null;
byte[] byteData = strInput.getBytes();
return new String(base64Decode(byteData));
}

public final static byte[] base64Encode(byte[] byteData) {
/* If we received a null argument, exit this method. */
if (byteData == null)
return null;

/*
* Declare working variables including an array of bytes that will
* contain the encoded data to be returned to the caller. Note that the
* encoded array is about 1/3 larger than the input. This is because
* every group of 3 bytes is being encoded into 4 bytes.
*/
int iSrcIdx; // index into source (byteData)
int iDestIdx; // index into destination (byteDest)
// byte[] byteData = (byte[])byteData_in.clone();
// byte[] byteData = byteData_in;
byte[] byteDest = new byte[((byteData.length + 2) / 3) * 4];

/*
* Walk through the input array, 24 bits at a time, converting them from
* 3 groups of 8 to 4 groups of 6 with two unset bits between. as per
* Base64 spec see
* http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.html for
* example explanation
*/
for (iSrcIdx = 0, iDestIdx = 0; iSrcIdx < byteData.length - 2; iSrcIdx += 3) {
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx] >>> 2) & 077);
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 1] >>> 4) & 017 | (byteData[iSrcIdx] << 4) & 077);
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 2] >>> 6) & 003 | (byteData[iSrcIdx + 1] << 2) & 077);
byteDest[iDestIdx++] = (byte) (byteData[iSrcIdx + 2] & 077);
}

/*
* If the number of bytes we received in the input array was not an even
* multiple of 3, convert the remaining 1 or 2 bytes.
*/
if (iSrcIdx < byteData.length) {
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx] >>> 2) & 077);
if (iSrcIdx < byteData.length - 1) {
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 1] >>> 4) & 017 | (byteData[iSrcIdx] << 4) & 077);
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 1] << 2) & 077);
} else
byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx] << 4) & 077);
}

/*
* Use the encoded data as indexes into the Base64 alphabet. (The Base64
* alphabet is completely documented in RFC 1521.)
*/
for (iSrcIdx = 0; iSrcIdx < iDestIdx; iSrcIdx++) {
if (byteDest[iSrcIdx] < 26)
byteDest[iSrcIdx] = (byte) (byteDest[iSrcIdx] + 'A');
else if (byteDest[iSrcIdx] < 52)
byteDest[iSrcIdx] = (byte) (byteDest[iSrcIdx] + 'a' - 26);
else if (byteDest[iSrcIdx] < 62)
byteDest[iSrcIdx] = (byte) (byteDest[iSrcIdx] + '0' - 52);
else if (byteDest[iSrcIdx] < 63)
byteDest[iSrcIdx] = '+';
else
byteDest[iSrcIdx] = '/';
}

/* Pad any unused bytes in the destination string with '=' characters. */
for (; iSrcIdx < byteDest.length; iSrcIdx++)
byteDest[iSrcIdx] = '=';

return byteDest;
}

public final static byte[] base64Decode(byte[] byteData) {
/* If we received a null argument, exit this method. */
if (byteData == null)
return null;

/*
* Declare working variables including an array of bytes that will
* contain the decoded data to be returned to the caller. Note that the
* decoded array is about 3/4 smaller than the input. This is because
* every group of 4 bytes is being encoded into 3 bytes.
*/
int iSrcIdx; // index into source (byteData)
int reviSrcIdx; // index from end of the src array (byteData)
int iDestIdx; // index into destination (byteDest)
byte[] byteTemp = new byte[byteData.length];

/*
* remove any '=' chars from the end of the byteData they would have
* been padding to make it up to groups of 4 bytes note that I don't
* need to remove it just make sure that when progressing throug array
* we don't go past reviSrcIdx ;-)
*/
for (reviSrcIdx = byteData.length; byteData[reviSrcIdx - 1] == '='; reviSrcIdx--) {
; // do nothing. I'm just interested in value of reviSrcIdx
}

/* sanity check */
if (reviSrcIdx == 0)
return null; // ie all padding

/*
* Set byteDest, this is smaller than byteData due to 4 -> 3 byte munge.
* Note that this is an integer division! This fact is used in the logic
* l8r. to make sure we don't fall out of the array and create an
* OutOfBoundsException and also in handling the remainder
*/
byte byteDest[] = new byte[((reviSrcIdx * 3) / 4)];

/*
* Convert from Base64 alphabet to encoded data (The Base64 alphabet is
* completely documented in RFC 1521.) The order of the testing is
* important as I use the '<' operator which looks at the hex value of
* these ASCII chars. So convert from the smallest up
*
* do all of this in a new arry so as not to edit the origional input
*/
for (iSrcIdx = 0; iSrcIdx < reviSrcIdx; iSrcIdx++) {
if (byteData[iSrcIdx] == '+')
byteTemp[iSrcIdx] = 62;
else if (byteData[iSrcIdx] == '/')
byteTemp[iSrcIdx] = 63;
else if (byteData[iSrcIdx] < '0' + 10)
byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] + 52 - '0');
else if (byteData[iSrcIdx] < ('A' + 26))
byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] - 'A');
else if (byteData[iSrcIdx] < 'a' + 26)
byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] + 26 - 'a');
}

/*
* 4bytes -> 3bytes munge Walk through the input array, 32 bits at a
* time, converting them from 4 groups of 6 to 3 groups of 8 removing
* the two unset most significant bits of each sorce byte as this was
* filler, as per Base64 spec. stop before potential buffer overun on
* byteDest, remember that byteDest is 3/4 (integer division) the size
* of input and won't necessary divide exactly (ie iDestIdx must be <
* (integer div byteDest.length / 3)*3 see
* http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.html for
* example
*/
for (iSrcIdx = 0, iDestIdx = 0; iSrcIdx < reviSrcIdx
&& iDestIdx < ((byteDest.length / 3) * 3); iSrcIdx += 4) {
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03);
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 1] << 4) & 0xF0 | (byteTemp[iSrcIdx + 2] >>> 2) & 0x0F);
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 2] << 6) & 0xC0 | byteTemp[iSrcIdx + 3] & 0x3F);
}

/*
* tidy up any remainders if iDestIdx >= ((byteDest.length / 3)*3) but
* iSrcIdx < reviSrcIdx then we have at most 2 extra destination bytes
* to fill and posiblr 3 input bytes yet to process
*/
if (iSrcIdx < reviSrcIdx) {
if (iSrcIdx < reviSrcIdx - 2) {
// "3 input bytes left"
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03);
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 1] << 4) & 0xF0 | (byteTemp[iSrcIdx + 2] >>> 2) & 0x0F);
} else if (iSrcIdx < reviSrcIdx - 1) {
// "2 input bytes left"
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03);
}
/*
* wont have just one input byte left (unless input wasn't base64
* encoded ) due to the for loop steps and array sizes, after "="
* pad removed, but for compleatness
*/
else {
System.err
.println("Warning: 1 input bytes left to process. This was not Base64 input");
byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC);
}
}
return byteDest;
}

public static void main(String[] args) {
if (args.length == 1) {
int i;
for (i = 0; i < args.length; i++) {
System.out.println("args[" + i + "] = " + args[i]);
}

String password = args[0];
String encodedPassword = base64Encode(password);
System.out.println("String to encode = " + password + " = "
+ encodedPassword);
System.out.println("Proove bease64 decode: String to decode = "
+ encodedPassword + " = " + base64Decode(encodedPassword));

// test against Suns undocumented helpers
BASE64Decoder decoder = new BASE64Decoder();
String encodedString = new String(encodedPassword);
try {
System.out.println("The Sun class decodes " + encodedString
+ " to: "
+ new String(decoder.decodeBuffer(encodedString)));
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out
.println("Usage: java Base64Helper ");
System.exit(1);
}
System.exit(0);
}
} // that's all folks!