Home → 2004 / « 06 »

Eclipse 3 is out

Does this mean I will have to shutdown the eclipse instance that was running without a glitch on my system for the last few months?

Eclipse's loading time is a little bit long but who cares if I only have to shut it down when I upgrade, or when Windows forces a reboot on me, eh?

Milestone builds of Eclipse were stable so I imagine the final release will be at least as good. 87 Megs though, that is a lot of code.

IMHO, amongst the many changes and improvements, the most noticeable feature in Eclipse 3 is RCP.

Home → 2004 / « 06 »

Atom API client example with WSSE authentication

Here is sample code in Java that shows how to access an AtomAPI enabled host to obtain a list of weblogs. This source code is dependance-free: no need to download any non-standard HTTP client library such as Apache's commons-httpclient.

As of today, it works perfectly on both Typepad (see their docs), and Blogger.


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Sample application that Lists the User's Weblogs from an Atom API enabled
 * host. The code that deals with WSSE was inspired by the Sandler
 * project.
 */
public class GetBlogs {

  public static void main(String[] args) {
    try {
      if (args.length < 3) {
        System.out
            .println("Usage: java GetBlogs <url> <username> <password>");
        System.out.println("<url> - the URL of the AtomAPI-enabled host");
        System.out.println("<username> - the username on the host");
        System.out.println("<password> - the username's password on the host");
        System.out.println();
        System.exit(1);
      }

      URL url = new URL(args[0]);
      String username = args[1];
      String password = args[2];

      URLConnection connection = url.openConnection();
      connection
          .addRequestProperty("X-WSSE", getWSSEHeader(username, password));

      InputStream in = null;
      try {
        in = connection.getInputStream();
      } catch(Exception e){
        e.printStackTrace();
        in = ((HttpURLConnection)connection).getErrorStream();
      }
      BufferedReader res = new BufferedReader(new InputStreamReader(in, "UTF-8"));
      String inputLine;
      while ((inputLine = res.readLine()) != null)
        System.out.println(inputLine);
      res.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

 private static String getWSSEHeader(String username, String password)
     throws Exception {

   byte[] nonceB = generateNonce();
   String nonce = base64Encode(nonceB);

   String created = generateTimestamp();

   String password64 = getBase64Digest(nonceB, created.getBytes("UTF-8"),
       password.getBytes("UTF-8"));
   StringBuffer header = new StringBuffer("UsernameToken Username=\"");
   header.append(username);
   header.append("\", ");
   header.append("PasswordDigest=\"");
   header.append(password64);
   header.append("\", ");
   header.append("Nonce=\"");
   header.append(nonce);
   header.append("\", ");
   header.append("Created=\"");
   header.append(created);
   header.append("\"");
   return header.toString();
 }

 private static byte[] generateNonce() {
     String nonce = Long.toString(new Date().getTime());
     return nonce.getBytes();
 }

 private static String generateTimestamp() {
   SimpleDateFormat dateFormatter = new SimpleDateFormat(
       "yyyy-MM-dd'T'HH:mm:ss'Z'");
   return dateFormatter.format(new Date());
 }

 private static synchronized String getBase64Digest(byte[] nonce,
     byte[] created, byte[] password) {
   try {
     MessageDigest messageDigester = MessageDigest.getInstance("SHA-1");
     // SHA-1 ( nonce + created + password )
     messageDigester.reset();
     messageDigester.update(nonce);
     messageDigester.update(created);
     messageDigester.update(password);
     return base64Encode(messageDigester.digest());
   } catch (java.security.NoSuchAlgorithmException e) {
     throw new RuntimeException(e);
   }
 }

 private static synchronized String getBase64Digest(byte[] password) {
   try {
     MessageDigest messageDigester = MessageDigest.getInstance("SHA-1");
     messageDigester.reset();
     messageDigester.update(password);
     return base64Encode(messageDigester.digest());
   } catch (java.security.NoSuchAlgorithmException e) {
     throw new RuntimeException(e);
   }
 }

 private static String base64Encode(byte[] bytes) {
   // Use Sun's encoder in this sample.
   return new sun.misc.BASE64Encoder().encode(bytes);
 }
}