The Artima Developer Community
Sponsored Link

Computing Thoughts
Subduing CLASSPATH
by Bruce Eckel
August 20, 2006
Summary
Setting CLASSPATH for directories and jars driving you crazy? I finally decided to do something about it.

Advertisement

The answer is some heavy-handed automation and convention. First, why bother trying to put files in the jre\lib\ext directory? Last I heard, there was some kind of security issue so it's prevented, maybe, in some cases. I don't want to have to know what those cases are.

Besides, you have to click down a bunch of directories to find jre\lib\ext, and at least on my system there always seems to end up being two of them, one for the JDK and one for the JRE, and half the time I put it in the wrong place. Too confusing, too much effort.

How about if all jar files just go in a directory called C:\jar? I don't think that will hurt anything, and it will be much easier to manage. Also, if you need to move your setup from your desktop to your laptop, all you have to do is copy that directory.

Well, almost. The other problem is that every time you add a new jar or a new directory to the CLASSPATH, you have to go in and set the environment variables on my computer, editing a really long line in a little tiny window. I'll be happy if I don't have to do that again.

Also, it's very easy to get incorrect and old, nonexistent elements in your CLASSPATH. I'd like that to be automatically fixed, as well.

Conveniently, Python is very good at all kinds of file and directory stuff. But even better, it has the _winreg module (as part of the standard Python distribution), which allows you to directly modify the registry.

The following program pulls your current CLASSPATH from the registry (so there are no problems if the CLASSPATH has been temporarily changed for one command window), removes duplicates and dead links, and then does one of three things:

  1. If there are jar files in the current directory and you don't provide command-line arguments, all the jar files are added to your CLASSPATH.
  2. If there are no jar files in the current directory, that directory is added to the CLASSPATH.
  3. If you provide command-line arguments, those are assumed to be jar files and added to the classpath.

So if you put this program in your C:\jars directory, every time you throw in a new jar file you can just double-click it to add that jar to your CLASSPATH. Should make hand-installation a lot simpler!

Finally, this might be the ideal solution for beginners and classroom situations, where lots of time is lost struggling with silly CLASSPATH issues.

I got most of the information about how to do this by googling for it, but this article was especially helpful.


#!python
"""
SetClasspath.py by Bruce Eckel, 2006 www.MindView.net
Permission granted for free use and distribution as long as this notice is maintained.

Warning! This program modifies the Windows Registry! Use at your own risk.

With no arguments:
    If there are jar files in the current directory, each one is added to the CLASSPATH.
    If there are no jar files, the current directory is added to the CLASSPATH.

With arguments:
    Each argument must be a jar file name. Each argument is added to the CLASSPATH.

Duplicate CLASSPATH entries and nonexistent paths are removed.

I recommend creating C:\jars directory, and adding this program to that directory.
Whenever you need to add a new jar, throw it in C:\jars and double-click this program.
That way, if you need the same set of jars on another machine, just copy the
directory and run this program.

It's also useful to create a batch/cmd file to run this program, and to place
that file in your Windows PATH. Then you can run the program from any directory.
The batch file might look like this:
python C:\jars\SetClassPath.py %1 %2 %3 %4 %5 %6 %7 %8 %9
If you're running Cygwin, you can make a shell file to do the same thing:
python C:/jars/SetClassPath.py $1 $2 $3 $4 $5 $6 $7 $8 $9

This program requires PythonWin, which you can find at:
http://starship.python.net/crew/mhammond/win32/
"""
from _winreg import *
import os, glob, sys
import win32gui, win32con # From PythonWin
path = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'

def getClassPath():
    try:
        reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
        key = OpenKey(reg, path, 0, KEY_ALL_ACCESS)
        i = 0
        while True:
            try:
                name, value, valueType = EnumValue(key, i)
                if name == 'CLASSPATH':
                    return value
                i += 1
            except EnvironmentError:
                return ""
    finally:
        CloseKey(key)
        CloseKey(reg)

def setClassPath(newPath):
    try:
        reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
        key = OpenKey(reg, path, 0, KEY_ALL_ACCESS)
        SetValueEx(key, 'CLASSPATH', 0, REG_SZ, newPath)
        win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
    finally:
        CloseKey(key)
        CloseKey(reg)

if __name__=='__main__':
    # set prevents duplicates, 'if os.path.exists(p)' prunes nonexistent paths:
    pathparts = set([p for p in getClassPath().split(os.pathsep) if os.path.exists(p)])
    pathparts.add(".")
    pathparts.add("..")
    if len(sys.argv) > 1:
        for arg in sys.argv[1:]:
            if not arg.endswith(".jar"):
                print "Arguments must be jar file names: problem with [" + arg + "]"
                sys.exit(1)
            if not os.path.exists(arg):
                print arg, "does not exist in this directory"
                sys.exit(1)
            pathparts.add(os.path.abspath(arg))
    else:
        jars = glob.glob("*.jar")
        if jars:
            for jar in jars:
                pathparts.add(os.path.abspath(jar))
        else:
            pathparts.add(os.getcwd())
    result = list(pathparts)
    result.sort()
    newClasspath = os.pathsep.join(result) + os.pathsep
    setClassPath(newClasspath)
    print getClassPath()

If there's a Linuxphile among you who would like to add a Linux (and presumably OSX would work for free) option to the above program, I'd love to incorporate that.

Talk Back!

Have an opinion? Readers have already posted 26 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Bruce Eckel adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Bruce Eckel (www.BruceEckel.com) provides development assistance in Python with user interfaces in Flex. He is the author of Thinking in Java (Prentice-Hall, 1998, 2nd Edition, 2000, 3rd Edition, 2003, 4th Edition, 2005), the Hands-On Java Seminar CD ROM (available on the Web site), Thinking in C++ (PH 1995; 2nd edition 2000, Volume 2 with Chuck Allison, 2003), C++ Inside & Out (Osborne/McGraw-Hill 1993), among others. He's given hundreds of presentations throughout the world, published over 150 articles in numerous magazines, was a founding member of the ANSI/ISO C++ committee and speaks regularly at conferences.

This weblog entry is Copyright © 2006 Bruce Eckel. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us