blob: 6de95abdd9813d14e69533516723dc426c443fbc [file] [log] [blame]
/*
** Java native interface to the Windows Registry API.
**
** Authored by Timothy Gerard Endres
** <mailto:time@gjt.org> <http://www.trustice.com>
**
** This work has been placed into the public domain.
** You may use this work in any way and for any purpose you wish.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE.
**
*/
package com.ice.jni.registry;
import java.io.PrintWriter;
import java.util.*;
/**
* The RegistryKey class represents a key in the registry.
* The class also provides all of the native interface calls.
*
* You should refer to the Windows Registry API documentation
* for the details of any of the native methods. The native
* implementation performs almost no processing before or after
* a given call, so their behavior should match the API's
* documented behavior precisely.
*
* Note that you can not open a subkey without an existing
* open RegistryKey. Thus, you need to start with one of the
* top level keys defined in the Registry class and open
* relative to that.
*
* @version 3.1.3
*
* @see com.ice.jni.registry.Registry
* @see com.ice.jni.registry.RegistryValue
*/
public class
RegistryKey
{
/**
* Constants used to determine the access level for
* newly opened keys.
*/
public static final int ACCESS_DEFAULT = 0;
public static final int ACCESS_READ = 1;
public static final int ACCESS_WRITE = 2;
public static final int ACCESS_EXECUTE = 3;
public static final int ACCESS_ALL = 4;
/**
* This is the actual DWORD key that is returned from the
* Registry API. This value is <strong>totally opaque</strong>
* and should never be referenced.
*/
protected int hKey;
/**
* The full pathname of this key.
*/
protected String name;
/**
* Used to indicate whether or not the key was created
* when method createSubKey() is called, otherwise false.
*/
protected boolean created;
public
RegistryKey( int hKey, String name )
{
this.hKey = hKey;
this.name = name;
this.created = false;
}
public
RegistryKey( int hKey, String name, boolean created )
{
this.hKey = hKey;
this.name = name;
this.created = created;
}
/**
* The finalize() override checks to be sure the key is closed.
*/
public void
finalize()
{
// Never close a top level key...
if ( this.name.indexOf( "\\" ) > 0 )
{
// REVIEW should we have an "open/closed" flag
// to avoid double closes? Or is it better to
// lazily not call closeKey() and let finalize()
// do it all the time?
//
try { this.closeKey(); }
catch ( RegistryException ex )
{ }
}
}
/**
* Get the name of this key. This is <em>not</em> fully
* qualified, which means that the name will not contain
* any backslashes.
*
* @return The relative name of this key.
*/
public String
getName()
{
int index = this.name.lastIndexOf( "\\" );
if ( index < 0 )
return this.name;
else
return this.name.substring( index + 1 );
}
/**
* Get the full name of the key, from the top level down.
*
* @return The full name of the key.
*/
public String
getFullName()
{
return this.name;
}
/**
* Determine if this key was opened or created and opened.
* The result can only be true if createSubKey() was called
* and the key did not exist, and the creation of the new
* subkey succeeded.
*
* @return True if the key was created new, else false.
*/
public boolean
wasCreated()
{
return this.created;
}
/**
* Used to set the <em>created</em> state of this key.
*
* @param created The new <em>created</em> state.
*/
public void
setCreated( boolean created )
{
this.created = created;
}
/**
* Open a Registry subkey of this key with READ access.
*
* @param subkey The name of the subkey to open.
* @return The newly opened RegistryKey.
*
* @exception NoSuchKeyException If the subkey does not exist.
* @exception RegistryException Any other registry API error.
*/
public RegistryKey
openSubKey( String subkey )
throws NoSuchKeyException, RegistryException
{
return this.openSubKey( subkey, ACCESS_READ );
}
/**
* Create, and open, a Registry subkey of this key with WRITE access.
* If the key already exists, it is opened, otherwise it is first
* created and then opened.
*
* @param subkey The name of the subkey to create.
* @param className The className of the created subkey.
* @return The newly created and opened RegistryKey.
*
* @exception RegistryException Any valid registry API error.
*/
public RegistryKey
createSubKey( String subkey, String className )
throws RegistryException
{
return this.createSubKey( subkey, "", ACCESS_WRITE );
}
/**
* Set the value of this RegistryKey.
*
* @param value The value to set, including the value name.
*
* @exception RegistryException Any valid registry API error.
*/
public void
setValue( RegistryValue value )
throws RegistryException
{
this.setValue( value.getName(), value );
}
//
// N A T I V E M E T H O D S
//
/**
* Open a Registry subkey of this key with the specified access.
*
* @param subkey The name of the subkey to open.
* @param access The access level for the open.
* @return The newly opened RegistryKey.
*
* @exception NoSuchKeyException If the subkey does not exist.
* @exception RegistryException Any other registry API error.
*/
public native RegistryKey
openSubKey( String subKey, int access )
throws NoSuchKeyException, RegistryException;
/**
* Connect to the remote registry on <em>hostName</em>.
* This method will only work when invoked on a toplevel
* key. The returned value will be the same toplevel key
* opened from the remote host's registry.
*
* @param hostName The remote computer's hostname.
* @return The remote top level key identical to this top level key.
*
* @exception NoSuchKeyException If the subkey does not exist.
* @exception RegistryException Any other registry API error.
*/
public native RegistryKey
connectRegistry( String hostName )
throws NoSuchKeyException, RegistryException;
/**
* Create a new subkey, or open the existing one. You can
* determine if the subkey was created, or whether an
* existing subkey was opened, via the wasCreated() method.
*
* @param subKey The name of the subkey to create/open.
* @param className The key's class name, or null.
* @param access The access level of the opened subkey.
* @return The newly created or opened subkey.
*
* @exception RegistryException Any valid registry API error.
*/
public native RegistryKey
createSubKey( String subKey, String className, int access )
throws RegistryException;
/**
* Closes this subkey. You may chose to let the finalize()
* method do the close.
*
* @exception RegistryException Any valid registry API error.
*/
public native void
closeKey()
throws RegistryException;
/**
* Delete a named subkey.
*
* @param subKey The name of the subkey to delete.
*
* @exception NoSuchKeyException If the subkey does not exist.
* @exception RegistryException Any other registry API error.
*/
public native void
deleteSubKey( String subKey )
throws NoSuchKeyException, RegistryException;
/**
* Delete a named value.
*
* @param valueName The name of the value to delete.
*
* @exception NoSuchValueException If the value does not exist.
* @exception RegistryException Any other registry API error.
*/
public native void
deleteValue( String valueName )
throws NoSuchValueException, RegistryException;
/**
* Guarentees that this key is written to disk. This
* method should be called only when needed, as it has
* a huge performance cost.
*
* @exception RegistryException Any valid registry API error.
*/
public native void
flushKey()
throws RegistryException;
/**
* Set the name value to the given data.
*
* @param valueName The name of the value to set.
* @param value The data to set the named value.
*
* @exception RegistryException Any valid registry API error.
*/
public native void
setValue( String valueName, RegistryValue value )
throws RegistryException;
/**
* Get the data of a named value.
*
* @param valueName The name of the value to get.
* @return The data of the named value.
*
* @exception NoSuchValueException If the value does not exist.
* @exception RegistryException Any other registry API error.
*/
public native RegistryValue
getValue( String valueName )
throws NoSuchValueException, RegistryException;
/**
* Get the value of a REG_SZ or REG_EXPAND_SZ value.
*
* @param valueName The name of the value to get.
* @return The string data of the named value.
*
* @exception NoSuchValueException If the value does not exist.
* @exception RegistryException Any other registry API error.
*/
public native String
getStringValue( String valueName )
throws NoSuchValueException, RegistryException;
/**
* Get the data from the default value.
*
* @return The string data of the default value.
*
* @exception NoSuchValueException If the value does not exist.
* @exception RegistryException Any other registry API error.
*/
public native String
getDefaultValue()
throws NoSuchValueException, RegistryException;
/**
* Determines if this key has a default value.
*
* @return True if there is a default value, else false.
*
* @exception RegistryException Any valid registry API error.
*/
public native boolean
hasDefaultValue()
throws RegistryException;
/**
* Determines if this key has <em>only</em> a default value.
*
* @return True if there is only a default value, else false.
*
* @exception RegistryException Any valid registry API error.
*/
public native boolean
hasOnlyDefaultValue()
throws RegistryException;
/**
* Obtains the number of subkeys that this key contains.
*
* @return The number of subkeys that this key contains.
*
* @exception RegistryException Any valid registry API error.
*/
public native int
getNumberSubkeys()
throws RegistryException;
/**
* Obtains the maximum length of all of the subkey names.
*
* @return The maximum length of all of the subkey names.
*
* @exception RegistryException Any valid registry API error.
*/
public native int
getMaxSubkeyLength()
throws RegistryException;
/**
* Obtains an enumerator for the subkeys of this key.
*
* @return The key enumerator.
*
* @exception RegistryException Any valid registry API error.
*/
public native String
regEnumKey( int index )
throws RegistryException;
/**
* Obtains the number of values that this key contains.
*
* @return The number of values that this key contains.
*
* @exception RegistryException Any valid registry API error.
*/
public native int
getNumberValues()
throws RegistryException;
/**
* Obtains the maximum length of all of the value data.
*
* @return The maximum length of all of the value data.
*
* @exception RegistryException Any valid registry API error.
*/
public native int
getMaxValueDataLength()
throws RegistryException;
/**
* Obtains the maximum length of all of the value names.
*
* @return The maximum length of all of the value names.
*
* @exception RegistryException Any valid registry API error.
*/
public native int
getMaxValueNameLength()
throws RegistryException;
/**
* Obtains an enumerator for the values of this key.
*
* @return The value enumerator.
*
* @exception RegistryException Any valid registry API error.
*/
public native String
regEnumValue( int index )
throws RegistryException;
//
// Convenience routines
//
/**
* This method will increment the value of a REG_DWORD value.
*
* @param valueName The name of the value to increment.
*
* @exception NoSuchValueException If the value does not exist.
* @exception RegistryException Any other registry API error.
*/
public native int
incrDoubleWord( String valueName )
throws NoSuchValueException, RegistryException;
/**
* This method will decrement the value of a REG_DWORD value.
*
* @param valueName The name of the value to increment.
*
* @exception NoSuchValueException If the value does not exist.
* @exception RegistryException Any other registry API error.
*/
public native int
decrDoubleWord( String valueName )
throws NoSuchValueException, RegistryException;
/**
* This method will expand a string to include the definitions
* of System environment variables that are referenced via the
* %variable% construct. This method invokes EnvExpandStrings().
*
* @param valueName The name of the value to increment.
*/
public static native String
expandEnvStrings( String exString );
/**
* Returns a new Enumeration that will enumerate the
* names of the subkeys of this key,
*
* @return A new Enumeration to enumerate subkey names.
*
* @exception RegistryException Any valid registry API error.
*/
public Enumeration
keyElements()
throws RegistryException
{
return this.new RegistryKeyEnumerator( this );
}
/**
* Returns a new Enumeration that will enumerate the
* names of the values of this key,
*
* @return A new Enumeration to enumerate value names.
*
* @exception RegistryException Any valid registry API error.
*/
public Enumeration
valueElements()
throws RegistryException
{
return this.new RegistryValueEnumerator( this );
}
/**
* A RegistryKey enumerator class. This enumerator
* is used to enumerate the names of this key's subkeys.
*
* This class should remain opaque to the client,
* which will use the Enumeration interface.
*/
class
RegistryKeyEnumerator implements Enumeration
{
RegistryKey key;
int currIndex;
int numSubKeys;
public
RegistryKeyEnumerator( RegistryKey key )
throws RegistryException
{
this.key = key;
this.currIndex = 0;
this.numSubKeys = key.getNumberSubkeys();
}
public boolean hasMoreElements()
{
return ( this.currIndex < this.numSubKeys );
}
public Object
nextElement()
{
Object result = null;
try { result = this.key.regEnumKey( this.currIndex++ ); }
catch ( RegistryException ex )
{
throw new NoSuchElementException( ex.getMessage() );
}
return result;
}
}
/**
* A RegistryValue enumerator class. This enumerator
* is used to enumerate the names of this key's values.
* This will return the default value name as an empty string.
*
* This class should remain opaque to the client.
* It will use the Enumeration interface.
*/
class
RegistryValueEnumerator implements Enumeration
{
RegistryKey key;
int currIndex;
int numValues;
public
RegistryValueEnumerator( RegistryKey key )
throws RegistryException
{
this.key = key;
this.currIndex = 0;
this.numValues = key.getNumberValues();
}
public boolean hasMoreElements()
{
return ( this.currIndex < this.numValues );
}
public Object
nextElement()
{
Object result = null;
try { result = this.key.regEnumValue( this.currIndex++ ); }
catch ( RegistryException ex )
{
throw new NoSuchElementException( ex.getMessage() );
}
return result;
}
}
/**
* Export this key's definition to the provided PrintWriter.
* The resulting file can be imported via RegEdit.
*
* @exception NoSuchKeyException Thrown by openSubKey().
* @exception NoSuchValueException Thrown by getValue().
* @exception RegistryException Any other registry API error.
*/
public void
export( PrintWriter out, boolean descend )
throws NoSuchKeyException, RegistryException
{
Enumeration en;
out.println( "[" + this.getFullName() + "]" );
en = this.valueElements();
for ( int idx = 0 ; en.hasMoreElements() ; ++idx )
{
String valueName = (String) en.nextElement();
RegistryValue value = this.getValue( valueName );
value.export( out );
}
out.println( "" );
if ( descend )
{
en = this.keyElements();
for ( int idx = 0 ; en.hasMoreElements() ; ++idx )
{
String keyName = (String) en.nextElement();
RegistryKey subKey = this.openSubKey( keyName );
subKey.export( out, descend );
subKey.closeKey();
}
}
}
}