SSH with Java

Recently I needed to do some server manipulation over the SSH-2 protocol from a Java client program. There are quite a few choices of SSH libraries for Java out there. Usually I prefer BSD license whenever possible, so I thought I’ll give Ganymed SSH-2 for Java a try. It turned out to be pretty simple to use. Here’s a short example of how to connect to the server using the private key and execute some command.

import java.io.*;
import ch.ethz.ssh2.*;

public class Example {
  public static void main(String[] args) throws IOException {
    Connection conn = new Connection("hostname");
    conn.connect();
    File pemKeyFile = new File("privKey.pem");
    boolean isAuth = conn.authenticateWithPublicKey("user", pemKeyFile, "keyPwd");
    if (isAuth == false) {
      throw new IOException("Authentication failed.");
    }

    Session sess = conn.openSession();
    sess.execCommand("netstat -nl | egrep ':80' | wc -l");
    InputStream inp = sess.getStdout();
    InputStreamReader reader = new InputStreamReader(inp);
    BufferedReader br = new BufferedReader(reader);
    String line = br.readLine();

    sess.close();
    conn.close();
  }
}

If you’re unfamiliar with private/public key authentication over SSH, see the links below or just google for “passwordless ssh login”.

One thing that most tutorials don’t mention is that your home directory should have permissions 755. I found out through trial and error, that using some user’s home directory with permissions 777 just doesn’t let you login with a private key.

Another thing that I needed to do was copy a file over to the server. Now this gave me some unexpected problems. While the API seemed simple enough, the code below just didn’t work.

  String data = "sample data";
  SFTPv3Client client = new SFTPv3Client(conn);
  SFTPv3FileHandle handle = client.createFile("test_file.txt");

  byte []arr = data.getBytes();
  client.write(handle, 0, arr, 0, arr.length);
  client.closeFile(handle);
  client.close();

Here, the conn object is the SSH connection which can be acquired as shown in the first code listing. This looks  pretty straightforward – create a file on the server, write some bytes to it, then close, but the outcome of it all – the file is created on the server, but it is  always 0 bytes in length.  It took me a while to figure out what’s wrong. Now is the time to mention that I was using the “latest version” of Ganymed that was available on their page – build210. And this screwed me good. After I got frustrated with the code not working the way I wanted it to, I started looking through the source of Ganymed and I found an unsatisfiable conditional statement in the write(…) method of the SFTPv3Client class. I fixed the problem, recompiled Ganymed library and voila it works. Then later I found out that Ganymed actually has a release build211, but they renamed the library to trilead. You can find it in this maven2 repository.

Firefox add-ons

Here I’ll just put my most used Firefox add-on list. Actually two lists – one for web development related add-ons and the other for general surfing and enjoying the web.

Developer’s add-ons

Surfing add-ons

There’s also this more official list of add-ons for Firefox categorized by the things you do on the web. So you might want to fashion your Firefox. And of course don’t forget to regularly visit Foxkeh’s Blog for the monthly wallpaper with the Japanese Firefox mascot – Foxkeh :)

Profiling Firefox

OK, this is a simple one, but I sometimes forget, because usually you do it once on any computer and then don’t think about it. Firefox is a great browser and what’s even more great is that it allows you to create different profiles so you can have different configurations/add-ons/layouts for general browsing, web development, extension development, etc.  The first step is to create a new profile which can be done by typing

firefox.exe -profilemanager

I’m assuming here the windows environment, but it is supposed to work on any OS where Firefox runs. A dialog will apear allowing you to manager your profiles and set a default one. Note that for this to work you first have to close all Firefox instances. After you created your profile i.e. myProfile you can use it with a command

firefox.exe -P myProfile

Of course it’s a good idea to create shortcuts for your new Firefox profiles. There’s another thing you need to know if you want to run two Firefox instances with different profiles at the same time. Then you need to modify the command line to

firefox.exe -P myProfile -no-remote

That’s about it, the basics of Firefox profiling.

iBatis and Stored Oracle procedures/functions

This one took me a while to get it right the first time. I won’t go into details of configuring iBatis datasources and such, and will go straight to putting some queries in the sqlMap file. Just let me note that I’m using iBatis 2.3 for these examples. I’ll start off with a procedure call.

<procedure id="getUserRoles" parameterMap="myParamMap">
    { call SCHEMA.GET_USERS_ROLES(?, ?) }
</procedure>

This one is pretty self-explanatory, just defining a procedure to be called. Notice the questionmarks in the SQL, don’t put the usual #variable# style annotation here. Also instead of parameterClass I use parameterMap here, which means I’ll have to define a parameter map for this query or it won’t work.

<parameterMap id="myParamMap" class="java.util.Map">
    <parameter property="username" mode="IN" />
    <parameter property="roles" jdbcType="ORACLECURSOR" mode="OUT" />
</parameterMap>

Here I explain to iBatis what kind of parameters I want to pass to the query and whether IN, OUT or INOUT mode should be used. It is important to specify correct jdbcType and javaType for the parameters otherwise when calling the procedure iBatis will spit out a very annoying Exception. Now for the JAVA part.

HashMap params = new HashMap();
params.put("username", username);
getSqlMapClient().queryForObject("getUserRoles", params);

Object o = params.get("roles");
if(o instanceof ResultSet)
{
    ResultSet res = (ResultSet) o;
    while(res.next())
        System.out.println(res.getInt("ROLE_NR"));
    res.close();
}

As you can see the procedure call is pretty much like any other SELECT query, but you don’t need to check the return value. All the OUT parameters will be stored in the Map object that you passed. In my case I defined a roles parameter as ORACLECURSOR which translates into ResultSet object. It’s not shown in this code snippet, but don’t forget to use startTransaction() and endTransaction() if you’re managing your own transactions. Also if the stored procedure is modifying the data you’ll most likely need commitTransaction() too, but iBatis transaction management is a different story.

And now for some stored function calling.

<procedure id="exampleFunction" parameterMap="funcMap">
    { ? = call SCHEMA.MY_FUNCTION(?, ?) }
</procedure>

The first thing you might notice is that it still says <procedure>, but it’s no a typo, iBatis doesn’t have a <function> tag (at least to my knowledge). Note how because it’s a function it has a questionmark at the beginning of the query to specify the return variable.

<parameterMap id="funcMap" class="java.util.Map">
  <parameter property="result" jdbcType="NUMERIC" mode="OUT"/>
  <parameter property="P1" />
  <parameter property="P2" javaType="java.util.Date" jdbcType="DATE" mode="OUT" />
</parameterMap>

Here I defined a parameter map which is pretty much like the one used for the procedure call except for the extra parameter result that is used to get the return value, but formally registered as an OUT parameter and not a return value.

HashMap params = new HashMap();
params.put("P1", param);
getSqlMapClient().queryForObject("exampleFunction", params);

Object o = params.get("result");
if(o instanceof Long)
{
    long res = (Long)o;
    System.out.println(res);
}

The actual call to the stored function is exactly the same as in the case of procedure. You just have to correctly configure the parameter mapping so that the return value will be available as an extra output parameter. In fact correctly configuring the parameter map was the place where I spent most of my time trying to figure out how to do it. In my case when using Oracle and retrieving an integer you can not jdbcType it INTEGER, NUMBER or whatever, it only worked when I put NUMERIC as a parameter JDBC type. That’s why I put so much stress on the parameter configuration. I wasted quite some time getting the annoying “java.sql.SQLException: Invalid column type” error. So, I guess that’s about it.

Certificate Generation with Java Tools

Java has a useful tool for generating private-public key pair, it’s called keytool and is located in your jdk/bin directory. Here’s a command line that I often use to generate keys and self-signed certificates for testing.

keytool -genkey -keyalg RSA -validity 365 -alias MyKey -keystore new_keystore.jks
-dname "CN=SubjectName, OU=My Department, O=My Company, L=Vilnius, S=Vilnius, C=LT"

Also it is sometimes needed to generate a request to get a signed certificate. Having created a keystore as shown above, it is easily done with the following line.

keytool -certreq -alias MyKey -keyalg RSA -keysize 2048 -file myfile.csr -keystore
new_keystore.jks

I realize that this is pretty trivial, but it’s nice to have it written down in case I forget something :)

Firefox 3 Download Day

Just found out about Firefox 3 Download Day and wanted to do my part by spreading the word. They’re trying to set a Guinness World Record for most software downloads in 24 hours. Sounds pretty simple, just download a great browser and help achieve the record.

Download Day 2008

You can also follow the Firefox news on twitter.

Using maven

Maven is an awesome build tool for JAVA, but it has some long parameter names that I don’t like to remember, so I put my often used tasks of maven in batch files.

install.bat

mvn install:install-file -Dfile=%1 -DgroupId=%2 -DartifactId=%3
-Dversion=%4 -Dpackaging=pom -DgeneratePom=true

This installs the specified .jar file in the local repository located in

C:\Documents and Settings\*User*\.m2\repository

where *User* is your username. Four arguments are required: jar_file, group, artifact and version.

new.bat

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes
-DgroupId=%1 -DartifactId=%2

I use this one to create new projects for stand-alone java programs. Two arguments required: group and artifact.

webnew.bat

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes
-DarchetypeArtifactId=maven-archetype-webapp -DgroupId=%1 -DartifactId=%2

This one creates a new project for a web application. Two arguments required: group and artifact.

More maven commands

  • mvn idea:idea – generate IDEA project files
  • mvn eclipse:eclipse – generate Eclipse project files
  • mvn clean package – clean target directory, rebuild and package
  • mvn jboss:deploy – deploy project to local jboss instance
  • mvn jboss:undeploy – undeploy project from local jboss instance

pom.xml

  <build>
    <finalName>myProject</finalName>
    <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
        <encoding>utf-8</encoding>
      </configuration>
    </plugin>
    </plugins>
  </build>

This is a snipet from pom.xml (maven configuration) file that I often add after creating a new project.

Ant tasks in pom.xml

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
    <dependencies>
      <dependency>
        <groupId>ant</groupId>
        <artifactId>ant-antlr</artifactId>
        <version>1.6.5</version>
      </dependency>
    </dependencies>
    <configuration>
      <!-- put Ant tasks here -->
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>run</goal>
        </goals>
      </execution>
    </executions>
</plugin>

This is very useful when you have some specific tasks that you were using in Ant and you don’t know the maven equivalent or if they’re custom made.

This is just a short compilation of things that I do with maven on a regular basis. There’s a lot more to this tool than shown here, and I’m still learning it myself. You can get more information on how to get started with maven here.

tail -f for windows

Here’s a simple implementation of “tail -f” UNIX command equivalent in python. I used it a lot on windows servers to monitor log files. The good thing is that it works over SMB (windows shares).

#!/usr/bin/env python
import sys, os, time

def main(argv):
	if len(argv)<2:
		print "Usage: tail filename.log"
		exit(1)
	try:
		fp = open(argv[1], "r")
		st_results = os.stat(argv[1])
		st_size = st_results[6]
		fp.seek(st_size)

		while 1:
			where = fp.tell()
			line = fp.readline()
			if not line:
				time.sleep(1)
				fp.seek(where)
			else:
				print line,
		fp.close()
	except:
		fp.close()

if __name__=="__main__":
	main(sys.argv)

This is useful when starting/stopping remote services with Windows Service Controller:

sc \\server1 stop "Macromedia JRun4 default Server"
sc \\server1 start "Macromedia JRun4 default Server"

A couple of useful resources

A while ago found this great page that aggregates various posts relevant to developers. Just to remind myself and maybe let others know, if you haven’t seen it definitely check it out – http://www.dzone.com

Recently I had the need to alter an SVG file that was produced by someone else. Now although you can do this by opening it in a text editor and make the changes by hand, but you would need to know the SVG tags, attributes, etc and more complex graphical changes are just too difficult. In my search for a tool I came across an open source vector graphics editor called Inkscape (http://www.inkscape.org). It supports files like SVG, EPS, EMF, PDF and some other formats. It was of great help for me, try it if you need to create/modify vector graphics.

Javascript introspection

Very basic, but sometimes useful javascript object introspection

<img id="test">
<script type="text/javascript" language="JavaScript">
    el = document.getElementById('test');
    str = '';
    for (i in el) str += i+'; ';
    alert(str);
</script>

Next Page »