Encrypting/decrypting with the IDEA algorithm

IDEA stands for International Data Encryption Algorithm. It is a patented, commercial algorithm that is fairly new (1990). It is faster than DES and considered more secure. It is used in PGP and SSL.

The IDEA key size is 128 bit and block size 64 bit.

Main.java:

import javax.crypto.spec.*;
import java.security.*;
import javax.crypto.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      String toEncrypt = "The shorter you live, the longer you're dead!";
 
      System.out.println("Encrypting...");
      byte[] encrypted = encrypt(toEncrypt, "password");
 
      System.out.println("Decrypting...");
      String decrypted = decrypt(encrypted, "password");
    
      System.out.println("Decrypted text: " + decrypted);
   } 
 
   public static byte[] encrypt(String toEncrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("IDEA");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // create an instance of cipher
      Cipher cipher = Cipher.getInstance("IDEA");
 
      // initialize the cipher with the key 
      cipher.init(Cipher.ENCRYPT_MODE, sk);
 
      // enctypt!
      byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
 
      return encrypted;
   }
 
   public static String decrypt(byte[] toDecrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("IDEA");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // do the decryption with that key
      Cipher cipher = Cipher.getInstance("IDEA");
      cipher.init(Cipher.DECRYPT_MODE, sk);
      byte[] decrypted = cipher.doFinal(toDecrypt);
 
      return new String(decrypted);
   }
}

(tested with the BouncyCastle JCE provider, http://www.bouncycastle.org)

Get started with JAAS

JAAS stands for Java Authentication and Authorization Service. It allows you to grant permission based on who is executing the code. Previous security models already granted permission based on where the code was coming from and who signed it. JAAS has been added to JDK1.4 and the examples here will use that JDK. If you want to run them with JDK version 1.3, download the optional JAAS package here and put jaas.jar in jdk1.3/jre/lib/ext.

JAAS consists of two components: the authentication component and the authorization component. The Authentication component determines who is attempting to run code. The authorization component determines if that entity has the necessary permissions to run that code.

To find out how to authenticate with JAAS, check out JAAS Authentication.
To find out how to allow or deny access to resources, check out JAAS Declarative Authorization and JAAS Programmatic Authorization.

Using a HashMap

A Map allows you to store elements, where each element is a key/value pair. Unlike an simple array where you store a value at a particular index, a Map determines the index itself and does this based on the hash value on the key. Eg. if you store a key key=”sinciput”, value=”the font part of the head or skull” in a Hashmap, the method hashcode (every Object inherits this method from the class Object) is invoked on “sinciput” which returns an integer that specifies where the key/value pair should go (internally, a HashMap uses an array):

   When writing: 
      HashMap hm = new HashMap();
      hm.put("sinciput", "the front part of the head or skull"); 
 
   hm internals:
      +----+
      |....|
      | 86 |    +------------------------------------------------------------+
      | 87 |--> | key="sinciput", value="the font part of the head or skull" |
      | 88 |    +------------------------------------------------------------+
      |....|
      +----+

If you store a key that already exists in the HashMap, it old key/value pair will be overwritten
Eg.

   When writing: 
      HashMap hm = new HashMap();
      hm.put("sinciput", "the front part of the head or skull"); 
      hm.put("sinciput", "dunno what it means");
 
   hm internals:
      +----+
      |....|
      | 86 |    +---------------------------------------------+
      | 87 |--> | key="sinciput", value="dunno what it means" |
      | 88 |    +---------------------------------------------+
      |....|
      +----+

If you store a key/value pair in which the hashcode of the keys maps to an index of the internal array that is already taken, the elements at that index acts as a linked list.
Eg.

   When writing:
      HashMap hm = new HashMap();
      hm.put("sinciput", "the front part");
      hm.put("whenever", "at any time");
 
   hm internals:
      +----+
      |....|
      | 86 |    +----------------------------------------+    +---------------------------+
      | 87 |--> | key="sinciput", value="the front part" |--> | "whenever", "at any time" |
      | 88 |    +----------------------------------------+    +---------------------------+
      |....|
      +----+

You can see that a HashMap (and HashTable) has the strong feature of doing lookups very quickly. Suppose you have built a HashMap of all dictionary words and you would like to know the meaning of “whenever”. You ask the HashMap if it contains that key and if so to return the value:

   if (hm.containsKey("whenever")) {
      Object value = hm.get("whenever");
   }

The method containsKey quickly determines that the index for “whenever” is 87 and then it just needs to sequentially look at each key in the linked list that appears on index 87. The get method does the same, but returns the value. Notice that get returns null when the key does not exist in the HashMap, but also returns null if the value of that key happens to be null. This is why you should use containsKey first if you know your HashMap is going to contain null values.

Internally a HashMap maintains an array. To have the HashMap work efficiently, the array must be large enough so that the key/value pairs are well-distributed and the performance is not affected. Therefore, the HashMap maintains two (customizable) variables capacity and loadFactor. The capacity is the length of the internal array and the loadFactor controls when the capacity should be increased.

Here’s an example:

import java.util.*;
import java.io.*;
    
public class Main 
{
   public static void main(String []args) throws Exception {
      String[] colors = { "black", "white", "blue", "green", 
                          "red", "yellow", "magenta", "cyan", 
                          "orange", "redorange",
                         "violet", "purple", "greenblue" };
      String[] rgbs = { "[0,0,0]", "[255,255,255]", "[0,0,255]", "[0,255,0]", 
                        "[255,0,0]", "[255,255,0]", "[255,0,255]", "[0,255,255]",
                        "[255,165,0]", "[255,69,0]", "[255,69,0]",
                        "[238,130,238]", "[160,32,240]", "[46,139,87]" };
 
      HashMap hm = new HashMap();
 
      for (int i=0; i<colors.length; i++) {
         hm.put(colors[i], rgbs[i]);
      }
 
 
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      
      String line;
      System.out.print("Enter color ('exit' to exit): ");
      line = br.readLine();
      while (!line.equals("exit")) {
         if (hm.containsKey(line)) {
            System.out.println("t" + line + " is found with value " + hm.get(line));
         }
         else {
            System.out.println("t" + line + " is not found");
         }
         System.out.print("Enter color ('exit' to exit): ");
         line = br.readLine();
      }
   }
}

sample output:

C:>java Main
Enter color ('exit' to exit): red
        red is found with value [255,0,0]
Enter color ('exit' to exit): yellow
        yellow is found with value [255,255,0]
Enter color ('exit' to exit): green
        green is found with value [0,255,0]
Enter color ('exit' to exit): blue
        blue is found with value [0,0,255]
Enter color ('exit' to exit): violet
        violet is found with value [255,69,0]
Enter color ('exit' to exit): jefke
        jefke is not found
Enter color ('exit' to exit): exit

Creating a date using GregorianCalender

Main.java:

import java.util.*;
 
public class Main
{
   public static void main(String []args) {
      Calendar calendar = new GregorianCalendar(2003, Calendar.JANUARY, 20);
 
      Date currentDate = calendar.getTime();
 
      System.out.println(currentDate);
   }
} 

Using the JDK1.4 logging package

Let’s start with a simple self-explanatory example.

Main.java:

import java.util.logging.*;
import java.io.*;
 
public class Main
{
   public static void main(String argv[]){
      Logger logger = Logger.getLogger("test");
 
      logger.setLevel(Level.ALL);
 
      logger.severe("Log message #1");
      logger.warning("Log message #2");
      logger.info("Log message #3");
      logger.config("Log message #4");
      logger.fine("Log message #5");
      logger.finer("Log message #6");
      logger.finest("Log message #7");
   }
}

outputs:

Jan 20, 2002 12:55:02 AM Main main
SEVERE: Log message #1
Jan 20, 2002 12:55:02 AM Main main
WARNING: Log message #2
Jan 20, 2002 12:55:02 AM Main main
INFO: Log message #3

A Level object determines the importance of a log record. The order of levels are important as they control what is being logged. Here’s the predefined hierarchy:

   SEVERE (highest value) 
   WARNING 
   INFO 
   CONFIG 
   FINE 
   FINER 
   FINEST (lowest value) 
 
   ALL    - log all messages
   OFF    - turn off logging

For example, setting the logging level to CONFIG will log messages that are categorized as SEVERE, WARNING, INFO and CONFIG.

So, why then is the above program only logging the first three log messages. After all, we asked the logger object to log all messages with Logger.setLevel(Level.ALL).

To understand why this is not working, you’ll have to know a bit about the whole logging architecture.

Handlers:

A logger is associated with a set of log Handlers. A Handler is a gateway to a particular logging destination resource. For example, there exist a ConsoleHandler that publishes log messages to System.err. There are a number of other handlers included (eg. FileHandler, ConsoleHandler, SocketHandler, …) and you can easily create one yourself.

Formatters:

A handler can have a formatter associated with it. The formatter converts a log record to a String in a particular format, eg. XML.

Levels, Filters

When you ask the logger to log a message, the logger first checks whether it is interested at all. It does so by comparing the level associated with the log message with its own minimum log level. If it’s not interested (the level of the log message is less than its minimum log level), it returns immediately. If it is interested, it will pass the log message to a filter, if one is set. When you create a filter, you have complete control over what message is logged based on the contents of the log message or whatever, just return true (log) or false (don’t log). When the filter approves it (or no filter is defined), the log message is passed to all Handlers that are registered with the Logger.

Likewise, a Handler itself has a minimum log level and can be further customized with a filter.

LogManager

All loggers that are managed by a LogManager. A LogManager is a singleton that keeps track of a hierarchical namespace of Logger objects. It also contains functionality to configure Logger objects. For example, it reads its default configuration from lib/logging.properties.

log parents

Every Logger has a parent. According to the API, it is its nearest existing ancestor in the Logger dot-separated namespace.
The line

   Logger logger = Logger.getLogger("test");

will create a logger object in the namespace test and will register itself with the LogManager. Its parent logger is RootLogger (an inner class in LogManager).

   Logger logger1 = Logger.getLogger("test");
   Logger logger2 = Logger.getLogger("test.a");

In this example, logger1′s parent is RootLogger and logger2′s parent is logger1. When a logger is asked to log a message, by default it will also pass that message to its parents. For example:

Main.java:

import java.util.logging.*;
import java.util.*;
import java.io.*;
 
public class Main
{
   public static void main(String argv[]){
      Logger logger1 = Logger.getLogger("test");
      Logger logger2 = Logger.getLogger("test.a");
 
      logger2.severe("this is a log message");
   }
}

will output:

Jan 20, 2002 2:49:39 AM Main main
SEVERE: this is a log message

The process here is as follows: logger2 is asked to log a message. It passes the minimum log level test (default is INFO and Level.SEVERE > Level.INFO). There are no log handlers associated with logger2 so the message is passed to logger1. Same issue with logger1 that will pass the message to the RootLogger. By default, the RootLogger has one handler registered: ConsoleHandler. [Take a look at jre/lib/logging.properties where the default handlers and levels are set].

Let’s modify the example to add our own ConsoleHandler:

Main.java:

import java.util.logging.*;
import java.util.*;
import java.io.*;
 
public class Main
{
   public static void main(String argv[]){
      Logger logger1 = Logger.getLogger("test");
      Logger logger2 = Logger.getLogger("test.a");
 
      ConsoleHandler ch = new ConsoleHandler();
      ch.setLevel(Level.FINE);
      logger2.addHandler(ch);
 
      logger2.severe("this is a log message");
   }
}

outputs:

Jan 20, 2002 2:58:27 AM Main main
SEVERE: this is a log message
Jan 20, 2002 2:58:27 AM Main main
SEVERE: this is a log message

Here, both logger2 and RootLogger will log the message. You could prevent logger2 from calling its parent by invoking logger2.setUseParentHandlers(false).

Back to the first example and the question why the logger is only logging the first three messages. By now, you should be able to figure out what’s wrong. This diagram may help you:

   +--------------------+
   | RootLogger         |
   | Level: INFO        |
   | Handlers:          |
   |   - ConsoleHandler |
   |     Level: INFO    |
   +--------------------+
            |
   +------------------+
   | Logger "test"    |
   | Level: ALL       |
   | Handlers:        |
   |   (none)         |
   +------------------+

If we want to display all messages, we can do a number of things. We could register our own ConsoleHandler with the logger “test”:

Main.java:

import java.util.logging.*;
import java.io.*;
 
public class Main
{
   public static void main(String argv[]){
      Logger logger = Logger.getLogger("test");
 
      logger.setLevel(Level.ALL);
      ConsoleHandler ch = new ConsoleHandler();
      ch.setLevel(Level.ALL);
      logger.addHandler(ch);
 
      logger.severe("Log message #1");
      logger.warning("Log message #2");
      logger.info("Log message #3");
      logger.config("Log message #4");
      logger.fine("Log message #5");
      logger.finer("Log message #6");
      logger.finest("Log message #7");
   }
}

outputs:

Jan 20, 2002 3:14:29 AM Main main
SEVERE: Log message #1
Jan 20, 2002 3:14:29 AM Main main
SEVERE: Log message #1
Jan 20, 2002 3:14:30 AM Main main
WARNING: Log message #2
Jan 20, 2002 3:14:30 AM Main main
WARNING: Log message #2
Jan 20, 2002 3:14:30 AM Main main
INFO: Log message #3
Jan 20, 2002 3:14:30 AM Main main
INFO: Log message #3
Jan 20, 2002 3:14:30 AM Main main
CONFIG: Log message #4
Jan 20, 2002 3:14:30 AM Main main
FINE: Log message #5
Jan 20, 2002 3:14:30 AM Main main
FINER: Log message #6
Jan 20, 2002 3:14:30 AM Main main
FINEST: Log message #7

Notice now that we get the first three messages outputted twice, once by the logger “test” and once by its parent RootLogger. To turn this off, call logger.setUseParentHandlers(false).

More later when 1.4 is released. The logging API has changed quite a bit during the 1.4 BETA versions.

Meanwhile, look at the other question/answers for more examples that make use of the java.util.logging package.

Saving a property list to disk

Use the store method. Check out the following example that stores the system properties to a specified file.

Main.java:

import java.util.*;
import java.io.*;
 
public class Main {   
   public static void main(String[] args) throws Exception {
      if (args.length != 1) {
         System.out.println("Usage: java Main <filename>");
         System.exit(1);
      }
 
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(args[0]));
      Properties p = System.getProperties();
      p.store(bos, "Our stored System properties");     
   }
}

stores in a specified file:

#Our stored System properties
#Wed Jun 27 17:21:15 CEST 2001
java.specification.name=Java Platform API Specification
awt.toolkit=sun.awt.windows.WToolkit
java.version=1.2.2
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
user.timezone=Europe/Paris
java.specification.version=1.2
java.vm.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
user.home=C:\WINDOWS
os.arch=x86
java.awt.fonts=
java.vendor.url=http://java.sun.com/
file.encoding.pkg=sun.io
user.region=US
java.home=C:\JDK1.2.2\JRE
java.class.path=c:\jdk1.2.2\jre\lib\rt.jar;C:\PRO
GRA~1\JMF2.1\LIB\SOUND.JAR;C:\PROGRA~1\JMF2.1\LIB\
JMF.JAR;c:\jakarta-log4j-1.0.4\log4j-core.jar;
line.separator=rn
java.ext.dirs=C:\JDK1.2.2\JRE\lib\ext
java.io.tmpdir=c:\windows\TEMP\
os.name=Windows 95
java.vendor=Sun Microsystems Inc.
java.awt.printerjob=sun.awt.windows.WPrinterJob
java.library.path=C:\JDK1.2.2\BIN;.;C:\WINDOWS\SYSTEM;C:\WINDOWS;C:\JIKES\BIN
;C:\ANT\BIN\;C:\JDK1.2.2\BIN;C:\WINDOWS;C:\WIN
DOWS;C:\WINDOWS\COMMAND;;C:\WN16\BIN;C:\PROGRA~1
NETWOR~1\PGP;C:\VIM\VIM55
java.vm.specification.vendor=Sun Microsystems Inc.
sun.io.unicode.encoding=UnicodeLittle
file.encoding=Cp1252
java.specification.vendor=Sun Microsystems Inc.
user.name=esus
user.language=en
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi
java.vm.name=Classic VM
java.vm.specification.name=Java Virtual Machine Specification
java.class.version=46.0
sun.boot.library.path=C:\JDK1.2.2\JRE\bin
os.version=4.10
java.vm.info=build JDK-1.2.2_005, native threads, symcjit
java.vm.version=1.2.2
java.compiler=symcjit
path.separator=;
user.dir=C:\
file.separator=\
sun.boot.class.path=C:\JDK1.2.2\JRE\lib\rt.jar;C:\
JDK1.2.2\JRE\lib\i18n.jar;C:\JDK1.2.2\JRE\classes

Scheduling a task at a specific time of day, every day in Java

This example will run the thread PrintTask every day at 04h28m30s (just because I wrote this example at that time :).

Main.java:

import java.util.*;
  
public class Scheduler
{
   public static void main(String []args) {
      Timer timer = new Timer();
 
      Calendar calendar = Calendar.getInstance();
      calendar.set(Calendar.HOUR_OF_DAY, 4);
      calendar.set(Calendar.MINUTE, 28);
      calendar.set(Calendar.SECOND, 30);
      Date time = calendar.getTime();
 
      timer.schedule(new PrintTask(),
                     time);     
   }
 
   static class PrintTask extends TimerTask {
      public void run() {
         System.out.println("Task executed");
      }
   }
} 

Rendering HTML documents in Java

JEditorPane is able to display and edit different kinds of content. By default,
text/plain, text/html and text/rtf are recognized and passed on to the
EditorKit that is designed to handle it: DefaultEditorKit, HTMLEditorKit and
RTFEditorKit
. In the following example, a URL can be given in a JTextField.
Clicking GO will invoke the setPage method on the JEditorPane that will load
the page into a default document and set the content type. Using the
mime type of the page, the pane will automatically detect the correct EditorPane to
use.
Try: http://www.yahoo.com and http://www.esus.com/richtext.rtf

import javax.swing.text.html.*;
import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.awt.*;
import java.io.*;
 
public class Main extends JFrame
{
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
 
   public Main() {
 
      JButton uriButton = new JButton("Go!");
      // needs to be final to allow the inner class to access it!
      final JTextField uriTextField = new JTextField();
      final JEditorPane htmlPane = new JEditorPane();
      uriTextField.setText("http://www.yahoo.com");
      htmlPane.setEditable(false);
 
      uriButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            try {
               htmlPane.setPage(new URL(uriTextField.getText()));
            }
            catch(Exception e) {
               System.out.println(e);
            }
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      JPanel topPanel = new JPanel(new BorderLayout());
      topPanel.add(BorderLayout.CENTER, uriTextField);
      topPanel.add(BorderLayout.EAST, uriButton);
 
      getContentPane().add(BorderLayout.NORTH, topPanel);
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(htmlPane));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
 
      setSize(400, 400);
   }
}

Iconifying or deiconinfying a JFrame

Use setState(Frame.ICONIFIED) and setState(Frame.NORMAL).

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame implements ActionListener
{
   public Main()
   {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      JButton iconButton = new JButton("Iconify this Frame");
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
      getContentPane().add(iconButton);
      iconButton.addActionListener(this);
   }
 
   public void actionPerformed(ActionEvent ae) {     
      this.setState(Frame.ICONIFIED);  
   }
 
   public static void main(String args[])
   {
      Main main = new Main();
      main.setSize(300, 150);
      main.setVisible(true);
   }
}

Scrolling a JScrollPane to the top programmatically

Call the method scrollRectToVisible of the component that is added to the JScrollPane container as shown in following example:

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() throws Exception {
      getContentPane().setLayout(new BorderLayout());
 
      final JPanel panel = createPanel(); 
      final JScrollPane scrollpane = new JScrollPane(panel);
 
      JButton button = new JButton("Scroll to top!");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            panel.scrollRectToVisible(
              new Rectangle(0, 0, 1, 1));
         }
      });
 
      getContentPane().add(BorderLayout.NORTH, button);
      getContentPane().add(BorderLayout.CENTER, scrollpane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static JPanel createPanel() throws Exception {
      JPanel panel = new JPanel();
      panel.setLayout(new GridLayout(50, 20, 10, 10));
 
      for (int i=0; i<50; i++) {
         for (int j=0; j<20; j++) {
            JLabel label = new JLabel("label " + i + ", " + j);
            panel.add(label);    
         }
      }
 
      return panel;
   }
 
   public static void main(String [] args) throws Exception  {
      Main main = new Main();
      main.setSize(600, 600);
      main.setVisible(true);
   } 
}