Imported GNU Classpath 0.90
Imported GNU Classpath 0.90
* scripts/makemake.tcl: LocaleData.java moved to gnu/java/locale.
* sources.am: Regenerated.
* gcj/javaprims.h: Regenerated.
* Makefile.in: Regenerated.
* gcj/Makefile.in: Regenerated.
* include/Makefile.in: Regenerated.
* testsuite/Makefile.in: Regenerated.
* gnu/java/lang/VMInstrumentationImpl.java: New override.
* gnu/java/net/local/LocalSocketImpl.java: Likewise.
* gnu/classpath/jdwp/VMMethod.java: Likewise.
* gnu/classpath/jdwp/VMVirtualMachine.java: Update to latest
interface.
* java/lang/Thread.java: Add UncaughtExceptionHandler.
* java/lang/reflect/Method.java: Implements GenericDeclaration and
isSynthetic(),
* java/lang/reflect/Field.java: Likewise.
* java/lang/reflect/Constructor.java
* java/lang/Class.java: Implements Type, GenericDeclaration,
getSimpleName() and getEnclosing*() methods.
* java/lang/Class.h: Add new public methods.
* java/lang/Math.java: Add signum(), ulp() and log10().
* java/lang/natMath.cc (log10): New function.
* java/security/VMSecureRandom.java: New override.
* java/util/logging/Logger.java: Updated to latest classpath
version.
* java/util/logging/LogManager.java: New override.
From-SVN: r113887
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
tools.zip
|
||||
@@ -1,17 +1,19 @@
|
||||
## Input file for automake to generate the Makefile.in used by configure
|
||||
|
||||
GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
|
||||
|
||||
# Setup the compiler to use the GNU Classpath library we just build
|
||||
if FOUND_GCJ
|
||||
JCOMPILER = $(GCJ) --bootclasspath '$(top_builddir)/lib' --classpath . -C
|
||||
JCOMPILER = $(GCJ) -encoding UTF-8 --bootclasspath $(GLIBJ_CLASSPATH) --classpath . -C
|
||||
else
|
||||
if FOUND_JIKES
|
||||
JCOMPILER = $(JIKES) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(top_builddir)/lib:.
|
||||
JCOMPILER = $(JIKES) $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(GLIBJ_CLASSPATH):.
|
||||
else
|
||||
if FOUND_GCJX
|
||||
JCOMPILER = $(GCJX) -bootclasspath '' -sourcepath '' -classpath $(top_builddir)/lib:.
|
||||
JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
|
||||
else
|
||||
if FOUND_ECJ
|
||||
JCOMPILER = $(ECJ) -bootclasspath '$(top_builddir)/lib' -classpath .
|
||||
JCOMPILER = $(ECJ) -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
|
||||
else
|
||||
error dunno how to setup the JCOMPILER and compile
|
||||
endif
|
||||
@@ -48,36 +50,12 @@ READMES = $(srcdir)/gnu/classpath/tools/giop/README
|
||||
ALL_TOOLS_FILES = $(TOOLS_JAVA_FILES) $(TOOLS_TEMPLATES) $(TOOLS_HELPS) $(READMES)
|
||||
|
||||
# Some architecture independent data to be installed.
|
||||
TOOLS_DATA = $(TOOLS_ZIP)
|
||||
TOOLS_DATA = $(TOOLS_ZIP) README
|
||||
|
||||
# Where we want these data files installed.
|
||||
TOOLSdir = $(pkgdatadir)/tools
|
||||
|
||||
# Make sure all sources and icons are also installed so users can use them.
|
||||
# (Be careful to strip off the srcdir part of the path when installing.)
|
||||
install-data-local:
|
||||
srcdir_cnt=`echo $(srcdir) | wc -c`; \
|
||||
for file in $(ALL_TOOLS_FILES); do \
|
||||
f=`echo $$file | cut -c$$srcdir_cnt-`; \
|
||||
fdir=`dirname $$f`; \
|
||||
if test ! -d $(DESTDIR)$(pkgdatadir)/tools/$$fdir; then \
|
||||
echo "$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir"; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir; \
|
||||
fi; \
|
||||
echo "$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
|
||||
$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f; \
|
||||
done
|
||||
|
||||
uninstall-local:
|
||||
srcdir_cnt=`echo $(srcdir) | wc -c`; \
|
||||
for file in $(ALL_TOOLS_FILES); do \
|
||||
f=`echo $$file | cut -c$$srcdir_cnt-`; \
|
||||
echo "rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
|
||||
rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f; \
|
||||
done
|
||||
TOOLSdir = $(pkgdatadir)
|
||||
|
||||
# Make sure everything is included in the distribution.
|
||||
EXTRA_DIST = Makefile.am
|
||||
dist-hook:
|
||||
srcdir_cnt=`echo $(srcdir) | wc -c`; \
|
||||
for file in $(ALL_TOOLS_FILES); do \
|
||||
@@ -91,9 +69,10 @@ dist-hook:
|
||||
cp -p $$file $(distdir)/$$f; \
|
||||
done
|
||||
|
||||
# To generate the example zip just depend on the sources and ignore the
|
||||
# class files. Always regenerate all .class files and remove them immediatly.
|
||||
# And copy the template files we use to the classes dir so they get also included.
|
||||
# To generate the example zip just depend on the sources and ignore
|
||||
# the class files. Always regenerate all .class files and remove them
|
||||
# immediately. And copy the template files we use to the classes dir
|
||||
# so they get also included.
|
||||
$(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
|
||||
mkdir -p classes/gnu/classpath/tools/giop/grmic/templates
|
||||
mkdir -p classes/gnu/classpath/tools/rmi/rmic/templates
|
||||
|
||||
@@ -38,7 +38,8 @@ build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = tools
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
$(srcdir)/jarsigner.sh.in $(srcdir)/keytool.sh.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../../libtool.m4 \
|
||||
$(top_srcdir)/m4/acattribute.m4 $(top_srcdir)/m4/accross.m4 \
|
||||
@@ -51,7 +52,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_FILES = jarsigner.sh keytool.sh
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
@@ -79,6 +80,7 @@ CAIRO_LIBS = @CAIRO_LIBS@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CLASSPATH_CONVENIENCE = @CLASSPATH_CONVENIENCE@
|
||||
CLASSPATH_INCLUDES = @CLASSPATH_INCLUDES@
|
||||
CLASSPATH_MODULE = @CLASSPATH_MODULE@
|
||||
COLLECTIONS_PREFIX = @COLLECTIONS_PREFIX@
|
||||
@@ -118,6 +120,8 @@ ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
ECJ = @ECJ@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_LOCAL_SOCKETS_FALSE = @ENABLE_LOCAL_SOCKETS_FALSE@
|
||||
ENABLE_LOCAL_SOCKETS_TRUE = @ENABLE_LOCAL_SOCKETS_TRUE@
|
||||
ERROR_CFLAGS = @ERROR_CFLAGS@
|
||||
EXAMPLESDIR = @EXAMPLESDIR@
|
||||
EXEEXT = @EXEEXT@
|
||||
@@ -138,6 +142,7 @@ FREETYPE2_LIBS = @FREETYPE2_LIBS@
|
||||
GCJ = @GCJ@
|
||||
GCJX = @GCJX@
|
||||
GJDOC = @GJDOC@
|
||||
GREP = @GREP@
|
||||
GTK_CAIRO_ENABLED = @GTK_CAIRO_ENABLED@
|
||||
GTK_CAIRO_FALSE = @GTK_CAIRO_FALSE@
|
||||
GTK_CAIRO_TRUE = @GTK_CAIRO_TRUE@
|
||||
@@ -185,6 +190,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PANGOFT2_CFLAGS = @PANGOFT2_CFLAGS@
|
||||
PANGOFT2_LIBS = @PANGOFT2_LIBS@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PATH_TO_GLIBJ_ZIP = @PATH_TO_GLIBJ_ZIP@
|
||||
PERL = @PERL@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
QT_CFLAGS = @QT_CFLAGS@
|
||||
@@ -203,8 +209,11 @@ USER_SPECIFIED_CLASSLIB_FALSE = @USER_SPECIFIED_CLASSLIB_FALSE@
|
||||
USER_SPECIFIED_CLASSLIB_TRUE = @USER_SPECIFIED_CLASSLIB_TRUE@
|
||||
USER_SPECIFIED_JAVAH_FALSE = @USER_SPECIFIED_JAVAH_FALSE@
|
||||
USER_SPECIFIED_JAVAH_TRUE = @USER_SPECIFIED_JAVAH_TRUE@
|
||||
USE_PREBUILT_GLIBJ_ZIP_FALSE = @USE_PREBUILT_GLIBJ_ZIP_FALSE@
|
||||
USE_PREBUILT_GLIBJ_ZIP_TRUE = @USE_PREBUILT_GLIBJ_ZIP_TRUE@
|
||||
VERSION = @VERSION@
|
||||
WARNING_CFLAGS = @WARNING_CFLAGS@
|
||||
XMKMF = @XMKMF@
|
||||
XML_CFLAGS = @XML_CFLAGS@
|
||||
XML_LIBS = @XML_LIBS@
|
||||
XSLT_CFLAGS = @XSLT_CFLAGS@
|
||||
@@ -216,8 +225,6 @@ X_PRE_LIBS = @X_PRE_LIBS@
|
||||
ZIP = @ZIP@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
@@ -234,7 +241,10 @@ build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
default_toolkit = @default_toolkit@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
glibjdir = @glibjdir@
|
||||
host = @host@
|
||||
@@ -242,18 +252,22 @@ host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
nativelibdir = @nativelibdir@
|
||||
nativeexeclibdir = @nativeexeclibdir@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
@@ -263,12 +277,13 @@ target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
vm_classes = @vm_classes@
|
||||
@FOUND_ECJ_TRUE@@FOUND_GCJX_FALSE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(ECJ) -bootclasspath '$(top_builddir)/lib' -classpath .
|
||||
@FOUND_GCJX_TRUE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(GCJX) -bootclasspath '' -sourcepath '' -classpath $(top_builddir)/lib:.
|
||||
@FOUND_GCJ_FALSE@@FOUND_JIKES_TRUE@JCOMPILER = $(JIKES) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(top_builddir)/lib:.
|
||||
GLIBJ_CLASSPATH = '$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
|
||||
@FOUND_ECJ_TRUE@@FOUND_GCJX_FALSE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(ECJ) -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
|
||||
@FOUND_GCJX_TRUE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
|
||||
@FOUND_GCJ_FALSE@@FOUND_JIKES_TRUE@JCOMPILER = $(JIKES) $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(GLIBJ_CLASSPATH):.
|
||||
|
||||
# Setup the compiler to use the GNU Classpath library we just build
|
||||
@FOUND_GCJ_TRUE@JCOMPILER = $(GCJ) --bootclasspath '$(top_builddir)/lib' --classpath . -C
|
||||
@FOUND_GCJ_TRUE@JCOMPILER = $(GCJ) -encoding UTF-8 --bootclasspath $(GLIBJ_CLASSPATH) --classpath . -C
|
||||
|
||||
# All our example java source files
|
||||
TOOLS_JAVA_FILES = $(srcdir)/gnu/classpath/tools/*.java $(srcdir)/gnu/classpath/tools/*/*.java $(srcdir)/gnu/classpath/tools/*/*/*.java
|
||||
@@ -296,13 +311,10 @@ READMES = $(srcdir)/gnu/classpath/tools/giop/README
|
||||
ALL_TOOLS_FILES = $(TOOLS_JAVA_FILES) $(TOOLS_TEMPLATES) $(TOOLS_HELPS) $(READMES)
|
||||
|
||||
# Some architecture independent data to be installed.
|
||||
TOOLS_DATA = $(TOOLS_ZIP)
|
||||
TOOLS_DATA = $(TOOLS_ZIP) README
|
||||
|
||||
# Where we want these data files installed.
|
||||
TOOLSdir = $(pkgdatadir)/tools
|
||||
|
||||
# Make sure everything is included in the distribution.
|
||||
EXTRA_DIST = Makefile.am
|
||||
TOOLSdir = $(pkgdatadir)
|
||||
all: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
@@ -336,6 +348,10 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
jarsigner.sh: $(top_builddir)/config.status $(srcdir)/jarsigner.sh.in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||
keytool.sh: $(top_builddir)/config.status $(srcdir)/keytool.sh.in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
@@ -452,7 +468,7 @@ info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-TOOLSDATA install-data-local
|
||||
install-data-am: install-TOOLSDATA
|
||||
|
||||
install-exec-am:
|
||||
|
||||
@@ -478,44 +494,22 @@ ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-TOOLSDATA uninstall-info-am uninstall-local
|
||||
uninstall-am: uninstall-TOOLSDATA uninstall-info-am
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||
clean-local dist-hook distclean distclean-generic \
|
||||
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
||||
install install-TOOLSDATA install-am install-data \
|
||||
install-data-am install-data-local install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
uninstall uninstall-TOOLSDATA uninstall-am uninstall-info-am \
|
||||
uninstall-local
|
||||
install-data-am install-exec install-exec-am install-info \
|
||||
install-info-am install-man install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am uninstall \
|
||||
uninstall-TOOLSDATA uninstall-am uninstall-info-am
|
||||
|
||||
@FOUND_ECJ_FALSE@@FOUND_GCJX_FALSE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@error dunno how to setup the JCOMPILER and compile
|
||||
|
||||
# Make sure all sources and icons are also installed so users can use them.
|
||||
# (Be careful to strip off the srcdir part of the path when installing.)
|
||||
install-data-local:
|
||||
srcdir_cnt=`echo $(srcdir) | wc -c`; \
|
||||
for file in $(ALL_TOOLS_FILES); do \
|
||||
f=`echo $$file | cut -c$$srcdir_cnt-`; \
|
||||
fdir=`dirname $$f`; \
|
||||
if test ! -d $(DESTDIR)$(pkgdatadir)/tools/$$fdir; then \
|
||||
echo "$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir"; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir; \
|
||||
fi; \
|
||||
echo "$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
|
||||
$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f; \
|
||||
done
|
||||
|
||||
uninstall-local:
|
||||
srcdir_cnt=`echo $(srcdir) | wc -c`; \
|
||||
for file in $(ALL_TOOLS_FILES); do \
|
||||
f=`echo $$file | cut -c$$srcdir_cnt-`; \
|
||||
echo "rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
|
||||
rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f; \
|
||||
done
|
||||
# Make sure everything is included in the distribution.
|
||||
dist-hook:
|
||||
srcdir_cnt=`echo $(srcdir) | wc -c`; \
|
||||
for file in $(ALL_TOOLS_FILES); do \
|
||||
@@ -529,9 +523,10 @@ dist-hook:
|
||||
cp -p $$file $(distdir)/$$f; \
|
||||
done
|
||||
|
||||
# To generate the example zip just depend on the sources and ignore the
|
||||
# class files. Always regenerate all .class files and remove them immediatly.
|
||||
# And copy the template files we use to the classes dir so they get also included.
|
||||
# To generate the example zip just depend on the sources and ignore
|
||||
# the class files. Always regenerate all .class files and remove them
|
||||
# immediately. And copy the template files we use to the classes dir
|
||||
# so they get also included.
|
||||
$(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
|
||||
mkdir -p classes/gnu/classpath/tools/giop/grmic/templates
|
||||
mkdir -p classes/gnu/classpath/tools/rmi/rmic/templates
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
The GNU Classpath tools are stored in the tools.zip. They can be invoked by
|
||||
putting this archive into classpath and specifying the tool main class as the
|
||||
class to run (parameters usually follow). The current release contains the
|
||||
following tools:
|
||||
|
||||
== GIOP tools ==
|
||||
|
||||
GIOP tools are used for creating the applications that use GIOP communication
|
||||
protocol. It provides necessary support for org.omg.* and javax.rmi.*
|
||||
packages.
|
||||
|
||||
All GIOP tools support the --help option, for instance:
|
||||
java -cp tools.zip gnu.classpath.tools.giop.IorParser --help
|
||||
|
||||
The list of the currently available GIOP tools (name matches the main
|
||||
class in gnu.classpath.tools.giop package):
|
||||
|
||||
* GRMIC - RMI-IIOP stub and tie generator.
|
||||
* NameService - GIOP transient naming service (this tool is called
|
||||
tnameserv in Sun's package).
|
||||
* NameServicePersistent
|
||||
- GIOP persistent naming service (this tool is called
|
||||
orbd in Sun's package).
|
||||
* IorParser - Parses the stringified form of the interoperable
|
||||
object references (IOR's).
|
||||
|
||||
== RMI tools ==
|
||||
|
||||
RMI tools provide support for java.rmi package. All tools support
|
||||
the --help key by printing more information, for instance:
|
||||
java -cp tools.zip gnu.classpath.tools.rmi.RMIC --help
|
||||
|
||||
The list of the currently available RMI tools (name matches the main tool class
|
||||
in gnu.classpath.tools.rmi package):
|
||||
|
||||
* RMIC - RMI stub and tie source code generator (complements
|
||||
the ASM based bytecode generator in the separate
|
||||
cp-tools project). This tool is only needed for
|
||||
research and backward-compatibile applications, as
|
||||
Classpath supports the 1.5 feature to replace such
|
||||
stubs by proxy classes.
|
||||
* REGISTRY - The persistent RMI naming service.
|
||||
* RMID - The persistent RMI activation daemon, supports the
|
||||
java.rmi.activation package.
|
||||
|
||||
== Security tools ==
|
||||
|
||||
Security tools (currently) are used for signing and verifying JAR files
|
||||
as well as (planned) generating and managing cryptographic tokens and
|
||||
credentials.
|
||||
|
||||
The list of individual tools, the name of their main class that should be
|
||||
invoked by the Java launcher, and a summary of what they provide follows:
|
||||
|
||||
* jarsigner gnu.classpath.tools.jarsigner.Main
|
||||
A drop-in replacement for the "jarsigner" tool.
|
||||
|
||||
|
||||
@@ -69,6 +69,39 @@ public class HelpPrinter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the contents of the resource specified by the designated path.
|
||||
*
|
||||
* @param helpResourcePath the path to a help resource, related to the
|
||||
* HelpPrinter class.
|
||||
*/
|
||||
public static void printHelp(String helpResourcePath)
|
||||
{
|
||||
InputStream in = HelpPrinter.class.getResourceAsStream(helpResourcePath);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
try
|
||||
{
|
||||
String s;
|
||||
while ((s = br.readLine()) != null)
|
||||
System.out.println(s);
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
System.err.print("Resource loading is broken:");
|
||||
x.printStackTrace(System.err);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
br.close();
|
||||
}
|
||||
catch (IOException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the help message and terminates.
|
||||
*
|
||||
@@ -77,23 +110,7 @@ public class HelpPrinter
|
||||
*/
|
||||
public static void printHelpAndExit(String helpResourcePath)
|
||||
{
|
||||
InputStream in = HelpPrinter.class.getResourceAsStream(helpResourcePath);
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
try
|
||||
{
|
||||
String s;
|
||||
while ((s = r.readLine()) != null)
|
||||
{
|
||||
System.out.println(s);
|
||||
}
|
||||
r.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.print("Resource loading is broken:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
printHelp(helpResourcePath);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/* CallbackUtil.java -- Callback related utilities
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.common;
|
||||
|
||||
import gnu.javax.security.auth.callback.ConsoleCallbackHandler;
|
||||
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
/**
|
||||
* A <i>Helper</i> class containing general purpose utlity methods dealing with
|
||||
* callback handlers and their <i>Security Provider</i>.
|
||||
*/
|
||||
public abstract class CallbackUtil
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(CallbackUtil.class.getName());
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// Class methods
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return an implementation of the {@link CallbackHandler}, from any
|
||||
* {@link Provider}, capable of handling callbacks through the <i>console</i>;
|
||||
* i.e. <code>System.in</code> and <code>System.out</code>.
|
||||
* <p>
|
||||
* If no <i>Security Provider</i> for this type of callback was found, this
|
||||
* method returns the default GNU implementation.
|
||||
*
|
||||
* @return a console {@link CallbackHandler} implementation.
|
||||
*/
|
||||
public static final CallbackHandler getConsoleHandler()
|
||||
{
|
||||
CallbackHandler result = getHandler("Console");
|
||||
if (result == null)
|
||||
{
|
||||
log.fine("No console callback handler found. Will use ours");
|
||||
result = new ConsoleCallbackHandler();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link CallbackHandler}, of a designated type, for interacting
|
||||
* with the user.
|
||||
* <p>
|
||||
* This method first finds all currently installed <i>Security Providers</i>
|
||||
* capable of providing such service and then in turn attempts to instantiate
|
||||
* the handler from those providers. As soon as one provider returns a non-
|
||||
* null instance of the callback handler, the search stops and that instance
|
||||
* is returned.
|
||||
*
|
||||
* @return a {@link CallbackHandler} of the designated type, or
|
||||
* <code>null</code> if no provider was found for theis type of
|
||||
* callback.
|
||||
*/
|
||||
private static final CallbackHandler getHandler(String handlerType)
|
||||
{
|
||||
log.entering(CallbackUtil.class.getName(), "getHandler", handlerType);
|
||||
|
||||
CallbackHandler result = null;
|
||||
String service = "CallbackHandler." + handlerType;
|
||||
Provider[] providers = Security.getProviders(service);
|
||||
if (providers != null)
|
||||
for (int i = 0; i < providers.length; i++)
|
||||
{
|
||||
Provider p = providers[i];
|
||||
String className = p.getProperty(service);
|
||||
if (className != null)
|
||||
try
|
||||
{
|
||||
result = (CallbackHandler) Class.forName(className.trim()).newInstance();
|
||||
}
|
||||
catch (InstantiationException x)
|
||||
{
|
||||
log.fine("InstantiationException while creating ["
|
||||
+ className + "] from provider [" + p.getName()
|
||||
+ "]. Ignore");
|
||||
}
|
||||
catch (IllegalAccessException x)
|
||||
{
|
||||
log.fine("IllegalAccessException while creating ["
|
||||
+ className + "] from provider [" + p.getName()
|
||||
+ "]. Ignore");
|
||||
}
|
||||
catch (ClassNotFoundException x)
|
||||
{
|
||||
log.fine("ClassNotFoundException while creating ["
|
||||
+ className + "] from provider [" + p.getName()
|
||||
+ "]. Ignore");
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
|
||||
log.fine("Will use [" + result.getClass().getName()
|
||||
+ "] from [" + p.getName() + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log.exiting(CallbackUtil.class.getName(), "getHandler", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/* ProviderUtil.java -- Security Provider related utilities
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.common;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A <i>Helper</i> class containing general purpose utlity methods dealing with
|
||||
* installing and removing <i>Security Providers</i> at runtime.
|
||||
*/
|
||||
public abstract class ProviderUtil
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(ProviderUtil.class.getName());
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// Class methods
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Attempt to (a) instantiate, and (b) add a designated {@link Provider} by
|
||||
* inserting at at the top of the list of <i>Security Providers</i> already
|
||||
* present at runtime, only if it is not already installed.
|
||||
* <p>
|
||||
* <b>IMPORTANT</b>: This method overrides the security check usually carried
|
||||
* out by the security manager when inserting a new {@link Provider}.
|
||||
*
|
||||
* @param providerClass a fully qualified, non-null, class name of a
|
||||
* <i>Security Provider</i> to add if it is not already installed.
|
||||
* @return an instance of {@link SecurityProviderInfo} referencing the
|
||||
* {@link Provider} instance created with the designated class name,
|
||||
* and its position in the underlying JVM runtime.
|
||||
*/
|
||||
public static final SecurityProviderInfo addProvider(String providerClass)
|
||||
{
|
||||
log.entering(ProviderUtil.class.getName(), "addProvider", providerClass);
|
||||
|
||||
Provider provider = null;
|
||||
try
|
||||
{
|
||||
provider = (Provider) Class.forName(providerClass.trim()).newInstance();
|
||||
}
|
||||
catch (InstantiationException x)
|
||||
{
|
||||
log.fine("InstantiationException while creating [" + providerClass
|
||||
+ "]. Ignore");
|
||||
}
|
||||
catch (IllegalAccessException x)
|
||||
{
|
||||
log.fine("IllegalAccessException while creating [" + providerClass
|
||||
+ "]. Ignore");
|
||||
}
|
||||
catch (ClassNotFoundException x)
|
||||
{
|
||||
log.fine("ClassNotFoundException while creating [" + providerClass
|
||||
+ "]. Ignore");
|
||||
}
|
||||
|
||||
int position = provider != null ? addProvider(provider) : -1;
|
||||
SecurityProviderInfo result = new SecurityProviderInfo(provider, position);
|
||||
|
||||
log.exiting(ProviderUtil.class.getName(), "addProvider", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to add the designated {@link Provider} by inserting at at the top
|
||||
* of the list of <i>Security Providers</i> already present at runtime, only
|
||||
* if it is not already installed.
|
||||
* <p>
|
||||
* <b>IMPORTANT</b>: This method overrides the security check usually carried
|
||||
* out by the security manager when inserting a new {@link Provider}.
|
||||
*
|
||||
* @param provider a non-null <i>Security Provider</i> to add if it is not
|
||||
* already installed.
|
||||
* @return the new position of the designated provider in the list if it was
|
||||
* not already present, or <code>-1</code> if it was already
|
||||
* installed.
|
||||
*/
|
||||
public static final int addProvider(final Provider provider)
|
||||
{
|
||||
log.entering(ProviderUtil.class.getName(), "addProvider", provider);
|
||||
|
||||
Integer actualPosition = (Integer) AccessController.doPrivileged(new PrivilegedAction()
|
||||
{
|
||||
public Object run()
|
||||
{
|
||||
int result = Security.insertProviderAt(provider, 1);
|
||||
return Integer.valueOf(result);
|
||||
}
|
||||
});
|
||||
|
||||
int result = actualPosition.intValue();
|
||||
log.fine("Provider [" + provider.getName() + "] installed? " + (result != - 1));
|
||||
|
||||
log.exiting(ProviderUtil.class.getName(), "addProvider", actualPosition);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a designated <i>Security Provider</i>.
|
||||
* <p>
|
||||
* <b>IMPORTANT</b>: This method overrides the security check usually carried
|
||||
* out by the security manager when removing a {@link Provider}.
|
||||
*
|
||||
* @param providerName the name of the {@link Provider} to remove.
|
||||
*/
|
||||
public static final void removeProvider(final String providerName)
|
||||
{
|
||||
log.entering(ProviderUtil.class.getName(), "removeProvider", providerName);
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction()
|
||||
{
|
||||
public Object run()
|
||||
{
|
||||
Security.removeProvider(providerName);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
log.exiting(ProviderUtil.class.getName(), "removeProvider");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/* SecurityProviderInfo.java -- Data Access Object for a security provider
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.common;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
/**
|
||||
* A Data Access Object (DAO) referenceing a <i>Security Provider</i> and its
|
||||
* position in the list of installed <i>Security Providers</i> in the underlying
|
||||
* JVM runtime.
|
||||
*/
|
||||
public class SecurityProviderInfo
|
||||
{
|
||||
final private Provider provider;
|
||||
final private int position;
|
||||
private transient String str;
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>SecurityProviderInfo</code>.
|
||||
* <p>
|
||||
* Used by {@link ProviderUtil} to indicate the result of adding a provider,
|
||||
* given its class name.
|
||||
*
|
||||
* @param provider the possibly <code>null</code> {@link Provider}.
|
||||
* @param position the position of <code>provider</code> in the list of
|
||||
* <i>Security Providers</i> in the underlying JVM runtime. <code>-1</code>
|
||||
* if that provider (a) is <code>null</code>, or (b) was not added because it
|
||||
* was already there.
|
||||
*/
|
||||
SecurityProviderInfo(Provider provider, int position)
|
||||
{
|
||||
super();
|
||||
|
||||
this.provider = provider;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/** @return the possibly <code>null</code> {@link Provider} instance. */
|
||||
public Provider getProvider()
|
||||
{
|
||||
return this.provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the position of the {@link Provider}, or <code>-1</code> if it
|
||||
* was not added.
|
||||
*/
|
||||
public int getPosition()
|
||||
{
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (str == null)
|
||||
if (provider == null)
|
||||
str = "SecurityProviderInfo{null, -1}";
|
||||
else
|
||||
str = "SecurityProviderInfo{" + provider.getName() + ", " + position + "}";
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
package gnu.classpath.tools.giop;
|
||||
|
||||
@@ -105,6 +89,10 @@ public class GRMIC
|
||||
verbose = true;
|
||||
compiler.setVerbose(true);
|
||||
}
|
||||
else if (c.equals("-force"))
|
||||
{
|
||||
compiler.setForce(true);
|
||||
}
|
||||
else if (c.equals("-d"))
|
||||
{
|
||||
int f = i + 1;
|
||||
|
||||
@@ -19,6 +19,9 @@ Usage: grmic <options> <class names>
|
||||
-help Print this help text
|
||||
-v Print version
|
||||
-verbose Verbose output
|
||||
-force Try to generate code even if the input classes seem not
|
||||
consistent with RMI specification.
|
||||
|
||||
|
||||
and <class names> can include one or more non abstract classes that implement
|
||||
Remote and are accessible via current class path.
|
||||
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
|
||||
package gnu.classpath.tools.giop;
|
||||
|
||||
@@ -9,7 +9,8 @@ The list of the currently available tools:
|
||||
* GRMIC - RMI-IIOP stub and tie generator.
|
||||
* NameService - GIOP transient naming service (this tool is called
|
||||
tnameserv in Sun's package).
|
||||
* NameService - GIOP persistent naming service (this tool is called
|
||||
* NameServicePersistent
|
||||
- GIOP persistent naming service (this tool is called
|
||||
orbd in Sun's package).
|
||||
* IorParser - Parses the stringified form of the interoperable
|
||||
object references (IOR's).
|
||||
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
package gnu.classpath.tools.giop.grmic;
|
||||
|
||||
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
package gnu.classpath.tools.giop.grmic;
|
||||
|
||||
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
package gnu.classpath.tools.giop.grmic;
|
||||
|
||||
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
package gnu.classpath.tools.giop.grmic;
|
||||
|
||||
@@ -115,6 +99,11 @@ public class GiopRmicCompiler
|
||||
* Verbose output
|
||||
*/
|
||||
protected boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Force mode - do not check the exceptions
|
||||
*/
|
||||
protected boolean force = false;
|
||||
|
||||
/**
|
||||
* Clear data, preparing for the next compilation.
|
||||
@@ -204,7 +193,7 @@ public class GiopRmicCompiler
|
||||
remEx = true;
|
||||
break;
|
||||
}
|
||||
if (! remEx)
|
||||
if (! remEx && !force)
|
||||
throw new CompilationError(m[i].getName() + ", defined in "
|
||||
+ c.getName()
|
||||
+ ", does not throw "
|
||||
@@ -483,6 +472,14 @@ public class GiopRmicCompiler
|
||||
{
|
||||
warnings = warn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error ignore mode.
|
||||
*/
|
||||
public void setForce(boolean isforce)
|
||||
{
|
||||
force = isforce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the package name.
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
/* HashFinder.java -- finds the hash character.
|
||||
Copyright (C) 2006 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
package gnu.classpath.tools.giop.grmic;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
@@ -17,23 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
package gnu.classpath.tools.giop.grmic;
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/* Utils.java -- Utility methods for JAR file signing/verification
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.jarsigner;
|
||||
|
||||
import gnu.java.security.hash.Sha160;
|
||||
import gnu.java.security.util.Base64;
|
||||
import gnu.java.util.jar.JarUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Collection of utility methods used in JAR file signing and verification.
|
||||
*/
|
||||
class HashUtils
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(HashUtils.class.getName());
|
||||
private Sha160 sha = new Sha160();
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
/**
|
||||
* @param stream the input stream to digest.
|
||||
* @return a base-64 representation of the resulting SHA-1 digest of the
|
||||
* contents of the designated input stream.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
*/
|
||||
String hashStream(InputStream stream) throws IOException
|
||||
{
|
||||
BufferedInputStream bis = new BufferedInputStream(stream, 4096);
|
||||
byte[] buffer = new byte[4096];
|
||||
int count = 0;
|
||||
int n;
|
||||
while ((n = bis.read(buffer)) != - 1)
|
||||
if (n > 0)
|
||||
{
|
||||
sha.update(buffer, 0, n);
|
||||
count += n;
|
||||
}
|
||||
|
||||
byte[] hash = sha.digest();
|
||||
log.finest("Hashed " + count + " byte(s)");
|
||||
String result = Base64.encode(hash);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ba the byte array to digest.
|
||||
* @return a base-64 representation of the resulting SHA-1 digest of the
|
||||
* contents of the designated buffer.
|
||||
*/
|
||||
String hashByteArray(byte[] ba) throws IOException
|
||||
{
|
||||
sha.update(ba);
|
||||
byte[] hash = sha.digest();
|
||||
log.finest("Hashed " + ba.length + " byte(s)");
|
||||
String result = Base64.encode(hash);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the JAR entry name
|
||||
* @param entryHash the hash of the entry file which appears in the
|
||||
* manifest.
|
||||
* @return the base-64 encoded form of the hash of the corresponding Manifest
|
||||
* JAR entry which will appear in the SF file under the entry with the
|
||||
* same name.
|
||||
* @throws UnsupportedEncodingException If UTF-8 character encoding is not
|
||||
* supported on this platform.
|
||||
*/
|
||||
String hashManifestEntry(String name, String entryHash)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
sha.update((JarUtils.NAME + ": " + name).getBytes("UTF-8"));
|
||||
sha.update(JarUtils.CRLF);
|
||||
sha.update((Main.DIGEST + ": " + entryHash).getBytes("UTF-8"));
|
||||
sha.update(JarUtils.CRLF);
|
||||
sha.update(JarUtils.CRLF);
|
||||
byte[] sfHash = sha.digest();
|
||||
String result = Base64.encode(sfHash);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* JarSigner.java -- The signing handler of the gjarsigner tool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.jarsigner;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
import gnu.java.util.jar.JarUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The JAR signing handler of the <code>gjarsigner</code> tool.
|
||||
*/
|
||||
public class JarSigner
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(JarSigner.class.getName());
|
||||
/** The owner tool of this handler. */
|
||||
private Main main;
|
||||
|
||||
JarSigner(Main main)
|
||||
{
|
||||
super();
|
||||
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
void start() throws Exception
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
JarFile jarFile = new JarFile(main.getJarFileName());
|
||||
SFHelper sfHelper = new SFHelper(jarFile);
|
||||
|
||||
sfHelper.startSigning();
|
||||
|
||||
// 1. compute the digests
|
||||
for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
|
||||
{
|
||||
JarEntry je = (JarEntry) e.nextElement();
|
||||
String jeName = je.getName();
|
||||
if (jeName.equals(JarFile.MANIFEST_NAME)
|
||||
|| jeName.endsWith(File.separator))
|
||||
continue;
|
||||
|
||||
sfHelper.updateEntry(je);
|
||||
if (main.isVerbose())
|
||||
System.out.println(Messages.getString("JarSigner.1") + jeName); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
sfHelper.finishSigning(main.isSectionsOnly());
|
||||
if (main.isVerbose())
|
||||
System.out.println(Messages.getString("JarSigner.2") + JarFile.MANIFEST_NAME); //$NON-NLS-1$
|
||||
|
||||
// 2. write jar entries and manifest
|
||||
File signedJarFile = File.createTempFile("gcp-", ".jar"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
FileOutputStream fos = new FileOutputStream(signedJarFile);
|
||||
JarOutputStream outSignedJarFile = new JarOutputStream(fos,
|
||||
sfHelper.getManifest());
|
||||
for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
|
||||
{
|
||||
JarEntry je = (JarEntry) e.nextElement();
|
||||
String jeName = je.getName();
|
||||
if (jeName.equals(JarFile.MANIFEST_NAME)
|
||||
|| jeName.endsWith(File.separator))
|
||||
continue;
|
||||
|
||||
log.finest("Processing " + jeName); //$NON-NLS-1$
|
||||
JarEntry newEntry = new JarEntry(jeName);
|
||||
newEntry.setTime(je.getTime());
|
||||
outSignedJarFile.putNextEntry(newEntry);
|
||||
InputStream jeis = jarFile.getInputStream(je);
|
||||
copyFromTo(jeis, outSignedJarFile);
|
||||
}
|
||||
|
||||
// 3. create the .SF file
|
||||
String signaturesFileName = main.getSigFileName();
|
||||
String sfFileName = JarUtils.META_INF + signaturesFileName
|
||||
+ JarUtils.SF_SUFFIX;
|
||||
log.finest("Processing " + sfFileName); //$NON-NLS-1$
|
||||
JarEntry sfEntry = new JarEntry(sfFileName);
|
||||
sfEntry.setTime(System.currentTimeMillis());
|
||||
outSignedJarFile.putNextEntry(sfEntry);
|
||||
sfHelper.writeSF(outSignedJarFile);
|
||||
log.finer("Created .SF file"); //$NON-NLS-1$
|
||||
if (main.isVerbose())
|
||||
System.out.println(Messages.getString("JarSigner.8") + sfFileName); //$NON-NLS-1$
|
||||
|
||||
// 4. create the .DSA file
|
||||
String dsaFileName = JarUtils.META_INF + signaturesFileName
|
||||
+ JarUtils.DSA_SUFFIX;
|
||||
log.finest("Processing " + dsaFileName); //$NON-NLS-1$
|
||||
JarEntry dsaEntry = new JarEntry(dsaFileName);
|
||||
dsaEntry.setTime(System.currentTimeMillis());
|
||||
outSignedJarFile.putNextEntry(dsaEntry);
|
||||
sfHelper.writeDSA(outSignedJarFile,
|
||||
main.getSignerPrivateKey(),
|
||||
main.getSignerCertificateChain(),
|
||||
main.isInternalSF());
|
||||
log.finer("Created .DSA file"); //$NON-NLS-1$
|
||||
if (main.isVerbose())
|
||||
System.out.println(Messages.getString("JarSigner.11") + dsaFileName); //$NON-NLS-1$
|
||||
|
||||
// cleanup
|
||||
outSignedJarFile.close();
|
||||
fos.close();
|
||||
signedJarFile.renameTo(new File(main.getSignedJarFileName()));
|
||||
log.finer("Renamed signed JAR file"); //$NON-NLS-1$
|
||||
if (main.isVerbose())
|
||||
System.out.println(SystemProperties.getProperty("line.separator") //$NON-NLS-1$
|
||||
+ Messages.getString("JarSigner.14")); //$NON-NLS-1$
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private void copyFromTo(InputStream in, JarOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[8192];
|
||||
int n;
|
||||
while ((n = in.read(buffer)) != -1)
|
||||
if (n > 0)
|
||||
out.write(buffer, 0, n);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/* JarVerifier.java -- The verification handler of the gjarsigner tool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.jarsigner;
|
||||
|
||||
import gnu.java.security.OID;
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.pkcs.PKCS7SignedData;
|
||||
import gnu.java.security.pkcs.SignerInfo;
|
||||
import gnu.java.security.sig.ISignature;
|
||||
import gnu.java.security.sig.ISignatureCodec;
|
||||
import gnu.java.security.sig.dss.DSSSignature;
|
||||
import gnu.java.security.sig.dss.DSSSignatureX509Codec;
|
||||
import gnu.java.security.sig.rsa.RSAPKCS1V1_5Signature;
|
||||
import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
|
||||
import gnu.java.security.util.Util;
|
||||
import gnu.java.util.jar.JarUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CRLException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
/**
|
||||
* The JAR verification handler of the <code>gjarsigner</code> tool.
|
||||
*/
|
||||
public class JarVerifier
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(JarVerifier.class.getName());
|
||||
/** The owner tool of this handler. */
|
||||
private Main main;
|
||||
private HashUtils util = new HashUtils();
|
||||
/** The JAR file to verify. */
|
||||
private JarFile jarFile;
|
||||
/** Map of jar entry names to their hash. */
|
||||
private Map entryHashes = new HashMap();
|
||||
|
||||
JarVerifier(Main main)
|
||||
{
|
||||
super();
|
||||
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
void start() throws Exception
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
String jarFileName = main.getJarFileName();
|
||||
jarFile = new JarFile(jarFileName);
|
||||
|
||||
// 1. find all signature (.SF) files
|
||||
List sfFiles = new ArrayList();
|
||||
for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
|
||||
{
|
||||
JarEntry je = (JarEntry) e.nextElement();
|
||||
String jeName = je.getName();
|
||||
if (! (jeName.startsWith(JarUtils.META_INF)
|
||||
&& jeName.endsWith(JarUtils.SF_SUFFIX)))
|
||||
continue;
|
||||
|
||||
// only interested in .SF files in, and not deeper than, META-INF
|
||||
String[] jeNameParts = jeName.split("/"); //$NON-NLS-1$
|
||||
if (jeNameParts.length != 2)
|
||||
continue;
|
||||
|
||||
String sfName = jeNameParts[1];
|
||||
String sigFileName = sfName.substring(0, sfName.length() - 3);
|
||||
sfFiles.add(sigFileName);
|
||||
}
|
||||
|
||||
// 2. verify each one
|
||||
if (sfFiles.isEmpty())
|
||||
System.out.println(Messages.getString("JarVerifier.2")); //$NON-NLS-1$
|
||||
else
|
||||
{
|
||||
int limit = sfFiles.size();
|
||||
int count = 0;
|
||||
for (Iterator it = sfFiles.iterator(); it.hasNext(); )
|
||||
{
|
||||
String alias = (String) it.next();
|
||||
if (verifySF(alias))
|
||||
if (verifySFEntries(alias))
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
System.out.println(Messages.getString("JarVerifier.3")); //$NON-NLS-1$
|
||||
else if (count != limit)
|
||||
System.out.println(Messages.getFormattedString("JarVerifier.4", //$NON-NLS-1$
|
||||
new Integer[] {Integer.valueOf(count),
|
||||
Integer.valueOf(limit)}));
|
||||
else
|
||||
System.out.println(Messages.getFormattedString("JarVerifier.7", //$NON-NLS-1$
|
||||
Integer.valueOf(limit)));
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sigFileName the name of the signature file; i.e. the name to use for
|
||||
* both the .SF and .DSA files.
|
||||
* @return <code>true</code> if the designated file-name (usually a key-store
|
||||
* <i>alias</i> name) has been successfully checked as the signer of the
|
||||
* corresponding <code>.SF</code> file. Returns <code>false</code> otherwise.
|
||||
* @throws IOException
|
||||
* @throws ZipException
|
||||
* @throws CertificateException
|
||||
* @throws CRLException
|
||||
*/
|
||||
private boolean verifySF(String sigFileName) throws CRLException,
|
||||
CertificateException, ZipException, IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "verifySF"); //$NON-NLS-1$
|
||||
log.finest("About to verify signature of " + sigFileName + "..."); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
// 1. find the corresponding .DSA file for this .SF file
|
||||
JarEntry dsaEntry = jarFile.getJarEntry(JarUtils.META_INF + sigFileName
|
||||
+ JarUtils.DSA_SUFFIX);
|
||||
if (dsaEntry == null)
|
||||
throw new SecurityException(Messages.getFormattedString("JarVerifier.13", //$NON-NLS-1$
|
||||
sigFileName));
|
||||
// 2. read the .DSA file contents as a PKCS7 SignedData
|
||||
InputStream in = jarFile.getInputStream(dsaEntry);
|
||||
PKCS7SignedData pkcs7SignedData = new PKCS7SignedData(in);
|
||||
|
||||
// 4. get the encrypted digest octet string from the first SignerInfo
|
||||
// this octet string is the digital signature of the .SF file contents
|
||||
Set signerInfos = pkcs7SignedData.getSignerInfos();
|
||||
if (signerInfos == null || signerInfos.isEmpty())
|
||||
throw new SecurityException(Messages.getString("JarVerifier.14")); //$NON-NLS-1$
|
||||
|
||||
SignerInfo signerInfo = (SignerInfo) signerInfos.iterator().next();
|
||||
byte[] encryptedDigest = signerInfo.getEncryptedDigest();
|
||||
if (encryptedDigest == null)
|
||||
throw new SecurityException(Messages.getString("JarVerifier.16")); //$NON-NLS-1$
|
||||
|
||||
log.finest("\n" + Util.dumpString(encryptedDigest, "--- signedSFBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
// 5. get the signer public key
|
||||
Certificate cert = pkcs7SignedData.getCertificates()[0];
|
||||
PublicKey verifierKey = cert.getPublicKey();
|
||||
log.finest("--- verifier public key = " + verifierKey); //$NON-NLS-1$
|
||||
|
||||
// 6. verify the signature file signature
|
||||
OID digestEncryptionAlgorithmOID = signerInfo.getDigestEncryptionAlgorithmId();
|
||||
ISignature signatureAlgorithm;
|
||||
ISignatureCodec signatureCodec;
|
||||
if (digestEncryptionAlgorithmOID.equals(Main.DSA_SIGNATURE_OID))
|
||||
{
|
||||
signatureAlgorithm = new DSSSignature();
|
||||
signatureCodec = new DSSSignatureX509Codec();
|
||||
}
|
||||
else
|
||||
{
|
||||
signatureAlgorithm = new RSAPKCS1V1_5Signature(Registry.MD5_HASH);
|
||||
signatureCodec = new RSAPKCS1V1_5SignatureX509Codec();
|
||||
}
|
||||
|
||||
Map signatureAttributes = new HashMap();
|
||||
signatureAttributes.put(ISignature.VERIFIER_KEY, verifierKey);
|
||||
signatureAlgorithm.setupVerify(signatureAttributes);
|
||||
|
||||
Object herSignature = signatureCodec.decodeSignature(encryptedDigest);
|
||||
|
||||
// 7. verify the signature file contents
|
||||
JarEntry sfEntry = jarFile.getJarEntry(JarUtils.META_INF + sigFileName
|
||||
+ JarUtils.SF_SUFFIX);
|
||||
in = jarFile.getInputStream(sfEntry);
|
||||
byte[] buffer = new byte[2048];
|
||||
int n;
|
||||
while ((n = in.read(buffer)) != -1)
|
||||
if (n > 0)
|
||||
signatureAlgorithm.update(buffer, 0, n);
|
||||
|
||||
boolean result = signatureAlgorithm.verify(herSignature);
|
||||
log.finer("Signature block [" + sigFileName + "] is " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ (result ? "" : "NOT ") + "OK"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
|
||||
log.exiting(this.getClass().getName(), "verifySF", Boolean.valueOf(result)); //$NON-NLS-1$
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called after at least one signer (usually a key-store
|
||||
* <code>alias</code> name) was found to be trusted; i.e. his/her signature
|
||||
* block in the corresponding <code>.DSA</code> file was successfully
|
||||
* verified using his/her public key.
|
||||
* <p>
|
||||
* This method, uses the contents of the corresponding <code>.SF</code> file
|
||||
* to compute and verify the hashes of the manifest entries in the JAR file.
|
||||
*
|
||||
* @param alias the name of the signature file; i.e. the name to use for both
|
||||
* the .SF and .DSA files.
|
||||
* @return <code>true</code> if all the entries in the corresponding
|
||||
* <code>.SF</code> file have the same hash values as their
|
||||
* alter-ego in the <i>manifest</i> file of the JAR file inquestion.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
*/
|
||||
private boolean verifySFEntries(String alias) throws IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "verifySFEntries"); //$NON-NLS-1$
|
||||
|
||||
// 1. read the signature file
|
||||
JarEntry jarEntry = jarFile.getJarEntry(JarUtils.META_INF + alias
|
||||
+ JarUtils.SF_SUFFIX);
|
||||
InputStream in = jarFile.getInputStream(jarEntry);
|
||||
Attributes attr = new Attributes();
|
||||
Map entries = new HashMap();
|
||||
JarUtils.readSFManifest(attr, entries, in);
|
||||
|
||||
// 2. The .SF file by default includes a header containing a hash of the
|
||||
// entire manifest file. When the header is present, then the verification
|
||||
// can check to see whether or not the hash in the header indeed matches
|
||||
// the hash of the manifest file.
|
||||
boolean result = false;
|
||||
String hash = attr.getValue(Main.DIGEST_MANIFEST_ATTR);
|
||||
if (hash != null)
|
||||
result = verifyManifest(hash);
|
||||
|
||||
// A verification is still considered successful if none of the files that
|
||||
// were in the JAR file when the signature was generated have been changed
|
||||
// since then, which is the case if the hashes in the non-header sections
|
||||
// of the .SF file equal the hashes of the corresponding sections in the
|
||||
// manifest file.
|
||||
//
|
||||
// 3. Read each file in the JAR file that has an entry in the .SF file.
|
||||
// While reading, compute the file's digest, and then compare the result
|
||||
// with the digest for this file in the manifest section. The digests
|
||||
// should be the same, or verification fails.
|
||||
if (! result)
|
||||
for (Iterator it = entries.keySet().iterator(); it.hasNext();)
|
||||
{
|
||||
Entry me = (Entry) it.next();
|
||||
String name = (String) me.getKey();
|
||||
attr = (Attributes) me.getValue();
|
||||
hash = attr.getValue(Main.DIGEST_ATTR);
|
||||
result = verifySFEntry(name, hash);
|
||||
if (! result)
|
||||
break;
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "verifySFEntries",
|
||||
Boolean.valueOf(result)); //$NON-NLS-1$
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hash Base-64 encoded form of the manifest's digest.
|
||||
* @return <code>true</code> if our computation of the manifest's hash
|
||||
* matches the given value; <code>false</code> otherwise.
|
||||
* @throws IOException if unable to acquire the JAR's manifest entry.
|
||||
*/
|
||||
private boolean verifyManifest(String hash) throws IOException
|
||||
{
|
||||
return verifySFEntry(JarFile.MANIFEST_NAME, hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name of a JAR entry to verify.
|
||||
* @param hash Base-64 encoded form of the designated entry's digest.
|
||||
* @return <code>true</code> if our computation of the JAR entry's hash
|
||||
* matches the given value; <code>false</code> otherwise.
|
||||
* @throws IOException if an exception occurs while returning the entry's
|
||||
* input stream.
|
||||
*/
|
||||
private boolean verifySFEntry(String name, String hash) throws IOException
|
||||
{
|
||||
String expectedValue = getEntryHash(JarFile.MANIFEST_NAME);
|
||||
boolean result = expectedValue.equalsIgnoreCase(hash);
|
||||
log.finest("Is " + name + " OK? " + result); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getEntryHash(String entryName) throws IOException
|
||||
{
|
||||
String result = (String) entryHashes.get(entryName);
|
||||
if (result == null)
|
||||
{
|
||||
JarEntry manifest = jarFile.getJarEntry(entryName);
|
||||
InputStream in = jarFile.getInputStream(manifest);
|
||||
result = util.hashStream(in);
|
||||
entryHashes.put(entryName, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
/* Main.java -- JAR signing and verification tool not unlike jarsigner
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.jarsigner;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
import gnu.classpath.tools.HelpPrinter;
|
||||
import gnu.classpath.tools.common.CallbackUtil;
|
||||
import gnu.classpath.tools.common.ProviderUtil;
|
||||
import gnu.java.security.OID;
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.javax.security.auth.callback.ConsoleCallbackHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Locale;
|
||||
import java.util.jar.Attributes.Name;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The GNU Classpath implementation of the <i>jarsigner</i> tool.
|
||||
* <p>
|
||||
* The <i>jarsigner</i> tool is used to sign and verify JAR (Java ARchive)
|
||||
* files.
|
||||
* <p>
|
||||
* This implementation is intended to be compatible with the behaviour
|
||||
* described in the public documentation of the same tool included in JDK 1.4.
|
||||
*/
|
||||
public class Main
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(Main.class.getName());
|
||||
private static final String HELP_PATH = "jarsigner/jarsigner.txt"; //$NON-NLS-1$
|
||||
private static final Locale EN_US_LOCALE = new Locale("en", "US"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
static final String DIGEST = "SHA1-Digest"; //$NON-NLS-1$
|
||||
static final String DIGEST_MANIFEST = "SHA1-Digest-Manifest"; //$NON-NLS-1$
|
||||
static final Name DIGEST_ATTR = new Name(DIGEST);
|
||||
static final Name DIGEST_MANIFEST_ATTR = new Name(DIGEST_MANIFEST);
|
||||
static final OID DSA_SIGNATURE_OID = new OID(Registry.DSA_OID_STRING);
|
||||
static final OID RSA_SIGNATURE_OID = new OID(Registry.RSA_OID_STRING);
|
||||
|
||||
private boolean verify;
|
||||
private String ksURL;
|
||||
private String ksType;
|
||||
private String password;
|
||||
private String ksPassword;
|
||||
private String sigFileName;
|
||||
private String signedJarFileName;
|
||||
private boolean verbose;
|
||||
private boolean certs;
|
||||
private boolean internalSF;
|
||||
private boolean sectionsOnly;
|
||||
private String providerClassName;
|
||||
private String jarFileName;
|
||||
private String alias;
|
||||
|
||||
protected Provider provider;
|
||||
private boolean providerInstalled;
|
||||
private char[] ksPasswordChars;
|
||||
private KeyStore store;
|
||||
private char[] passwordChars;
|
||||
private PrivateKey signerPrivateKey;
|
||||
private Certificate[] signerCertificateChain;
|
||||
/** The callback handler to use when needing to interact with user. */
|
||||
private CallbackHandler handler;
|
||||
|
||||
private Main()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public static final void main(String[] args)
|
||||
{
|
||||
log.entering(Main.class.getName(), "main", args); //$NON-NLS-1$
|
||||
|
||||
Main tool = new Main();
|
||||
try
|
||||
{
|
||||
tool.processArgs(args);
|
||||
tool.start();
|
||||
}
|
||||
catch (SecurityException x)
|
||||
{
|
||||
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
|
||||
System.err.println(Messages.getString("Main.7") + x.getMessage()); //$NON-NLS-1$
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
|
||||
System.err.println(Messages.getString("Main.9") + x); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
tool.teardown();
|
||||
|
||||
log.exiting(Main.class.getName(), "main"); //$NON-NLS-1$
|
||||
// System.exit(0);
|
||||
}
|
||||
|
||||
// helper methods -----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Read the command line arguments setting the tool's parameters in
|
||||
* preparation for the user desired action.
|
||||
*
|
||||
* @param args an array of options (strings).
|
||||
* @throws Exception if an exceptio occurs during the process.
|
||||
*/
|
||||
private void processArgs(String[] args) throws Exception
|
||||
{
|
||||
log.entering(this.getClass().getName(), "processArgs", args); //$NON-NLS-1$
|
||||
|
||||
HelpPrinter.checkHelpKey(args, HELP_PATH);
|
||||
if (args == null || args.length == 0)
|
||||
HelpPrinter.printHelpAndExit(HELP_PATH);
|
||||
|
||||
int limit = args.length;
|
||||
log.finest("args.length=" + limit); //$NON-NLS-1$
|
||||
int i = 0;
|
||||
String opt;
|
||||
while (i < limit)
|
||||
{
|
||||
opt = args[i++];
|
||||
log.finest("args[" + (i - 1) + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-verify".equals(opt)) // -verify //$NON-NLS-1$
|
||||
verify = true;
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
ksURL = args[i++];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
ksType = args[i++];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
ksPassword = args[i++];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
|
||||
password = args[i++];
|
||||
else if ("-sigfile".equals(opt)) // -sigfile NAME //$NON-NLS-1$
|
||||
sigFileName = args[i++];
|
||||
else if ("-signedjar".equals(opt)) // -signedjar FILE_NAME //$NON-NLS-1$
|
||||
signedJarFileName = args[i++];
|
||||
else if ("-verbose".equals(opt)) // -verbose //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else if ("-certs".equals(opt)) // -certs //$NON-NLS-1$
|
||||
certs = true;
|
||||
else if ("-internalsf".equals(opt)) // -internalsf //$NON-NLS-1$
|
||||
internalSF = true;
|
||||
else if ("-sectionsonly".equals(opt)) // -sectionsonly //$NON-NLS-1$
|
||||
sectionsOnly = true;
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
providerClassName = args[i++];
|
||||
else
|
||||
{
|
||||
jarFileName = opt;
|
||||
if (! verify)
|
||||
alias = args[i++];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < limit) // more options than needed
|
||||
log.fine("Last argument is assumed at index #" + (i - 1) //$NON-NLS-1$
|
||||
+ ". Remaining arguments (" + args[i] //$NON-NLS-1$
|
||||
+ "...) will be ignored"); //$NON-NLS-1$
|
||||
|
||||
setupCommonParams();
|
||||
if (verify)
|
||||
{
|
||||
log.finer("Will verify with the following parameters:"); //$NON-NLS-1$
|
||||
log.finer(" jar-file = '" + jarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer("Options:"); //$NON-NLS-1$
|
||||
log.finer(" provider = '" + providerClassName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" verbose ? " + verbose); //$NON-NLS-1$
|
||||
log.finer(" certs ? " + certs); //$NON-NLS-1$
|
||||
log.finer(" internalsf ? " + internalSF); //$NON-NLS-1$
|
||||
log.finer(" sectionsonly ? " + sectionsOnly); //$NON-NLS-1$
|
||||
}
|
||||
else // sign
|
||||
{
|
||||
setupSigningParams();
|
||||
|
||||
log.finer("Will sign with the following parameters:"); //$NON-NLS-1$
|
||||
log.finer(" jar-file = '" + jarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" alias = '" + alias + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer("Options:"); //$NON-NLS-1$
|
||||
log.finer(" keystore = '" + ksURL + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" storetype = '" + ksType + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" storepass = '" + ksPassword + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" keypass = '" + password + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" sigfile = '" + sigFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" signedjar = '" + signedJarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" provider = '" + providerClassName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.finer(" verbose ? " + verbose); //$NON-NLS-1$
|
||||
log.finer(" internalsf ? " + internalSF); //$NON-NLS-1$
|
||||
log.finer(" sectionsonly ? " + sectionsOnly); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "processArgs"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the <code>start()</code> method of the concrete handler.
|
||||
* <p>
|
||||
* Depending on the result of processing the command line arguments, this
|
||||
* handler may be one for signing the jar, or verifying it.
|
||||
*
|
||||
* @throws Exception if an exception occurs during the process.
|
||||
*/
|
||||
private void start() throws Exception
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
if (verify)
|
||||
{
|
||||
JarVerifier jv = new JarVerifier(this);
|
||||
jv.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
JarSigner js = new JarSigner(this);
|
||||
js.start();
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the underlying JVM is left in the same state as we found it
|
||||
* when we first launched the tool. Specifically, if we have installed a new
|
||||
* security provider then now is the time to remove it.
|
||||
* <p>
|
||||
* Note (rsn): this may not be necessary if we terminate the JVM; i.e. call
|
||||
* {@link System#exit(int)} at the end of the tool's invocation. Nevertheless
|
||||
* it's good practive to return the JVM to its initial state.
|
||||
*/
|
||||
private void teardown()
|
||||
{
|
||||
log.entering(this.getClass().getName(), "teardown"); //$NON-NLS-1$
|
||||
|
||||
if (providerInstalled)
|
||||
ProviderUtil.removeProvider(provider.getName());
|
||||
|
||||
log.exiting(this.getClass().getName(), "teardown"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* After processing the command line arguments, this method is invoked to
|
||||
* process the common parameters which may have been encountered among the
|
||||
* actual arguments.
|
||||
* <p>
|
||||
* Common parameters are those which are allowed in both signing and
|
||||
* verification modes.
|
||||
*
|
||||
* @throws InstantiationException if a security provider class name is
|
||||
* specified but that class name is that of either an interface or
|
||||
* an abstract class.
|
||||
* @throws IllegalAccessException if a security provider class name is
|
||||
* specified but no 0-arguments constructor is defined for that
|
||||
* class.
|
||||
* @throws ClassNotFoundException if a security provider class name is
|
||||
* specified but no such class was found in the classpath.
|
||||
* @throws IOException if the JAR file name for signing, or verifying, does
|
||||
* not exist, exists but denotes a directory, or is not readable.
|
||||
*/
|
||||
private void setupCommonParams() throws InstantiationException,
|
||||
IllegalAccessException, ClassNotFoundException, IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "setupCommonParams"); //$NON-NLS-1$
|
||||
|
||||
if (jarFileName == null)
|
||||
HelpPrinter.printHelpAndExit(HELP_PATH);
|
||||
|
||||
File jar = new File(jarFileName);
|
||||
if (! jar.exists())
|
||||
throw new FileNotFoundException(jarFileName);
|
||||
|
||||
if (jar.isDirectory())
|
||||
throw new IOException(Messages.getFormattedString("Main.70", jarFileName)); //$NON-NLS-1$
|
||||
|
||||
if (! jar.canRead())
|
||||
throw new IOException(Messages.getFormattedString("Main.72", jarFileName)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
if (providerClassName != null && providerClassName.length() > 0)
|
||||
{
|
||||
provider = (Provider) Class.forName(providerClassName).newInstance();
|
||||
// is it already installed?
|
||||
String providerName = provider.getName();
|
||||
Provider installedProvider = Security.getProvider(providerName);
|
||||
if (installedProvider != null)
|
||||
log.finer("Provider " + providerName + " is already installed"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
else // install it
|
||||
installNewProvider();
|
||||
}
|
||||
|
||||
if (! verbose && certs)
|
||||
{
|
||||
log.fine("Option <certs> is set but <verbose> is not. Ignored"); //$NON-NLS-1$
|
||||
certs = false;
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "setupCommonParams"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the user defined security provider in the underlying JVM.
|
||||
* <p>
|
||||
* Also record this fact so we can remove it when we exit the tool.
|
||||
*/
|
||||
private void installNewProvider()
|
||||
{
|
||||
log.entering(this.getClass().getName(), "installNewProvider"); //$NON-NLS-1$
|
||||
|
||||
providerInstalled = ProviderUtil.addProvider(provider) != -1;
|
||||
|
||||
log.exiting(this.getClass().getName(), "installNewProvider"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* After processing the command line arguments, this method is invoked to
|
||||
* process the parameters which may have been encountered among the actual
|
||||
* arguments, and which are specific to the signing action of the tool.
|
||||
*
|
||||
* @throws KeyStoreException if no implementation of the designated (or
|
||||
* default type) of a key store is availabe.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
* @throws NoSuchAlgorithmException if an implementation of an algorithm used
|
||||
* by the key store is not available.
|
||||
* @throws CertificateException if an exception occurs while reading a
|
||||
* certificate from the key store.
|
||||
* @throws UnsupportedCallbackException if no implementation of a password
|
||||
* callback is available.
|
||||
* @throws UnrecoverableKeyException if the wrong password was used to unlock
|
||||
* the key store.
|
||||
* @throws SecurityException if the designated alias is not known to the key
|
||||
* store or is not an Alias of a Key Entry.
|
||||
*/
|
||||
private void setupSigningParams() throws KeyStoreException, IOException,
|
||||
NoSuchAlgorithmException, CertificateException,
|
||||
UnsupportedCallbackException, UnrecoverableKeyException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "setupSigningParams"); //$NON-NLS-1$
|
||||
|
||||
if (ksURL == null || ksURL.trim().length() == 0)
|
||||
{
|
||||
String userHome = SystemProperties.getProperty("user.home"); //$NON-NLS-1$
|
||||
if (userHome == null || userHome.trim().length() == 0)
|
||||
throw new SecurityException(Messages.getString("Main.85")); //$NON-NLS-1$
|
||||
|
||||
ksURL = "file:" + userHome.trim() + "/.keystore"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
else
|
||||
{
|
||||
ksURL = ksURL.trim();
|
||||
if (ksURL.indexOf(":") == -1) //$NON-NLS-1$
|
||||
ksURL = "file:" + ksURL; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (ksType == null || ksType.trim().length() == 0)
|
||||
ksType = KeyStore.getDefaultType();
|
||||
else
|
||||
ksType = ksType.trim();
|
||||
|
||||
store = KeyStore.getInstance(ksType);
|
||||
|
||||
if (ksPassword == null)
|
||||
{
|
||||
// ask the user to provide one
|
||||
PasswordCallback pcb = new PasswordCallback(Messages.getString("Main.92"), //$NON-NLS-1$
|
||||
false);
|
||||
getCallbackHandler().handle(new Callback[] { pcb });
|
||||
ksPasswordChars = pcb.getPassword();
|
||||
}
|
||||
else
|
||||
ksPasswordChars = ksPassword.toCharArray();
|
||||
|
||||
URL url = new URL(ksURL);
|
||||
InputStream stream = url.openStream();
|
||||
store.load(stream, ksPasswordChars);
|
||||
|
||||
if (alias == null)
|
||||
HelpPrinter.printHelpAndExit(HELP_PATH);
|
||||
|
||||
if (! store.containsAlias(alias))
|
||||
throw new SecurityException(Messages.getFormattedString("Main.6", alias)); //$NON-NLS-1$
|
||||
|
||||
if (! store.isKeyEntry(alias))
|
||||
throw new SecurityException(Messages.getFormattedString("Main.95", alias)); //$NON-NLS-1$
|
||||
|
||||
Key key;
|
||||
if (password == null)
|
||||
{
|
||||
passwordChars = ksPasswordChars;
|
||||
try
|
||||
{
|
||||
key = store.getKey(alias, passwordChars);
|
||||
}
|
||||
catch (UnrecoverableKeyException x)
|
||||
{
|
||||
// ask the user to provide one
|
||||
String prompt = Messages.getFormattedString("Main.97", alias); //$NON-NLS-1$
|
||||
PasswordCallback pcb = new PasswordCallback(prompt, false);
|
||||
getCallbackHandler().handle(new Callback[] { pcb });
|
||||
passwordChars = pcb.getPassword();
|
||||
// take 2
|
||||
key = store.getKey(alias, passwordChars);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
passwordChars = password.toCharArray();
|
||||
key = store.getKey(alias, passwordChars);
|
||||
}
|
||||
|
||||
if (! (key instanceof PrivateKey))
|
||||
throw new SecurityException(Messages.getFormattedString("Main.99", alias)); //$NON-NLS-1$
|
||||
|
||||
signerPrivateKey = (PrivateKey) key;
|
||||
signerCertificateChain = store.getCertificateChain(alias);
|
||||
log.finest(String.valueOf(signerCertificateChain));
|
||||
|
||||
if (sigFileName == null)
|
||||
sigFileName = alias;
|
||||
|
||||
sigFileName = sigFileName.toUpperCase(EN_US_LOCALE);
|
||||
if (sigFileName.length() > 8)
|
||||
sigFileName = sigFileName.substring(0, 8);
|
||||
|
||||
char[] chars = sigFileName.toCharArray();
|
||||
for (int i = 0; i < chars.length; i++)
|
||||
{
|
||||
char c = chars[i];
|
||||
if (! (Character.isLetter(c)
|
||||
|| Character.isDigit(c)
|
||||
|| c == '_'
|
||||
|| c == '-'))
|
||||
chars[i] = '_';
|
||||
}
|
||||
|
||||
sigFileName = new String(chars);
|
||||
|
||||
if (signedJarFileName == null)
|
||||
signedJarFileName = jarFileName;
|
||||
|
||||
log.exiting(this.getClass().getName(), "setupSigningParams"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
boolean isVerbose()
|
||||
{
|
||||
return verbose;
|
||||
}
|
||||
|
||||
boolean isCerts()
|
||||
{
|
||||
return certs;
|
||||
}
|
||||
|
||||
String getSigFileName()
|
||||
{
|
||||
return this.sigFileName;
|
||||
}
|
||||
|
||||
String getJarFileName()
|
||||
{
|
||||
return this.jarFileName;
|
||||
}
|
||||
|
||||
boolean isSectionsOnly()
|
||||
{
|
||||
return this.sectionsOnly;
|
||||
}
|
||||
|
||||
boolean isInternalSF()
|
||||
{
|
||||
return this.internalSF;
|
||||
}
|
||||
|
||||
PrivateKey getSignerPrivateKey()
|
||||
{
|
||||
return this.signerPrivateKey;
|
||||
}
|
||||
|
||||
Certificate[] getSignerCertificateChain()
|
||||
{
|
||||
return signerCertificateChain;
|
||||
}
|
||||
|
||||
String getSignedJarFileName()
|
||||
{
|
||||
return this.signedJarFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a CallbackHandler which uses the Console (System.in and System.out)
|
||||
* for interacting with the user.
|
||||
* <p>
|
||||
* This method first finds all currently installed security providers capable
|
||||
* of providing such service and then in turn attempts to instantiate the
|
||||
* handler from those providers. As soon as one provider returns a non-null
|
||||
* instance of the callback handler, the search stops and that instance is
|
||||
* set to be used from now on.
|
||||
* <p>
|
||||
* If no installed providers were found, this method falls back on the GNU
|
||||
* provider, by-passing the Security search mechanism. The default console
|
||||
* callback handler implementation is {@link ConsoleCallbackHandler}.
|
||||
*
|
||||
* @return a console-based {@link CallbackHandler}.
|
||||
*/
|
||||
protected CallbackHandler getCallbackHandler()
|
||||
{
|
||||
if (handler == null)
|
||||
handler = CallbackUtil.getConsoleHandler();
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* Messages.java -- I18N related helper class
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.jarsigner;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* An initially generated Eclipse helper class to ease the use of localized
|
||||
* messages.
|
||||
* <p>
|
||||
* Enriched to handle localized message formats.
|
||||
*/
|
||||
class Messages
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(Messages.class.getName());
|
||||
private static final String BUNDLE_NAME = "gnu.classpath.tools.jarsigner.MessageBundle"; //$NON-NLS-1$
|
||||
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
|
||||
private static final Map CACHED_FORMATS = new HashMap(5);
|
||||
|
||||
private Messages()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public static String getString(String key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return RESOURCE_BUNDLE.getString(key);
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
return constructMessage(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFormattedString(String key, Object args)
|
||||
{
|
||||
MessageFormat mf = (MessageFormat) CACHED_FORMATS.get(key);
|
||||
if (mf == null)
|
||||
{
|
||||
String formatString = getString(key);
|
||||
if (formatString.startsWith("!"))
|
||||
return constructMessage(key, args);
|
||||
|
||||
mf = new MessageFormat(formatString);
|
||||
CACHED_FORMATS.put(key, mf);
|
||||
}
|
||||
|
||||
// if the argument is not an array, then build one consisiting of the
|
||||
// sole argument before passing it to the format() method
|
||||
try
|
||||
{
|
||||
if (args instanceof Object[])
|
||||
return mf.format(args);
|
||||
|
||||
return mf.format(new Object[] { args });
|
||||
}
|
||||
catch (IllegalArgumentException x)
|
||||
{
|
||||
log.fine("Exception while rendering a message format keyed by ["
|
||||
+ key + "]: " + mf.toPattern());
|
||||
return constructMessage(mf.toPattern(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String constructMessage(String m, Object args)
|
||||
{
|
||||
if (args == null)
|
||||
return '!' + m + '!';
|
||||
|
||||
return '!' + m + '!' + String.valueOf(args) + '!';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/* SFHelper -- A .SF file helper
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.jarsigner;
|
||||
|
||||
import gnu.java.security.OID;
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.der.DER;
|
||||
import gnu.java.security.der.DERValue;
|
||||
import gnu.java.security.pkcs.PKCS7Data;
|
||||
import gnu.java.security.pkcs.PKCS7SignedData;
|
||||
import gnu.java.security.pkcs.SignerInfo;
|
||||
import gnu.java.security.sig.ISignature;
|
||||
import gnu.java.security.sig.ISignatureCodec;
|
||||
import gnu.java.security.sig.dss.DSSSignature;
|
||||
import gnu.java.security.sig.dss.DSSSignatureX509Codec;
|
||||
import gnu.java.security.sig.rsa.RSAPKCS1V1_5Signature;
|
||||
import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
|
||||
import gnu.java.security.util.Util;
|
||||
import gnu.java.util.jar.JarUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.CRLException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509CRL;
|
||||
import java.security.interfaces.DSAPrivateKey;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* A helper class for the .SF file found in signed jars.
|
||||
*/
|
||||
public class SFHelper
|
||||
{
|
||||
// Constants and fields
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
private static final Logger log = Logger.getLogger(SFHelper.class.getName());
|
||||
private static final int READY = 0;
|
||||
private static final int STARTED = 1;
|
||||
private static final int FINISHED = 2;
|
||||
private static final int SF_GENERATED = 3;
|
||||
private static final int DSA_GENERATED = 4;
|
||||
/** http://asn1.elibel.tm.fr/cgi-bin/oid/display?oid=1.3.14.3.2.26&action=display */
|
||||
private static final OID hashAlgorithmIdentifierSHA1 = new OID("1.3.14.3.2.26"); //$NON-NLS-1$
|
||||
|
||||
private int state;
|
||||
private JarFile jar;
|
||||
private Manifest manifest;
|
||||
private Attributes sfMainAttributes;
|
||||
private Map sfEntries;
|
||||
private byte[] sfBytes;
|
||||
private HashUtils util;
|
||||
|
||||
// Constructor(s)
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @param jar the JAR archive the .SF file belongs to.
|
||||
*/
|
||||
public SFHelper(JarFile jar)
|
||||
{
|
||||
super();
|
||||
|
||||
this.jar = jar;
|
||||
this.state = READY;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Instance methods
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Writes the contents of the <code>.SF</code> file to the designated JAR
|
||||
* output stream. Line-endings are platform-independent and consist of the
|
||||
* 2-codepoint sequence <code>0x0D</code> and <code>0x0A</code>.
|
||||
*
|
||||
* @param jar the JAR output stream to write a <code>.SF</code> file to.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
*/
|
||||
void writeSF(JarOutputStream jar) throws IOException
|
||||
{
|
||||
if (this.state != FINISHED)
|
||||
throw new IllegalStateException(Messages.getString("SFHelper.1")); //$NON-NLS-1$
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
JarUtils.writeSFManifest(sfMainAttributes, sfEntries, baos);
|
||||
sfBytes = baos.toByteArray();
|
||||
log.finest("\n" + Util.dumpString(sfBytes, "+++ sfBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
jar.write(sfBytes);
|
||||
jar.flush();
|
||||
|
||||
this.state = SF_GENERATED;
|
||||
}
|
||||
|
||||
/**
|
||||
* The contents of the .DSA file is the DER encoded form of a PKCS#7
|
||||
* ContentInfo of the type SignedData.
|
||||
* <p>
|
||||
* The ContentInfo ASN.1 syntax is as described in the "PKCS#7 Cryptographic
|
||||
* Message Syntax Standard" (RSA Labs) specifications:
|
||||
* <pre>
|
||||
* ContentInfo ::= SEQUENCE {
|
||||
* contentType ContentType,
|
||||
* content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
|
||||
* }
|
||||
*
|
||||
* ContentType ::= OBJECT IDENTIFIER
|
||||
* </pre>
|
||||
* <p>
|
||||
* The ContentType is an OID which determines the type of the contents field
|
||||
* that follows it. For the .DSA file the OID is "1.2.840.113549.1.7.2", while
|
||||
* the content field is the byte array representing the DER encoded form of a
|
||||
* SignedData content-type. The ASN.1 syntax of the SignedData type is as
|
||||
* follows:
|
||||
* <pre>
|
||||
* SignedData ::= SEQUENCE {
|
||||
* version Version, -- always 1 for PKCS#7 1.5
|
||||
* digestAlgorithms DigestAlgorithmIdentifiers,
|
||||
* contentInfo ContentInfo,
|
||||
* certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
|
||||
* crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
|
||||
* signerInfos SignerInfos
|
||||
* }
|
||||
*
|
||||
* DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
|
||||
*
|
||||
* SignerInfos ::= SET OF SignerInfo
|
||||
* </pre>
|
||||
* <p>
|
||||
* Finally the SignerInfo is a per-signer structure. Its ASN.1 syntax looks
|
||||
* like so:
|
||||
* <pre>
|
||||
* SignerInfo ::= SEQUENCE {
|
||||
* version Version, -- always 1 for PKCS#7 1.5
|
||||
* issuerAndSerialNumber IssuerAndSerialNumber,
|
||||
* digestAlgorithm DigestAlgorithmIdentifier,
|
||||
* authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
|
||||
* digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
|
||||
* encryptedDigest EncryptedDigest,
|
||||
* unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
|
||||
* }
|
||||
*
|
||||
* EncryptedDigest ::= OCTET STRING
|
||||
* </pre>
|
||||
*
|
||||
* @param jar the JAR output stream to write a <code>.DSA</code> file to.
|
||||
* @param signerKey the private key to sign with.
|
||||
* @param certificates the possibly null signer certificate chain.
|
||||
* @param internalSF if <code>true</code> then include the .SF file contents
|
||||
* in the signed .DSA file; otherwise don't.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
* @throws CRLException
|
||||
* @throws CertificateEncodingException
|
||||
*/
|
||||
void writeDSA(JarOutputStream jar, PrivateKey signerKey,
|
||||
Certificate[] certificates, boolean internalSF)
|
||||
throws IOException, CertificateEncodingException, CRLException
|
||||
{
|
||||
if (this.state != SF_GENERATED)
|
||||
throw new IllegalStateException(Messages.getString("SFHelper.4")); //$NON-NLS-1$
|
||||
|
||||
log.finest("+++ signer private key = " + signerKey); //$NON-NLS-1$
|
||||
ISignature signatureAlgorithm;
|
||||
ISignatureCodec signatureCodec;
|
||||
OID digestEncryptionAlgorithmOID;
|
||||
if (signerKey instanceof DSAPrivateKey)
|
||||
{
|
||||
signatureAlgorithm = new DSSSignature();
|
||||
signatureCodec = new DSSSignatureX509Codec();
|
||||
digestEncryptionAlgorithmOID = Main.DSA_SIGNATURE_OID;
|
||||
}
|
||||
else if (signerKey instanceof RSAPrivateKey)
|
||||
{
|
||||
signatureAlgorithm = new RSAPKCS1V1_5Signature(Registry.MD5_HASH);
|
||||
signatureCodec = new RSAPKCS1V1_5SignatureX509Codec();
|
||||
digestEncryptionAlgorithmOID = Main.RSA_SIGNATURE_OID;
|
||||
}
|
||||
else
|
||||
throw new SecurityException(Messages.getString("SFHelper.6")); //$NON-NLS-1$
|
||||
|
||||
Map signatureAttributes = new HashMap();
|
||||
signatureAttributes.put(ISignature.SIGNER_KEY, signerKey);
|
||||
signatureAlgorithm.setupSign(signatureAttributes);
|
||||
signatureAlgorithm.update(sfBytes, 0, sfBytes.length);
|
||||
Object signature = signatureAlgorithm.sign();
|
||||
byte[] signedSFBytes = signatureCodec.encodeSignature(signature);
|
||||
log.finest("\n" + Util.dumpString(signedSFBytes, "+++ signedSFBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
Set digestAlgorithms = new HashSet();
|
||||
List digestAlgorithm = new ArrayList(2);
|
||||
DERValue derDigestAlgorithmOID = new DERValue(DER.OBJECT_IDENTIFIER,
|
||||
hashAlgorithmIdentifierSHA1);
|
||||
DERValue derDigestAlgorithmParams = new DERValue(DER.NULL, null);
|
||||
digestAlgorithm.add(derDigestAlgorithmOID);
|
||||
digestAlgorithm.add(derDigestAlgorithmParams);
|
||||
DERValue derDigestAlgorithm = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
|
||||
digestAlgorithm);
|
||||
digestAlgorithms.add(derDigestAlgorithm);
|
||||
|
||||
// TODO (rsn): test with internalsf == true
|
||||
PKCS7Data data = internalSF ? new PKCS7Data(sfBytes) : null;
|
||||
|
||||
X509CRL[] crls = null;
|
||||
|
||||
Set signerInfos = new HashSet();
|
||||
X509Certificate cert = (X509Certificate) certificates[0];
|
||||
X500Principal issuer = cert.getIssuerX500Principal();
|
||||
BigInteger serialNumber = cert.getSerialNumber();
|
||||
byte[] authenticatedAttributes = null;
|
||||
byte[] encryptedDigest = signedSFBytes;
|
||||
byte[] unauthenticatedAttributes = null;
|
||||
SignerInfo signerInfo = new SignerInfo(issuer,
|
||||
serialNumber,
|
||||
hashAlgorithmIdentifierSHA1,
|
||||
authenticatedAttributes,
|
||||
digestEncryptionAlgorithmOID,
|
||||
encryptedDigest,
|
||||
unauthenticatedAttributes);
|
||||
signerInfos.add(signerInfo);
|
||||
|
||||
PKCS7SignedData dsaContents = new PKCS7SignedData(digestAlgorithms,
|
||||
data,
|
||||
certificates,
|
||||
crls,
|
||||
signerInfos);
|
||||
dsaContents.encode(jar);
|
||||
|
||||
jar.flush();
|
||||
this.state = DSA_GENERATED;
|
||||
}
|
||||
|
||||
Manifest getManifest()
|
||||
{
|
||||
return this.manifest;
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
void startSigning() throws IOException
|
||||
{
|
||||
if (this.state != READY)
|
||||
throw new IllegalStateException(Messages.getString("SFHelper.9")); //$NON-NLS-1$
|
||||
|
||||
Manifest oldManifest = jar.getManifest();
|
||||
this.manifest = oldManifest == null ? new Manifest()
|
||||
: new Manifest(oldManifest);
|
||||
this.sfMainAttributes = new Attributes();
|
||||
this.sfEntries = new HashMap();
|
||||
util = new HashUtils();
|
||||
|
||||
this.state = STARTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the designated JAR entry (the file itself); adds the resulting hash
|
||||
* as an attribute to the manifest, and computes the hash of the added (to
|
||||
* the Manifest) two headers and add the result as an attribute of the
|
||||
* corresponding entry in the .SF file.
|
||||
*/
|
||||
void updateEntry(JarEntry entry) throws IOException
|
||||
{
|
||||
if (this.state != STARTED)
|
||||
throw new IllegalStateException(Messages.getString("SFHelper.10")); //$NON-NLS-1$
|
||||
|
||||
String name = entry.getName();
|
||||
InputStream jeis = jar.getInputStream(entry);
|
||||
String hash = util.hashStream(jeis);
|
||||
log.finer("Hash of " + name + " = " + hash); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
Attributes mainfestAttributes = manifest.getAttributes(name);
|
||||
if (mainfestAttributes == null)
|
||||
{
|
||||
mainfestAttributes = new Attributes();
|
||||
manifest.getEntries().put(name, mainfestAttributes);
|
||||
}
|
||||
|
||||
mainfestAttributes.putValue(Main.DIGEST, hash);
|
||||
|
||||
// hash the newly added 2-header block and add it as an attribute to .SF
|
||||
|
||||
String sfHash = util.hashManifestEntry(name, hash);
|
||||
Attributes sfAttributes = (Attributes) sfEntries.get(name);
|
||||
if (sfAttributes == null)
|
||||
{
|
||||
sfAttributes = new Attributes();
|
||||
sfEntries.put(name, sfAttributes);
|
||||
}
|
||||
|
||||
sfAttributes.putValue(Main.DIGEST, sfHash);
|
||||
log.finest("Name: " + name); //$NON-NLS-1$
|
||||
log.finest(Main.DIGEST + ": " + sfHash); //$NON-NLS-1$
|
||||
log.finest(""); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sectionsOnly whether to compute, in addition to the files, the hash
|
||||
* of the mainfest itself (<code>false</code>) or not (<code>true</code>).
|
||||
*/
|
||||
void finishSigning(boolean sectionsOnly) throws IOException
|
||||
{
|
||||
if (state != STARTED)
|
||||
throw new IllegalStateException(Messages.getString("SFHelper.10")); //$NON-NLS-1$
|
||||
|
||||
if (sectionsOnly)
|
||||
return;
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
manifest.write(baos);
|
||||
baos.flush();
|
||||
String manifestHash = util.hashByteArray(baos.toByteArray());
|
||||
log.fine("Hashed Manifest " + manifestHash); //$NON-NLS-1$
|
||||
sfMainAttributes.putValue(Main.DIGEST_MANIFEST, manifestHash);
|
||||
|
||||
this.state = FINISHED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
/* CertReqCmd.java -- The certreq command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.java.security.OID;
|
||||
import gnu.java.security.der.BitString;
|
||||
import gnu.java.security.der.DER;
|
||||
import gnu.java.security.der.DERReader;
|
||||
import gnu.java.security.der.DERValue;
|
||||
import gnu.java.security.der.DERWriter;
|
||||
import gnu.java.security.util.Base64;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/**
|
||||
* The <b>-certreq</b> keytool command handler is used to generate a Certificate
|
||||
* Signing Request (CSR) in PKCS#10 format.
|
||||
* <p>
|
||||
* The ASN.1 specification of a CSR, as stated in RFC-2986 is as follows:
|
||||
* <p>
|
||||
* <pre>
|
||||
* CertificationRequest ::= SEQUENCE {
|
||||
* certificationRequestInfo CertificationRequestInfo,
|
||||
* signatureAlgorithm AlgorithmIdentifier,
|
||||
* signature BIT STRING
|
||||
* }
|
||||
*
|
||||
* CertificationRequestInfo ::= SEQUENCE {
|
||||
* version INTEGER -- v1(0)
|
||||
* subject Name,
|
||||
* subjectPKInfo SubjectPublicKeyInfo,
|
||||
* attributes [0] IMPLICIT Attributes -- see note later
|
||||
* }
|
||||
*
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING
|
||||
* }
|
||||
* </pre>
|
||||
* <b>IMPORTANT</b>: Some documentation (e.g. RSA examples) claims that the
|
||||
* <code>attributes</code> field is <i>OPTIONAL</i> while <i>RFC-2986</i>
|
||||
* implies the opposite. This implementation considers this field, by default,
|
||||
* as <i>OPTIONAL</i>, unless the option <code>-attributes</code> is included
|
||||
* on the command line.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-sigalg ALGORITHM</dt>
|
||||
* <dd>The canonical name of the digital signature algorithm to use for
|
||||
* signing the certificate. If this option is omitted, a default value will
|
||||
* be chosen based on the type of the private key associated with the
|
||||
* designated <i>Alias</i>. If the private key is a <code>DSA</code> one,
|
||||
* the value for the signature algorithm will be <code>SHA1withDSA</code>.
|
||||
* If on the other hand the private key is an <code>RSA</code> one, then
|
||||
* the tool will use <code>MD5withRSA</code> as the signature algorithm.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-file FILE_NAME</dt>
|
||||
*
|
||||
* <dt>-keypass PASSWORD</dt>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-attributes</dt>
|
||||
* <dd>Use this option to force the tool to encode a NULL DER value in the
|
||||
* CSR as the value of the Attributes field.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class CertReqCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(CertReqCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _sigAlgorithm;
|
||||
private String _certReqFileName;
|
||||
private String _password;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private boolean nullAttributes;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param algorithm the canonical name of the digital signature algorithm to
|
||||
* use.
|
||||
*/
|
||||
public void setSigalg(String algorithm)
|
||||
{
|
||||
this._sigAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
/** @param pathName the fully qualified path name of the file to process. */
|
||||
public void setFile(String pathName)
|
||||
{
|
||||
this._certReqFileName = pathName;
|
||||
}
|
||||
|
||||
/** @param password the (private) key password to use. */
|
||||
public void setKeypass(String password)
|
||||
{
|
||||
this._password = password;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flag whether to use, or not, a <code>NULL</code> DER value for
|
||||
* the certificate's Attributes field.
|
||||
*/
|
||||
public void setAttributes(String flag)
|
||||
{
|
||||
this.nullAttributes = Boolean.valueOf(flag).booleanValue();
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-sigalg".equals(opt)) // -sigalg ALGORITHM //$NON-NLS-1$
|
||||
_sigAlgorithm = args[++i];
|
||||
else if ("-file".equals(opt)) // -file FILE_NAME //$NON-NLS-1$
|
||||
_certReqFileName = args[++i];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
|
||||
_password = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else if ("-attributes".equals(opt)) //$NON-NLS-1$
|
||||
nullAttributes = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setOutputStreamParam(_certReqFileName);
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
setKeyPasswordNoPrompt(_password);
|
||||
// setSignatureAlgorithm(_sigAlgorithm);
|
||||
|
||||
log.finer("-certreq handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -sigalg=" + _sigAlgorithm); //$NON-NLS-1$
|
||||
log.finer(" -file=" + _certReqFileName); //$NON-NLS-1$
|
||||
log.finer(" -keypass=" + _password); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
log.finer(" -attributes=" + nullAttributes); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
|
||||
UnsupportedCallbackException, UnrecoverableKeyException,
|
||||
InvalidKeyException, SignatureException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
// 1. get the key entry and certificate chain associated to alias
|
||||
Key privateKey = getAliasPrivateKey();
|
||||
Certificate[] chain = store.getCertificateChain(alias);
|
||||
|
||||
// 2. get alias's DN and public key to use in the CSR
|
||||
X509Certificate bottomCertificate = (X509Certificate) chain[0];
|
||||
X500Principal aliasName = bottomCertificate.getIssuerX500Principal();
|
||||
PublicKey publicKey = bottomCertificate.getPublicKey();
|
||||
|
||||
// 3. generate the CSR
|
||||
setSignatureAlgorithmParam(_sigAlgorithm, privateKey);
|
||||
byte[] derBytes = getCSR(aliasName, publicKey, (PrivateKey) privateKey);
|
||||
|
||||
// 4. encode it in base-64 and write it to outStream
|
||||
String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
|
||||
PrintWriter writer = new PrintWriter(outStream, true);
|
||||
writer.println("-----BEGIN NEW CERTIFICATE REQUEST-----"); //$NON-NLS-1$
|
||||
writer.println(encoded);
|
||||
writer.println("-----END NEW CERTIFICATE REQUEST-----"); //$NON-NLS-1$
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (! systemOut)
|
||||
System.out.println(Messages.getFormattedString("CertReqCmd.27", //$NON-NLS-1$
|
||||
_certReqFileName));
|
||||
System.out.println(Messages.getString("CertReqCmd.28")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
writer.close();
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @param aliasName
|
||||
* @param publicKey
|
||||
* @param privateKey
|
||||
* @return the DER encoded Certificate Signing Request.
|
||||
* @throws IOException
|
||||
* @throws InvalidKeyException
|
||||
* @throws SignatureException
|
||||
*/
|
||||
private byte[] getCSR(X500Principal aliasName, PublicKey publicKey,
|
||||
PrivateKey privateKey)
|
||||
throws IOException, InvalidKeyException, SignatureException
|
||||
{
|
||||
DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
|
||||
DERValue derSubject = new DERReader(aliasName.getEncoded()).read();
|
||||
DERValue derSubjectPKInfo = new DERReader(publicKey.getEncoded()).read();
|
||||
byte[] b = nullAttributes ? new byte[] { 0x05, 0x00 } : new byte[0];
|
||||
DERValue derAttributes = new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 0,
|
||||
b.length, b, null);
|
||||
ArrayList certRequestInfo = new ArrayList(4);
|
||||
certRequestInfo.add(derVersion);
|
||||
certRequestInfo.add(derSubject);
|
||||
certRequestInfo.add(derSubjectPKInfo);
|
||||
certRequestInfo.add(derAttributes);
|
||||
DERValue derCertRequestInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
|
||||
certRequestInfo);
|
||||
|
||||
OID sigAlgorithmID = getSignatureAlgorithmOID();
|
||||
DERValue derSigAlgorithmID = new DERValue(DER.OBJECT_IDENTIFIER,
|
||||
sigAlgorithmID);
|
||||
ArrayList sigAlgorithm = new ArrayList(2);
|
||||
sigAlgorithm.add(derSigAlgorithmID);
|
||||
if (! sigAlgorithmID.equals(Command.SHA1_WITH_DSA)) // it's an RSA-based
|
||||
sigAlgorithm.add(new DERValue(DER.NULL, null));
|
||||
|
||||
sigAlgorithm.trimToSize();
|
||||
DERValue derSignatureAlgorithm = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
|
||||
sigAlgorithm);
|
||||
|
||||
signatureAlgorithm.initSign(privateKey);
|
||||
signatureAlgorithm.update(derCertRequestInfo.getEncoded());
|
||||
byte[] sigBytes = signatureAlgorithm.sign();
|
||||
DERValue derSignature = new DERValue(DER.BIT_STRING, new BitString(sigBytes));
|
||||
|
||||
ArrayList csr = new ArrayList(3);
|
||||
csr.add(derCertRequestInfo);
|
||||
csr.add(derSignatureAlgorithm);
|
||||
csr.add(derSignature);
|
||||
DERValue derCSR = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, csr);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DERWriter.write(baos, derCSR);
|
||||
byte[] result = baos.toByteArray();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
||||
/* DeleteCmd.java -- The delete command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The <b>-delete</b> keytool command handler is used to delete from the key
|
||||
* store the entry associated with a designated alias.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class DeleteCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(DeleteCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setTheAlias(_alias);
|
||||
|
||||
log.finer("-delete handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, NoSuchAlgorithmException,
|
||||
CertificateException, IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
ensureStoreContainsAlias();
|
||||
store.deleteEntry(alias);
|
||||
saveKeyStore();
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the alias to delete from the key store.
|
||||
* <p>
|
||||
* Unlike in other keytool handlers, the default value (<i>mykey</i>) for the
|
||||
* Alias is not used. Instead, if an alias was not found on the command line,
|
||||
* the user is prompted to enter one.
|
||||
*
|
||||
* @param anAlias a possibly null Alias gleaned from the command line.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
* @throws UnsupportedCallbackException if no implementation of a password
|
||||
* callback handler was found.
|
||||
*/
|
||||
private void setTheAlias(String anAlias) throws IOException,
|
||||
UnsupportedCallbackException
|
||||
{
|
||||
if (anAlias == null || anAlias.trim().length() == 0)
|
||||
{
|
||||
String prompt = Messages.getString("DeleteCmd.19"); //$NON-NLS-1$
|
||||
NameCallback ncb = new NameCallback(prompt);
|
||||
getCallbackHandler().handle(new Callback[] { ncb });
|
||||
anAlias = ncb.getName();
|
||||
if (anAlias == null || anAlias.trim().length() == 0)
|
||||
throw new SecurityException(Messages.getString("DeleteCmd.20")); //$NON-NLS-1$
|
||||
}
|
||||
alias = anAlias.trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/* ExportCmd.java -- The export command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.java.security.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The <b>-export</b> keytool command handler is used to read the certificate
|
||||
* associated with a designated alias from the key store, and write it to a
|
||||
* designated file.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-file FILE_NAME</dt>
|
||||
* <dd>The fully qualified path of the file where the certificate will be
|
||||
* exported to. If omitted, STDOUT will be used instead.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-rfc</dt>
|
||||
* <dd>Use RFC-1421 specifications when encoding the output.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Output the certificate in binary DER encoding. This is the default
|
||||
* output format of the command if neither <code>-rfc</code> nor
|
||||
* <code>-v</code> options were detected on the command line. If both this
|
||||
* option and the <code>-rfc</code> option are detected on the command
|
||||
* line, the tool will opt for the RFC-1421 style encoding.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class ExportCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(ExportCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _certFileName;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private boolean rfc;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param pathName the fully qualified path name of the file to process. */
|
||||
public void setFile(String pathName)
|
||||
{
|
||||
this._certFileName = pathName;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flag whether to use, or not, RFC-1421 format when exporting the
|
||||
* certificate(s).
|
||||
*/
|
||||
public void setRfc(String flag)
|
||||
{
|
||||
this.rfc = Boolean.valueOf(flag).booleanValue();
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt);
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS
|
||||
_alias = args[++i];
|
||||
else if ("-file".equals(opt)) // -file FILE_NAME
|
||||
_certFileName = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME
|
||||
_providerClassName = args[++i];
|
||||
else if ("-rfc".equals(opt))
|
||||
rfc = true;
|
||||
else if ("-v".equals(opt))
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setOutputStreamParam(_certFileName);
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
|
||||
log.finer("-export handler will use the following options:");
|
||||
log.finer(" -alias=" + alias);
|
||||
log.finer(" -file=" + _certFileName);
|
||||
log.finer(" -storetype=" + storeType);
|
||||
log.finer(" -keystore=" + storeURL);
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars));
|
||||
log.finer(" -provider=" + provider);
|
||||
log.finer(" -rfc=" + rfc);
|
||||
log.finer(" -v=" + verbose);
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, CertificateEncodingException,
|
||||
IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start");
|
||||
|
||||
ensureStoreContainsAlias();
|
||||
Certificate certificate;
|
||||
if (store.isCertificateEntry(alias))
|
||||
{
|
||||
log.fine("Alias [" + alias + "] is a trusted certificate");
|
||||
certificate = store.getCertificate(alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.fine("Alias [" + alias + "] is a key entry");
|
||||
Certificate[] chain = store.getCertificateChain(alias);
|
||||
certificate = chain[0];
|
||||
}
|
||||
|
||||
byte[] derBytes = certificate.getEncoded();
|
||||
if (rfc)
|
||||
{
|
||||
String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
|
||||
PrintWriter pw = new PrintWriter(outStream, true);
|
||||
pw.println("-----BEGIN CERTIFICATE-----");
|
||||
pw.println(encoded);
|
||||
pw.println("-----END CERTIFICATE-----");
|
||||
}
|
||||
else
|
||||
outStream.write(derBytes);
|
||||
|
||||
// stream is closed in Command.teardown()
|
||||
log.exiting(this.getClass().getName(), "start");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
/* GenKeyCmd.java -- The genkey command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.java.security.util.Util;
|
||||
import gnu.java.security.x509.X500DistinguishedName;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.TextInputCallback;
|
||||
import javax.security.auth.callback.TextOutputCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The <b>-genkey</b> keytool command handler is used to generate a key pair (a
|
||||
* public, and associated private keys). It then generates a self-signed X509 v1
|
||||
* certificate (authenticating the public key) and stores this certificate and
|
||||
* the private key in the key store associating both to a designated alias.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keyalg ALGORITHM</dt>
|
||||
* <dd>Use this option to specify the canonical name of the key-pair
|
||||
* generation algorithm. The default value for this option is
|
||||
* <code>DSS</code> (a synonym for the Digital Signature Algorithm also
|
||||
* known as <code>DSA</code>).
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keysize KEY_SIZE</dt>
|
||||
* <dd>Use this option to specify the number of bits of the shared modulus
|
||||
* (for both the public and private keys) to use when generating new keys.
|
||||
* A default value of <code>1024</code> will be used if this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-sigalg ALGORITHM</dt>
|
||||
* <dd>The canonical name of the digital signature algorithm to use for
|
||||
* signing certificates. If this option is omitted, a default value will be
|
||||
* chosen based on the type of the key-pair; i.e. the algorithm that ends
|
||||
* up being used by the <code>-keyalg</code> option. If the key-pair
|
||||
* generation algorithm is <code>DSA</code>, the value for the signature
|
||||
* algorithm will be <code>SHA1withDSA</code>. If on the other hand the
|
||||
* key-pair generation algorithm is <code>RSA</code>, then the tool will
|
||||
* use <code>MD5withRSA</code> as the signature algorithm.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-dname NAME</dt>
|
||||
* <dd>This a mandatory value for this command. If this option is omitted
|
||||
* the tool will prompt you to enter a <i>Distinguished Name</i> to use as
|
||||
* both the <i>Owner</i> and <i>Issuer</i> of the generated self-signed
|
||||
* certificate.
|
||||
* <p>
|
||||
* The syntax of a valid value for this option MUST follow RFC-2253
|
||||
* specifications. Namely the following components (with their accepted
|
||||
* meaning) will be recognized. Note that the component name is case-
|
||||
* insensitive:
|
||||
* <dl>
|
||||
* <dt>CN</dt>
|
||||
* <dd>The Common Name; e.g. "host.domain.com"</dd>
|
||||
*
|
||||
* <dt>OU</dt>
|
||||
* <dd>The Organizational Unit; e.g. "IT Department"</dd>
|
||||
*
|
||||
* <dt>O</dt>
|
||||
* <dd>The Organization Name; e.g. "The Sample Company"</dd>
|
||||
*
|
||||
* <dt>L</dt>
|
||||
* <dd>The Locality Name; e.g. "Sydney"</dd>
|
||||
*
|
||||
* <dt>ST</dt>
|
||||
* <dd>The State Name; e.g. "New South Wales"</dd>
|
||||
*
|
||||
* <dt>C</dt>
|
||||
* <dd>The 2-letter Country identifier; e.g. "AU"</dd>
|
||||
* </dl>
|
||||
* <p>
|
||||
* When specified with a <code>-dname</code> option, each pair of component
|
||||
* / value will be separated from the other with a comma. Each component
|
||||
* and value pair MUST be separated by an equal sign. For example, the
|
||||
* following is a valid DN value:
|
||||
* <pre>
|
||||
* CN=host.domain.com, O=The Sample Company, L=Sydney, ST=NSW, C=AU
|
||||
* </pre>
|
||||
* If this option is omitted, the tool will prompt you to enter the
|
||||
* information through the console.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keypass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password which the tool will use to
|
||||
* protect the newly created Key Entry.
|
||||
* <p>
|
||||
* If this option is omitted, you will be prompted to provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-validity DAY_COUNT</dt>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class GenKeyCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(GenKeyCmd.class.getName());
|
||||
/** Default key size in bits. */
|
||||
private static final int DEFAULT_KEY_SIZE = 1024;
|
||||
|
||||
private String _alias;
|
||||
private String _keyAlgorithm;
|
||||
private String _keySizeStr;
|
||||
private String _sigAlgorithm;
|
||||
private String _dName;
|
||||
private String _password;
|
||||
private String _validityStr;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private int keySize;
|
||||
private X500DistinguishedName distinguishedName;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param algorithm the canonical name of the key-pair algorithm to use. */
|
||||
public void setKeyalg(String algorithm)
|
||||
{
|
||||
this._keyAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits the string representation of the number of bits (a decimal
|
||||
* positive integer) the modulus of the generated keys (private and
|
||||
* public) should have.
|
||||
*/
|
||||
public void setKeysize(String bits)
|
||||
{
|
||||
this._validityStr = bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param algorithm the canonical name of the digital signature algorithm to
|
||||
* use.
|
||||
*/
|
||||
public void setSigalg(String algorithm)
|
||||
{
|
||||
this._sigAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
/** @param name the distiniguished name to use. */
|
||||
public void setDname(String name)
|
||||
{
|
||||
this._dName = name;
|
||||
}
|
||||
|
||||
/** @param password the (private) key password to use. */
|
||||
public void setKeypass(String password)
|
||||
{
|
||||
this._password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param days the string representation of the number of days (a decimal,
|
||||
* positive integer) to assign to the generated certificate.
|
||||
*/
|
||||
public void setValidity(String days)
|
||||
{
|
||||
this._validityStr = days;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-keyalg".equals(opt)) // -keyalg ALGORITHM //$NON-NLS-1$
|
||||
_keyAlgorithm = args[++i];
|
||||
else if ("-keysize".equals(opt)) // -keysize KEY_SIZE //$NON-NLS-1$
|
||||
_keySizeStr = args[++i];
|
||||
else if ("-sigalg".equals(opt)) // -sigalg ALGORITHM //$NON-NLS-1$
|
||||
_sigAlgorithm = args[++i];
|
||||
else if ("-dname".equals(opt)) // -dname NAME //$NON-NLS-1$
|
||||
_dName = args[++i];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
|
||||
_password = args[++i];
|
||||
else if ("-validity".equals(opt)) // -validity DAY_COUNT //$NON-NLS-1$
|
||||
_validityStr = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
setKeyPasswordParam(_password);
|
||||
setAlgorithmParams(_keyAlgorithm, _sigAlgorithm);
|
||||
setKeySize(_keySizeStr);
|
||||
setDName(_dName);
|
||||
setValidityParam(_validityStr);
|
||||
|
||||
log.finer("-genkey handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -keyalg=" + keyPairGenerator.getAlgorithm()); //$NON-NLS-1$
|
||||
log.finer(" -keysize=" + keySize); //$NON-NLS-1$
|
||||
log.finer(" -sigalg=" + signatureAlgorithm.getAlgorithm()); //$NON-NLS-1$
|
||||
log.finer(" -dname=" + distinguishedName); //$NON-NLS-1$
|
||||
log.finer(" -keypass=" + String.valueOf(keyPasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -validity=" + validityInDays); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws CertificateException, KeyStoreException,
|
||||
InvalidKeyException, SignatureException, IOException,
|
||||
NoSuchAlgorithmException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
// 1. generate a new key-pair
|
||||
log.fine("About to generate key-pair...");
|
||||
keyPairGenerator.initialize(keySize);
|
||||
KeyPair kp = keyPairGenerator.generateKeyPair();
|
||||
PublicKey publicKey = kp.getPublic();
|
||||
PrivateKey privateKey = kp.getPrivate();
|
||||
|
||||
// 2. generate a self-signed certificate
|
||||
log.fine("About to generate a self-signed certificate...");
|
||||
byte[] derBytes = getSelfSignedCertificate(distinguishedName,
|
||||
publicKey,
|
||||
privateKey);
|
||||
log.finest(Util.dumpString(derBytes, "derBytes ")); //$NON-NLS-1$
|
||||
CertificateFactory x509Factory = CertificateFactory.getInstance(Main.X_509);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(derBytes);
|
||||
Certificate certificate = x509Factory.generateCertificate(bais);
|
||||
log.finest("certificate = " + certificate); //$NON-NLS-1$
|
||||
|
||||
// 3. store it, w/ its private key, associating them to alias
|
||||
Certificate[] chain = new Certificate[] { certificate };
|
||||
log.finest("About to store newly generated material in key store..."); //$NON-NLS-1$
|
||||
store.setKeyEntry(alias, privateKey, keyPasswordChars, chain);
|
||||
|
||||
// 4. persist the key store
|
||||
saveKeyStore();
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @param size the desired key size as a string.
|
||||
* @throws NumberFormatException if the string does not represent a valid
|
||||
* decimal integer value.
|
||||
*/
|
||||
private void setKeySize(String size)
|
||||
{
|
||||
if (size == null || size.trim().length() == 0)
|
||||
this.keySize = DEFAULT_KEY_SIZE;
|
||||
else
|
||||
{
|
||||
size = size.trim();
|
||||
keySize = Integer.parseInt(size);
|
||||
// When generating a DSA key pair, the key size must be in the range
|
||||
// from 512 to 1024 bits, and must be a multiple of 64. The default
|
||||
// key size for any algorithm is 1024 bits
|
||||
if (keySize < 1)
|
||||
throw new IllegalArgumentException(Messages.getString("GenKeyCmd.54")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the X.500 distinguished name of the principal for whom the
|
||||
* key/certificate are being generated.
|
||||
* @throws UnsupportedCallbackException if no implementation of a name
|
||||
* callback is available.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
* @throws IllegalArgumentException if the designated, or captured, value is
|
||||
* not a valid X.500 distinguished name.
|
||||
*/
|
||||
private void setDName(String name) throws IOException,
|
||||
UnsupportedCallbackException
|
||||
{
|
||||
if (name != null && name.trim().length() > 0)
|
||||
name = name.trim();
|
||||
else
|
||||
{
|
||||
// prompt user to provide one
|
||||
String dnTxt = Messages.getString("GenKeyCmd.0"); //$NON-NLS-1$
|
||||
String oDefault = Messages.getString("GenKeyCmd.6"); //$NON-NLS-1$
|
||||
String lDefault = Messages.getString("GenKeyCmd.7"); //$NON-NLS-1$
|
||||
String stDefault = Messages.getString("GenKeyCmd.8"); //$NON-NLS-1$
|
||||
String cDefault = Messages.getString("GenKeyCmd.9"); //$NON-NLS-1$
|
||||
String cnPrompt = Messages.getString("GenKeyCmd.10"); //$NON-NLS-1$
|
||||
String oPrompt = Messages.getFormattedString("GenKeyCmd.11", oDefault); //$NON-NLS-1$
|
||||
String ouPrompt = Messages.getString("GenKeyCmd.13"); //$NON-NLS-1$
|
||||
String lPrompt = Messages.getFormattedString("GenKeyCmd.14", lDefault); //$NON-NLS-1$
|
||||
String stPrompt = Messages.getFormattedString("GenKeyCmd.16", stDefault); //$NON-NLS-1$
|
||||
String cPrompt = Messages.getFormattedString("GenKeyCmd.18", cDefault); //$NON-NLS-1$
|
||||
|
||||
TextOutputCallback dnCB = new TextOutputCallback(TextOutputCallback.INFORMATION,
|
||||
dnTxt);
|
||||
TextInputCallback cnCB = new TextInputCallback(cnPrompt);
|
||||
TextInputCallback oCB = new TextInputCallback(oPrompt, oDefault);
|
||||
TextInputCallback ouCB = new TextInputCallback(ouPrompt);
|
||||
TextInputCallback lCB = new TextInputCallback(lPrompt, lDefault);
|
||||
TextInputCallback sCB = new TextInputCallback(stPrompt, stDefault);
|
||||
TextInputCallback cCB = new TextInputCallback(cPrompt, cDefault);
|
||||
getCallbackHandler().handle(new Callback[] { dnCB, cnCB, oCB, ouCB, lCB, sCB, cCB });
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// handle CN
|
||||
name = parseUserPrompt(cnCB);
|
||||
if (name != null && name.length() > 0)
|
||||
sb.append("CN=").append(name); //$NON-NLS-1$
|
||||
|
||||
// handle O
|
||||
name = parseUserPrompt(oCB);
|
||||
if (name != null && name.length() > 0)
|
||||
sb.append(",O=").append(name); //$NON-NLS-1$
|
||||
|
||||
// handle OU
|
||||
name = parseUserPrompt(ouCB);
|
||||
if (name != null && name.length() > 0)
|
||||
sb.append(",OU=").append(name.trim()); //$NON-NLS-1$
|
||||
|
||||
// handle L
|
||||
name = parseUserPrompt(lCB);
|
||||
if (name != null && name.length() > 0)
|
||||
sb.append(",L=").append(name.trim()); //$NON-NLS-1$
|
||||
|
||||
// handle ST
|
||||
name = parseUserPrompt(sCB);
|
||||
if (name != null && name.length() > 0)
|
||||
sb.append(",ST=").append(name.trim()); //$NON-NLS-1$
|
||||
|
||||
// handle C
|
||||
name = parseUserPrompt(cCB);
|
||||
if (name != null && name.length() > 0)
|
||||
sb.append(",C=").append(name.trim()); //$NON-NLS-1$
|
||||
|
||||
name = sb.toString().trim();
|
||||
}
|
||||
|
||||
log.fine("dName=[" + name + "]"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
distinguishedName = new X500DistinguishedName(name);
|
||||
}
|
||||
|
||||
private String parseUserPrompt(TextInputCallback ticb)
|
||||
{
|
||||
String result = ticb.getText();
|
||||
if (result == null || result.trim().length() == 0)
|
||||
result = ticb.getDefaultText();
|
||||
else if (result.trim().equals(".")) //$NON-NLS-1$
|
||||
result = null;
|
||||
else
|
||||
result = result.trim();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/* IdentityDBCmd.java -- The identitydb command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* <b>NOT IMPLEMENTED YET</b>
|
||||
* <p>
|
||||
* The <b>-identitydb</b> keytool command handler is used to read the JDK 1.1.x-
|
||||
* style identity database and add its entries to the key store. If a key store
|
||||
* does not exist, it is created.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-file FILE_NAME</dt>
|
||||
* <dd>The fully qualified path of the identity file to import. If this
|
||||
* option is omitted, the tool will process STDIN.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class IdentityDBCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(IdentityDBCmd.class.getName());
|
||||
private String _idbFileName;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param pathName the fully qualified path name of the file to process. */
|
||||
public void setFile(String pathName)
|
||||
{
|
||||
this._idbFileName = pathName;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt);
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-file".equals(opt)) // -file FILE_NAME
|
||||
_idbFileName = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt))
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setInputStreamParam(_idbFileName);
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
|
||||
log.finer("-identitydb handler will use the following options:");
|
||||
log.finer(" -file=" + _idbFileName);
|
||||
log.finer(" -storetype=" + storeType);
|
||||
log.finer(" -keystore=" + storeURL);
|
||||
log.finer(" -storepass=" + new String(storePasswordChars));
|
||||
log.finer(" -provider=" + provider);
|
||||
log.finer(" -v=" + verbose);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,751 @@
|
||||
/* ImportCmd.java -- The import command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
import gnu.java.security.x509.X509CertPath;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertPathValidator;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.PKIXCertPathValidatorResult;
|
||||
import java.security.cert.PKIXParameters;
|
||||
import java.security.interfaces.DSAParams;
|
||||
import java.security.interfaces.DSAPublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.ConfirmationCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The <code>-import</code> keytool command handler is used to read an X.509
|
||||
* certificate, or a PKCS#7 Certificate Reply from a designated input source and
|
||||
* incorporate the certificates into the key store.
|
||||
* <p>
|
||||
* If the <i>Alias</i> does not already exist in the key store, the tool treats
|
||||
* the certificate read from the input source as a new Trusted Certificate. It
|
||||
* then attempts to discover a chain-of-trust, starting from that certificate
|
||||
* and ending at another <i>Trusted Certificate</i>, already stored in the key
|
||||
* store. If the <code>-trustcacerts</code> option is present, an additional
|
||||
* key store, of type <code>JKS</code> named <code>cacerts</code>, and assumed
|
||||
* to be present in <code>${JAVA_HOME}/lib/security</code> will also be
|
||||
* consulted if found --<code>${JAVA_HOME}</code> refers to the location of an
|
||||
* installed Java Runtime Environment (JRE). If no chain-of-trust can be
|
||||
* established, and unless the <code>-noprompt</code> option has been specified,
|
||||
* the certificate is printed to STDOUT and the user is prompted for a
|
||||
* confirmation.
|
||||
* <p>
|
||||
* If <i>Alias</i> exists in the key store, the tool will treat the
|
||||
* certificate(s) read from the input source as a <i>Certificate Reply</i>,
|
||||
* which can be a chain of certificates, that eventually would replace the chain
|
||||
* of certificates associated with the <i>Key Entry</i> of that <i>Alias</i>.
|
||||
* The substitution of the certificates only occurs if a chain-of-trust can be
|
||||
* established between the bottom certificate of the chain read from the input
|
||||
* file and the <i>Trusted Certificates</i> already present in the key store.
|
||||
* Again, if the <code>-trustcacerts</code> option is specified, additional
|
||||
* <i>Trusted Certificates</i> in the same <code>cacerts</code> key store will
|
||||
* be considered. If no chain-of-trust can be established, the operation will
|
||||
* abort.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-file FILE_NAME</dt>
|
||||
* <dd>The fully qualified path of the file to read from. If omitted, the
|
||||
* tool will process STDIN.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keypass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password which the tool will use to
|
||||
* protect the <i>Key Entry</i> associated with the designated <i>Alias</i>,
|
||||
* when replacing this <i>Alias</i>' chain of certificates with that found
|
||||
* in the certificate reply.
|
||||
* <p>
|
||||
* If this option is omitted, and the chain-of-trust for the certificate
|
||||
* reply has been established, the tool will first attempt to unlock the
|
||||
* <i>Key Entry</i> using the same password protecting the key store. If
|
||||
* this fails, you will then be prompted to provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-noprompt</dt>
|
||||
* <dd>Use this option to prevent the tool from prompting the user.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-trustcacerts</dt>
|
||||
* <dd>Use this option to indicate to the tool that a key store, of type
|
||||
* <code>JKS</code>, named <code>cacerts</code>, and usually located in
|
||||
* <code>lib/security</code> in an installed Java Runtime Environment
|
||||
* should be considered when trying to establish chain-of-trusts.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class ImportCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(ImportCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _certFileName;
|
||||
private String _password;
|
||||
private boolean noPrompt;
|
||||
private boolean trustCACerts;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private CertificateFactory x509Factory;
|
||||
private boolean imported;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the existing alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param pathName the fully qualified path name of the file to process. */
|
||||
public void setFile(String pathName)
|
||||
{
|
||||
this._certFileName = pathName;
|
||||
}
|
||||
|
||||
/** @param password the existing (private) key password to use. */
|
||||
public void setKeypass(String password)
|
||||
{
|
||||
this._password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flag whether to prompt, or not, the user to verify certificate
|
||||
* fingerprints.
|
||||
*/
|
||||
public void setNoprompt(String flag)
|
||||
{
|
||||
this.noPrompt = Boolean.valueOf(flag).booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flag whether to trust, or not, certificates found in the
|
||||
* <code>cacerts</code> key store.
|
||||
*/
|
||||
public void setTrustcacerts(String flag)
|
||||
{
|
||||
this.trustCACerts = Boolean.valueOf(flag).booleanValue();
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-file".equals(opt)) // -file FILE_NAME //$NON-NLS-1$
|
||||
_certFileName = args[++i];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
|
||||
_password = args[++i];
|
||||
else if ("-noprompt".equals(opt)) //$NON-NLS-1$
|
||||
noPrompt = true;
|
||||
else if ("-trustcacerts".equals(opt)) //$NON-NLS-1$
|
||||
trustCACerts = true;
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setInputStreamParam(_certFileName);
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
setKeyPasswordNoPrompt(_password);
|
||||
|
||||
log.finer("-import handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -file=" + _certFileName); //$NON-NLS-1$
|
||||
log.finer(" -keypass=" + _password); //$NON-NLS-1$
|
||||
log.finer(" -noprompt=" + noPrompt); //$NON-NLS-1$
|
||||
log.finer(" -trustcacerts=" + trustCACerts); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws CertificateException, KeyStoreException, IOException,
|
||||
UnsupportedCallbackException, NoSuchAlgorithmException,
|
||||
CertPathValidatorException, UnrecoverableKeyException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
x509Factory = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
|
||||
// the alias will tell us whether we're dealing with
|
||||
// a new trusted certificate or a certificate reply
|
||||
if (! store.containsAlias(alias))
|
||||
importNewTrustedCertificate();
|
||||
else
|
||||
{
|
||||
ensureAliasIsKeyEntry();
|
||||
importCertificateReply();
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* When importing a new trusted certificate, <i>alias</i> MUST NOT yet exist
|
||||
* in the key store.
|
||||
* <p>
|
||||
* Before adding the certificate to the key store and associate it with the
|
||||
* designated Alias, this method tries to verify it by attempting to construct
|
||||
* a chain of trust from that certificate to a self-signed certificate
|
||||
* (belonging to a root CA), using (already) trusted certificates that are
|
||||
* available in the key store.
|
||||
* <p>
|
||||
* If the <code>-trustcacerts</code> option was detected on the command
|
||||
* line, additional trusted certificates are considered for establishing the
|
||||
* chain of trust. Those additional certificates are assumed to be in a key
|
||||
* store, of type <code>JKS</code> named <code>cacerts</code> and usually
|
||||
* located in <code>${JAVA_HOME}/lib/security</code>, where
|
||||
* <code>${JAVA_HOME}</code> is the root folder location of a Java runtime.
|
||||
* <p>
|
||||
* If this method fails to establish a trust path from the certificate to be
|
||||
* imported up to a trusted self-signed certificate, the certificate is
|
||||
* printed to <code>STDOUT</code>, and the user is prompted to verify it,
|
||||
* with the option of aborting the import operation. If however the option
|
||||
* <code>-noprompt</code> was detected on the command line, no interaction
|
||||
* with the user will take place and the import operation will abort.
|
||||
*
|
||||
* @throws CertificateException
|
||||
* @throws KeyStoreException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws UnsupportedCallbackException
|
||||
* @throws IOException
|
||||
* @throws UnrecoverableKeyException
|
||||
* @throws CertPathValidatorException
|
||||
*/
|
||||
private void importNewTrustedCertificate() throws CertificateException,
|
||||
KeyStoreException, NoSuchAlgorithmException, IOException,
|
||||
UnsupportedCallbackException, CertPathValidatorException,
|
||||
UnrecoverableKeyException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "importNewTrustedCertificate"); //$NON-NLS-1$
|
||||
|
||||
Certificate certificate = x509Factory.generateCertificate(inStream);
|
||||
log.finest("certificate = " + certificate); //$NON-NLS-1$
|
||||
LinkedList orderedReply = new LinkedList();
|
||||
orderedReply.addLast(certificate);
|
||||
|
||||
if (findTrustAndUpdate(orderedReply, ! noPrompt))
|
||||
{
|
||||
store.setCertificateEntry(alias, certificate);
|
||||
System.out.println(Messages.getString("ImportCmd.29")); //$NON-NLS-1$
|
||||
saveKeyStore();
|
||||
}
|
||||
else
|
||||
System.out.println(Messages.getString("ImportCmd.28")); //$NON-NLS-1$
|
||||
|
||||
log.exiting(this.getClass().getName(), "importNewTrustedCertificate"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* A certificate reply is a certificate, whose Owner is stored in the key
|
||||
* store associated to the designated Alias, and now signed by supposedly a
|
||||
* trusted CA (Certificate Authority). In other words, the Subject in this
|
||||
* certificate reply is Alias's own and the Issuer is a CA.
|
||||
* <p>
|
||||
* When importing a certificate reply, the reply is validated using trusted
|
||||
* certificates from the key store, and optionally (if the option
|
||||
* <code>-trustcacerts</code> was detected on the command line) certificates
|
||||
* found in the key store, of type <code>JKS</code> named <code>cacerts</code>
|
||||
* located in <code>${JAVA_HOME}/lib/security</code>, where
|
||||
* <code>${JAVA_HOME}</code> is the root folder location of a Java runtime.
|
||||
*
|
||||
* @throws CertificateException
|
||||
* @throws UnsupportedCallbackException
|
||||
* @throws IOException
|
||||
* @throws KeyStoreException
|
||||
* @throws CertPathValidatorException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws UnrecoverableKeyException
|
||||
*/
|
||||
private void importCertificateReply() throws CertificateException,
|
||||
IOException, UnsupportedCallbackException, KeyStoreException,
|
||||
NoSuchAlgorithmException, CertPathValidatorException,
|
||||
UnrecoverableKeyException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "importCertificateReply"); //$NON-NLS-1$
|
||||
|
||||
Collection certificates = x509Factory.generateCertificates(inStream);
|
||||
ensureReplyIsOurs(certificates);
|
||||
// we now have established that the public keys are the same.
|
||||
// find a chain-of-trust if one exists
|
||||
if (certificates.size() == 1)
|
||||
importCertificate((Certificate) certificates.iterator().next());
|
||||
else
|
||||
importChain(certificates);
|
||||
|
||||
log.exiting(this.getClass().getName(), "importCertificateReply"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* If the reply is a single X.509 certificate, keytool attempts to establish a
|
||||
* trust chain, starting at the certificate reply and ending at a self-signed
|
||||
* certificate (belonging to a root CA). The certificate reply and the
|
||||
* hierarchy of certificates used to authenticate the certificate reply form
|
||||
* the new certificate chain of alias. If a trust chain cannot be established,
|
||||
* the certificate reply is not imported. In this case, keytool does not print
|
||||
* out the certificate, nor does it prompt the user to verify it. This is
|
||||
* because it is very hard (if not impossible) for a user to determine the
|
||||
* authenticity of the certificate reply.
|
||||
*
|
||||
* @param certificate the certificate reply to import into the key store.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws CertPathValidatorException
|
||||
* @throws UnsupportedCallbackException
|
||||
* @throws IOException
|
||||
* @throws UnrecoverableKeyException
|
||||
* @throws KeyStoreException
|
||||
* @throws CertificateException
|
||||
*/
|
||||
private void importCertificate(Certificate certificate)
|
||||
throws NoSuchAlgorithmException, CertPathValidatorException,
|
||||
KeyStoreException, UnrecoverableKeyException, IOException,
|
||||
UnsupportedCallbackException, CertificateException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "importCertificate", certificate); //$NON-NLS-1$
|
||||
|
||||
LinkedList reply = new LinkedList();
|
||||
reply.addLast(certificate);
|
||||
|
||||
if (! findTrustAndUpdate(reply, false))
|
||||
throw new CertPathValidatorException(Messages.getString("ImportCmd.34")); //$NON-NLS-1$
|
||||
|
||||
Certificate[] newChain = (Certificate[]) reply.toArray(new Certificate[0]);
|
||||
Key privateKey = getAliasPrivateKey();
|
||||
store.setKeyEntry(alias, privateKey, keyPasswordChars, newChain);
|
||||
saveKeyStore();
|
||||
|
||||
log.exiting(this.getClass().getName(), "importCertificate"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* If the reply is a PKCS#7 formatted certificate chain, the chain is first
|
||||
* ordered (with the user certificate first and the self-signed root CA
|
||||
* certificate last), before keytool attempts to match the root CA certificate
|
||||
* provided in the reply with any of the trusted certificates in the key store
|
||||
* or the "cacerts" keystore file (if the -trustcacerts option was specified).
|
||||
* If no match can be found, the information of the root CA certificate is
|
||||
* printed out, and the user is prompted to verify it, e.g., by comparing the
|
||||
* displayed certificate fingerprints with the fingerprints obtained from some
|
||||
* other (trusted) source of information, which might be the root CA itself.
|
||||
* The user then has the option of aborting the import operation. If the
|
||||
* -noprompt option is given, however, there will be no interaction with the
|
||||
* user.
|
||||
*
|
||||
* @param chain the collection of certificates parsed from the user
|
||||
* designated input.
|
||||
* @throws UnsupportedCallbackException
|
||||
* @throws IOException
|
||||
* @throws UnrecoverableKeyException
|
||||
* @throws KeyStoreException
|
||||
* @throws CertPathValidatorException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws CertificateException
|
||||
*/
|
||||
private void importChain(Collection chain) throws NoSuchAlgorithmException,
|
||||
CertPathValidatorException, KeyStoreException, UnrecoverableKeyException,
|
||||
IOException, UnsupportedCallbackException, CertificateException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "importChain", chain); //$NON-NLS-1$
|
||||
|
||||
LinkedList reply = orderChain(chain);
|
||||
if (findTrustAndUpdate(reply, ! noPrompt))
|
||||
{
|
||||
Certificate[] newChain = (Certificate[]) reply.toArray(new Certificate[0]);
|
||||
Key privateKey = getAliasPrivateKey();
|
||||
store.setKeyEntry(alias, privateKey, keyPasswordChars, newChain);
|
||||
saveKeyStore();
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "importChain"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to ensure that alias's public key is the subject of the first
|
||||
* certificate in the passed certificate collection. Throws an exception if
|
||||
* the public keys do not match.
|
||||
*
|
||||
* @param certificates a {@link Collection} of certificate replies (either a
|
||||
* signle certificate reply, or a PKCS#7 certificate reply chain)
|
||||
* usually sent by a CA as a response to a Certificate Signing
|
||||
* Request (CSR).
|
||||
* @throws IOException
|
||||
* @throws UnsupportedCallbackException
|
||||
* @throws KeyStoreException
|
||||
*/
|
||||
private void ensureReplyIsOurs(Collection certificates) throws IOException,
|
||||
UnsupportedCallbackException, KeyStoreException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "ensureReplyIsOurs"); //$NON-NLS-1$
|
||||
|
||||
Certificate certificate = (Certificate) certificates.iterator().next();
|
||||
log.finest("certificate = " + certificate); //$NON-NLS-1$
|
||||
Certificate[] chain = store.getCertificateChain(alias);
|
||||
if (chain == null)
|
||||
throw new IllegalArgumentException(Messages.getFormattedString("ImportCmd.37", //$NON-NLS-1$
|
||||
alias));
|
||||
Certificate anchor = chain[0];
|
||||
PublicKey anchorPublicKey = anchor.getPublicKey();
|
||||
PublicKey certPublicKey = certificate.getPublicKey();
|
||||
boolean sameKey;
|
||||
if (anchorPublicKey instanceof DSAPublicKey)
|
||||
{
|
||||
DSAPublicKey pk1 = (DSAPublicKey) anchorPublicKey;
|
||||
if (!(certPublicKey instanceof DSAPublicKey))
|
||||
throw new IllegalArgumentException(Messages.getString("ImportCmd.38")); //$NON-NLS-1$
|
||||
|
||||
sameKey = areEqual(pk1, (DSAPublicKey) certPublicKey);
|
||||
}
|
||||
else if (anchorPublicKey instanceof RSAPublicKey)
|
||||
{
|
||||
RSAPublicKey pk1 = (RSAPublicKey) anchorPublicKey;
|
||||
if (!(certPublicKey instanceof RSAPublicKey))
|
||||
throw new IllegalArgumentException(Messages.getString("ImportCmd.38")); //$NON-NLS-1$
|
||||
|
||||
sameKey = areEqual(pk1, (RSAPublicKey) certPublicKey);
|
||||
}
|
||||
else
|
||||
throw new IllegalArgumentException(
|
||||
Messages.getFormattedString("ImportCmd.40", //$NON-NLS-1$
|
||||
new String[] { alias,
|
||||
anchorPublicKey.getClass().getName() }));
|
||||
if (! sameKey)
|
||||
throw new IllegalArgumentException(Messages.getString("ImportCmd.41")); //$NON-NLS-1$
|
||||
|
||||
log.exiting(this.getClass().getName(), "ensureReplyIsOurs"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private boolean areEqual(DSAPublicKey pk1, DSAPublicKey pk2)
|
||||
{
|
||||
if (pk1.getY().compareTo(pk2.getY()) != 0)
|
||||
return false;
|
||||
|
||||
DSAParams p1 = pk1.getParams();
|
||||
DSAParams p2 = pk2.getParams();
|
||||
if (p1.getG().compareTo(p2.getG()) != 0)
|
||||
return false;
|
||||
|
||||
if (p1.getP().compareTo(p2.getP()) != 0)
|
||||
return false;
|
||||
|
||||
return p1.getQ().compareTo(p2.getQ()) == 0;
|
||||
}
|
||||
|
||||
private boolean areEqual(RSAPublicKey pk1, RSAPublicKey pk2)
|
||||
{
|
||||
if (pk1.getPublicExponent().compareTo(pk2.getPublicExponent()) != 0)
|
||||
return false;
|
||||
|
||||
return pk1.getModulus().compareTo(pk2.getModulus()) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param chain
|
||||
* @return the input collection, ordered with own certificate first, and CA's
|
||||
* self-signed certificate last.
|
||||
*/
|
||||
private LinkedList orderChain(Collection chain)
|
||||
{
|
||||
log.entering(this.getClass().getName(), "orderChain"); //$NON-NLS-1$
|
||||
|
||||
LinkedList result = new LinkedList();
|
||||
|
||||
|
||||
log.entering(this.getClass().getName(), "orderChain", result); //$NON-NLS-1$
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an ordered list of certificates, this method attempts to validate the
|
||||
* chain, and if successful, updates the key store entry for the designated
|
||||
* alias. The list of certificates is expected to be ordered as a chain, where
|
||||
* the first is the alias's own certificate and the last being a self-signed
|
||||
* CA certificate.
|
||||
* <p>
|
||||
* if <code>promptUser</code> is <code>true</code>, then even if no
|
||||
* anchor trust certificate is found, the user is prompted to approve, or not,
|
||||
* the import operation. On the other hand if the <code>promptUser</code>
|
||||
* parameter is <code>false</code> then this method will throw an exception
|
||||
* if no trust anchor is to be found.
|
||||
*
|
||||
* @param reply an ordered certificate path, where the last entry is the CA's
|
||||
* self-signed certificate.
|
||||
* @param promptUser a boolean flag indicating whether or not to prompt the
|
||||
* user for explicit trust in a CA certificate.
|
||||
* @return <code>true</code> if the validation succeeds; or <code>false</code>
|
||||
* otherwise.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws CertPathValidatorException
|
||||
* @throws UnsupportedCallbackException
|
||||
* @throws IOException
|
||||
* @throws UnrecoverableKeyException
|
||||
* @throws KeyStoreException
|
||||
* @throws CertificateEncodingException
|
||||
*/
|
||||
private boolean findTrustAndUpdate(LinkedList reply, boolean promptUser)
|
||||
throws IOException, NoSuchAlgorithmException, CertPathValidatorException,
|
||||
KeyStoreException, UnrecoverableKeyException, UnsupportedCallbackException,
|
||||
CertificateEncodingException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "findTrustAndUpdate"); //$NON-NLS-1$
|
||||
|
||||
X509CertPath certPath = new X509CertPath(reply);
|
||||
CertPathValidator validator = CertPathValidator.getInstance("PKIX"); //$NON-NLS-1$
|
||||
PKIXCertPathValidatorResult cpvr = findTrustInStore(certPath, validator);
|
||||
if (cpvr == null && trustCACerts)
|
||||
cpvr = findTrustInCACerts(certPath, validator);
|
||||
|
||||
boolean result = false;
|
||||
if (cpvr == null)
|
||||
{
|
||||
if (promptUser)
|
||||
{
|
||||
printVerbose((Certificate) reply.getLast());
|
||||
ConfirmationCallback ccb;
|
||||
ccb = new ConfirmationCallback(Messages.getString("ImportCmd.32"), //$NON-NLS-1$
|
||||
ConfirmationCallback.INFORMATION,
|
||||
ConfirmationCallback.YES_NO_OPTION,
|
||||
ConfirmationCallback.NO);
|
||||
getCallbackHandler().handle(new Callback[] { ccb });
|
||||
int answer = ccb.getSelectedIndex();
|
||||
result = answer == ConfirmationCallback.YES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.fine("Found a chain-of-trust anchored by " + cpvr.getTrustAnchor()); //$NON-NLS-1$
|
||||
Certificate trustedCert = cpvr.getTrustAnchor().getTrustedCert();
|
||||
reply.addLast(trustedCert);
|
||||
result = true;
|
||||
}
|
||||
|
||||
log.entering(this.getClass().getName(), "findTrustAndUpdate", //$NON-NLS-1$
|
||||
Boolean.valueOf(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
private PKIXCertPathValidatorResult findTrustInStore(X509CertPath certPath,
|
||||
CertPathValidator validator)
|
||||
{
|
||||
log.entering(this.getClass().getName(), "findTrustInStore"); //$NON-NLS-1$
|
||||
|
||||
PKIXCertPathValidatorResult result;
|
||||
try
|
||||
{
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
result = (PKIXCertPathValidatorResult) validator.validate(certPath, params);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
log.log(Level.FINE,
|
||||
"Exception in findTrustInStore(). Ignore + Return NULL", //$NON-NLS-1$
|
||||
x);
|
||||
result = null;
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "findTrustInStore", result); //$NON-NLS-1$
|
||||
return result;
|
||||
}
|
||||
|
||||
private PKIXCertPathValidatorResult findTrustInCACerts(X509CertPath certPath,
|
||||
CertPathValidator validator)
|
||||
{
|
||||
log.entering(this.getClass().getName(), "findTrustInCACerts"); //$NON-NLS-1$
|
||||
|
||||
FileInputStream stream = null;
|
||||
PKIXCertPathValidatorResult result = null;
|
||||
try
|
||||
{
|
||||
KeyStore cacerts = KeyStore.getInstance("jks"); //$NON-NLS-1$
|
||||
String cacertsPath = SystemProperties.getProperty("java.home");
|
||||
String fs = SystemProperties.getProperty("file.separator"); //$NON-NLS-1$
|
||||
cacertsPath = new StringBuilder(cacertsPath).append(fs)
|
||||
.append("lib").append(fs) //$NON-NLS-1$
|
||||
.append("security").append(fs) //$NON-NLS-1$
|
||||
.append("cacerts").toString(); //$NON-NLS-1$
|
||||
stream = new FileInputStream(cacertsPath);
|
||||
cacerts.load(stream, "changeit".toCharArray()); //$NON-NLS-1$
|
||||
PKIXParameters params = new PKIXParameters(cacerts);
|
||||
result = (PKIXCertPathValidatorResult) validator.validate(certPath,
|
||||
params);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
log.log(Level.FINE,
|
||||
"Exception in findTrustInCACerts(). Ignore + Return NULL", //$NON-NLS-1$
|
||||
x);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
try
|
||||
{
|
||||
stream.close();
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "findTrustInCACerts", result); //$NON-NLS-1$
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/* KeyCloneCmd.java -- The keyclone command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.TextOutputCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The <b>-keyclone</b> keytool command handler is used to clone an existing
|
||||
* key store entry associated with a designated alias, with its private key and
|
||||
* chain of certificates.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-dest ALIAS</dt>
|
||||
* <dd>Use this option to specify the new <i>Alias</i> which will be used
|
||||
* to identify the cloned copy of the <i>Key Entry</i>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keypass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password which the tool will use to
|
||||
* unlock the <i>Key Entry</i> associated with the designated <i>Alias</i>.
|
||||
* <p>
|
||||
* If this option is omitted, the tool will first attempt to unlock the
|
||||
* <i>Key Entry</i> using the same password protecting the key store. If
|
||||
* this fails, you will then be prompted to provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-new PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the private key
|
||||
* material of the newly cloned copy of the <i>Key Entry</i>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class KeyCloneCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(KeyCloneCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _destAlias;
|
||||
private String _password;
|
||||
private String _newPassword;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private String destinationAlias;
|
||||
private char[] newKeyPasswordChars;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the existing alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param alias the new alias to use. */
|
||||
public void setDest(String alias)
|
||||
{
|
||||
this._destAlias = alias;
|
||||
}
|
||||
|
||||
/** @param password the existing (private) key password to use. */
|
||||
public void setKeypass(String password)
|
||||
{
|
||||
this._password = password;
|
||||
}
|
||||
|
||||
/** @param password the new (private) key password to use. */
|
||||
public void setNew(String password)
|
||||
{
|
||||
this._newPassword = password;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-dest".equals(opt)) // -dest ALIAS //$NON-NLS-1$
|
||||
_destAlias = args[++i];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
|
||||
_password = args[++i];
|
||||
else if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
|
||||
_newPassword = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
setKeyPasswordNoPrompt(_password);
|
||||
setDestinationAlias(_destAlias);
|
||||
// setNewKeyPassword(_newPassword);
|
||||
|
||||
log.finer("-keyclone handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -dest=" + destinationAlias); //$NON-NLS-1$
|
||||
log.finer(" -keypass=" + _password); //$NON-NLS-1$
|
||||
log.finer(" -new=" + _newPassword); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
|
||||
UnsupportedCallbackException, UnrecoverableKeyException,
|
||||
CertificateException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
if (store.containsAlias(destinationAlias))
|
||||
throw new SecurityException(Messages.getString("KeyCloneCmd.23")); //$NON-NLS-1$
|
||||
|
||||
Key privateKey = getAliasPrivateKey();
|
||||
|
||||
setNewKeyPassword(_newPassword);
|
||||
Certificate[] chain = store.getCertificateChain(alias);
|
||||
|
||||
store.setKeyEntry(destinationAlias, privateKey, newKeyPasswordChars, chain);
|
||||
|
||||
saveKeyStore();
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
private void setDestinationAlias(String name) throws IOException,
|
||||
UnsupportedCallbackException
|
||||
{
|
||||
if (name == null || name.trim().length() == 0) // ask user to provide one
|
||||
{
|
||||
NameCallback ncb = new NameCallback(Messages.getString("KeyCloneCmd.26")); //$NON-NLS-1$
|
||||
getCallbackHandler().handle(new Callback[] { ncb });
|
||||
name = ncb.getName();
|
||||
if (name == null || name.trim().length() == 0)
|
||||
throw new IllegalArgumentException(Messages.getString("KeyCloneCmd.27")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
destinationAlias = name.trim();
|
||||
}
|
||||
|
||||
private void setNewKeyPassword(String password) throws IOException,
|
||||
UnsupportedCallbackException
|
||||
{
|
||||
if (password != null) // ask user to provide one
|
||||
newKeyPasswordChars = password.toCharArray();
|
||||
else
|
||||
{
|
||||
boolean ok = false;
|
||||
Callback[] prompts = new Callback[1];
|
||||
Callback[] errors = new Callback[1];
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
if (! ok)
|
||||
throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prompt4NewPassword(CallbackHandler handler,
|
||||
Callback[] prompts, Callback[] errors)
|
||||
throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
String p = Messages.getFormattedString("KeyCloneCmd.28", //$NON-NLS-1$
|
||||
new String[] { destinationAlias,
|
||||
String.valueOf(keyPasswordChars) });
|
||||
PasswordCallback pcb = new PasswordCallback(p, false);
|
||||
prompts[0] = pcb;
|
||||
handler.handle(prompts);
|
||||
char[] pwd1 = pcb.getPassword();
|
||||
pcb.clearPassword();
|
||||
if (pwd1 == null || pwd1.length == 0)
|
||||
{
|
||||
newKeyPasswordChars = (char[]) keyPasswordChars.clone();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pwd1.length < 6)
|
||||
{
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR,
|
||||
Messages.getString("StorePasswdCmd.21")); //$NON-NLS-1$
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
newKeyPasswordChars = pwd1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/* KeyPasswdCmd.java -- The keypasswd command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.TextOutputCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The <b>-keypasswd</b> keytool command handler is used to change the password
|
||||
* protecting the private key associated to a designated alias.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keypass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password which the tool will use to
|
||||
* unlock the <i>Key Entry</i> associated with the designated <i>Alias</i>.
|
||||
* <p>
|
||||
* If this option is omitted, the tool will first attempt to unlock the
|
||||
* <i>Key Entry</i> using the same password protecting the key store. If
|
||||
* this fails, you will then be prompted to provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-new PASSWORD</dt>
|
||||
* <dd>The new, and different, password which will be used to protect the
|
||||
* private key material of the designated Key Entry.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class KeyPasswdCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(KeyPasswdCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _password;
|
||||
private String _newPassword;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private char[] newPasswordChars;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param password the existing (private) key password to use. */
|
||||
public void setKeypass(String password)
|
||||
{
|
||||
this._password = password;
|
||||
}
|
||||
|
||||
/** @param password the new (private) key password to use. */
|
||||
public void setNew(String password)
|
||||
{
|
||||
this._newPassword = password;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
|
||||
_password = args[++i];
|
||||
else if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
|
||||
_newPassword = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
setKeyPasswordNoPrompt(_password);
|
||||
// setNewKeyPassword(_newPassword);
|
||||
|
||||
log.finer("-keypasswd handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -keypass=" + _password); //$NON-NLS-1$
|
||||
log.finer(" -new=" + _newPassword); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
|
||||
UnsupportedCallbackException, UnrecoverableKeyException,
|
||||
CertificateException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
// 1. get the key entry and certificate chain associated to alias
|
||||
Key privateKey = getAliasPrivateKey();
|
||||
Certificate[] chain = store.getCertificateChain(alias);
|
||||
|
||||
// 2. replace the old entry
|
||||
setNewKeyPassword(_newPassword);
|
||||
store.setKeyEntry(alias, privateKey, newPasswordChars, chain);
|
||||
|
||||
// 3. persist the key store
|
||||
saveKeyStore();
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the new password to use for protecting Alias's private key.
|
||||
*
|
||||
* @param password the new key password. if <code>null</code> prompt the
|
||||
* user to provide one. When prompting, the password is entered twice
|
||||
* and compared for a match.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
* @throws UnsupportedCallbackException if no implementation of a password
|
||||
* callback handler was found.
|
||||
*/
|
||||
private void setNewKeyPassword(String password) throws IOException,
|
||||
UnsupportedCallbackException
|
||||
{
|
||||
if (password != null)
|
||||
newPasswordChars = password.toCharArray();
|
||||
else
|
||||
{
|
||||
boolean ok = false;
|
||||
Callback[] prompts = new Callback[1];
|
||||
Callback[] errors = new Callback[1];
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
if (! ok)
|
||||
throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prompt4NewPassword(CallbackHandler handler,
|
||||
Callback[] prompts, Callback[] errors)
|
||||
throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
// prompt user (1st time) to provide one
|
||||
String p = Messages.getFormattedString("KeyPasswdCmd.24", alias); //$NON-NLS-1$
|
||||
PasswordCallback pcb = new PasswordCallback(p, false);
|
||||
prompts[0] = pcb;
|
||||
handler.handle(prompts);
|
||||
char[] pwd1 = pcb.getPassword();
|
||||
pcb.clearPassword();
|
||||
String ls = SystemProperties.getProperty("line.separator"); //$NON-NLS-1$
|
||||
if (pwd1 == null || pwd1.length < 6)
|
||||
{
|
||||
String m = Messages.getString("StorePasswdCmd.21") + ls; //$NON-NLS-1$
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Arrays.equals(keyPasswordChars, pwd1))
|
||||
{
|
||||
String m = Messages.getString("StorePasswdCmd.22") + ls; //$NON-NLS-1$
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
// prompt user (2nd time) for confirmation
|
||||
p = Messages.getFormattedString("KeyPasswdCmd.28", alias); //$NON-NLS-1$
|
||||
pcb = new PasswordCallback(p, false);
|
||||
prompts[0] = pcb;
|
||||
handler.handle(prompts);
|
||||
char[] pwd2 = pcb.getPassword();
|
||||
pcb.clearPassword();
|
||||
if (! Arrays.equals(pwd1, pwd2))
|
||||
{
|
||||
String m = Messages.getString("StorePasswdCmd.24") + ls; //$NON-NLS-1$
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
newPasswordChars = pwd2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
/* ListCmd.java -- The list command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.java.security.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The <b>-list</b> keytool command handler is used to output one or all key
|
||||
* store entries.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-rfc</dt>
|
||||
* <dd>Use RFC-1421 specifications when encoding the output.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Output the certificate in human-readable format. If both this option
|
||||
* and the <code>-rfc</code> option are detected on the command line, the
|
||||
* tool will opt for the human-readable form and will not abort the
|
||||
* command.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class ListCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(ListCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private boolean rfc;
|
||||
private boolean all;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flag whether to use, or not, RFC-1421 format when listing the
|
||||
* certificate(s).
|
||||
*/
|
||||
public void setRfc(String flag)
|
||||
{
|
||||
this.rfc = Boolean.valueOf(flag).booleanValue();
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
|
||||
_alias = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else if ("-rfc".equals(opt)) //$NON-NLS-1$
|
||||
rfc = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
all = _alias == null;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setOutputStreamParam(null); // use stdout
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
if (! all)
|
||||
setAliasParam(_alias);
|
||||
|
||||
if (verbose & rfc)
|
||||
{
|
||||
log.warning("Both -v and -rfc options were found on the command line. " //$NON-NLS-1$
|
||||
+ "Only the former will be considered"); //$NON-NLS-1$
|
||||
rfc = false;
|
||||
}
|
||||
|
||||
log.finer("-list handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -alias=" + alias); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
log.finer(" -rfc=" + rfc); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, CertificateEncodingException,
|
||||
IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
PrintWriter writer = new PrintWriter(outStream, true);
|
||||
writer.println(Messages.getFormattedString("ListCmd.21", store.getType())); //$NON-NLS-1$
|
||||
writer.println(Messages.getFormattedString("ListCmd.22", //$NON-NLS-1$
|
||||
store.getProvider().getName()));
|
||||
if (all)
|
||||
{
|
||||
log.finest("About to list all aliases in key store..."); //$NON-NLS-1$
|
||||
writer.println();
|
||||
writer.println(Messages.getFormattedString("ListCmd.24", //$NON-NLS-1$
|
||||
Integer.valueOf(store.size())));
|
||||
for (Enumeration e = store.aliases(); e.hasMoreElements(); )
|
||||
{
|
||||
String anAlias = (String) e.nextElement();
|
||||
if (anAlias != null)
|
||||
list1Alias(anAlias, writer);
|
||||
}
|
||||
}
|
||||
else
|
||||
list1Alias(alias, writer);
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Prints the certificate(s) associated with the designated alias.
|
||||
*
|
||||
* @param anAlias a non-null string denoting an alias in the key-store.
|
||||
* @param writer where to print.
|
||||
* @throws KeyStoreException if an exception occurs while obtaining the
|
||||
* certificate associated to the designated alias.
|
||||
* @throws CertificateEncodingException if an exception occurs while obtaining
|
||||
* the DER encoded form of the certificate.
|
||||
* @throws IOException if an I/O related exception occurs during the process.
|
||||
*/
|
||||
private void list1Alias(String anAlias, PrintWriter writer)
|
||||
throws KeyStoreException, CertificateEncodingException, IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "list1Alias", anAlias); //$NON-NLS-1$
|
||||
|
||||
writer.println();
|
||||
writer.println(Messages.getFormattedString("ListCmd.30", anAlias)); //$NON-NLS-1$
|
||||
writer.println(Messages.getFormattedString("ListCmd.31", store.getCreationDate(anAlias))); //$NON-NLS-1$
|
||||
|
||||
if (store.isCertificateEntry(anAlias))
|
||||
{
|
||||
writer.println(Messages.getString("ListCmd.32")); //$NON-NLS-1$
|
||||
Certificate certificate = store.getCertificate(anAlias);
|
||||
print1Certificate(certificate, writer);
|
||||
}
|
||||
else if (store.isKeyEntry(anAlias))
|
||||
{
|
||||
writer.println(Messages.getString("ListCmd.33")); //$NON-NLS-1$
|
||||
Certificate[] chain = store.getCertificateChain(anAlias);
|
||||
print1Chain(chain, writer);
|
||||
}
|
||||
else
|
||||
throw new IllegalArgumentException(Messages.getFormattedString("ListCmd.34", //$NON-NLS-1$
|
||||
anAlias));
|
||||
log.exiting(this.getClass().getName(), "list1Alias"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the designated certificate chain, or a fingerprint of the first
|
||||
* certificate (bottom) in the chain, depending on the values of the flags
|
||||
* <code>v</code> (for verbose) and <code>rfc</code>.
|
||||
* <p>
|
||||
* If both flags are <code>false</code>, only the fingerprint is generated,
|
||||
* otherwise, if the <code>v</code> flag is set, then a human readable output
|
||||
* is generated. If <code>rfc</code> is set, then an RFC-1421 like output
|
||||
* is generated.
|
||||
* <p>Note that both <code>v</code> and <code>rfc</code> cannot both be
|
||||
* <code>true</code> at the same time.
|
||||
*
|
||||
* @param chain the certificate chain to process.
|
||||
* @param writer where to print.
|
||||
* @throws CertificateEncodingException if an exception occurs while obtaining
|
||||
* the DER encoded form of the certificate.
|
||||
*/
|
||||
private void print1Chain(Certificate[] chain, PrintWriter writer)
|
||||
throws CertificateEncodingException
|
||||
{
|
||||
if (!verbose && !rfc)
|
||||
fingerprint(chain[0], writer);
|
||||
else
|
||||
{
|
||||
int limit = chain.length;
|
||||
writer.println(Messages.getFormattedString("ListCmd.38", //$NON-NLS-1$
|
||||
Integer.valueOf(limit)));
|
||||
writer.println(Messages.getString("ListCmd.39")); //$NON-NLS-1$
|
||||
print1Certificate(chain[0], writer);
|
||||
for (int i = 1; i < limit; i++)
|
||||
{
|
||||
writer.println();
|
||||
writer.println(Messages.getFormattedString("ListCmd.40", //$NON-NLS-1$
|
||||
Integer.valueOf(i + 1)));
|
||||
print1Certificate(chain[i], writer);
|
||||
}
|
||||
writer.println();
|
||||
writer.println(Messages.getString("ListCmd.42")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the designated certificate, or its fingerprint, depending on the
|
||||
* values of the flags <code>v</code> (for verbose) and <code>rfc</code>.
|
||||
* <p>
|
||||
* If both flags are <code>false</code>, only a fingerprint is generated,
|
||||
* otherwise, if the <code>v</code> flag is set, then a human readable output
|
||||
* is generated. If <code>rfc</code> is set, then an RFC-1421 like output
|
||||
* is generated.
|
||||
* <p>Note that both <code>v</code> and <code>rfc</code> cannot both be
|
||||
* <code>true</code> at the same time.
|
||||
*
|
||||
* @param certificate the certificate to process.
|
||||
* @param writer where to print.
|
||||
* @throws CertificateEncodingException if an exception occurs while obtaining
|
||||
* the DER encoded form of the certificate.
|
||||
*/
|
||||
private void print1Certificate(Certificate certificate, PrintWriter writer)
|
||||
throws CertificateEncodingException
|
||||
{
|
||||
if (verbose)
|
||||
printVerbose(certificate, writer);
|
||||
else if (rfc)
|
||||
printRFC1421(certificate, writer);
|
||||
else
|
||||
fingerprint(certificate, writer);
|
||||
}
|
||||
|
||||
private void printRFC1421(Certificate certificate, PrintWriter writer)
|
||||
throws CertificateEncodingException
|
||||
{
|
||||
byte[] derBytes = certificate.getEncoded();
|
||||
String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
|
||||
writer.println(Messages.getString("ListCmd.43")); //$NON-NLS-1$
|
||||
writer.println(encoded);
|
||||
writer.println(Messages.getString("ListCmd.44")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private void fingerprint(Certificate certificate, PrintWriter writer)
|
||||
throws CertificateEncodingException
|
||||
{
|
||||
byte[] derBytes = certificate.getEncoded();
|
||||
String fingerPrint = digestWithMD5(derBytes);
|
||||
writer.println(Messages.getFormattedString("ListCmd.45", fingerPrint)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/* Main.java -- Implementation of the keytool security tool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.classpath.tools.HelpPrinter;
|
||||
import gnu.classpath.tools.common.ProviderUtil;
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.javax.crypto.jce.GnuCrypto;
|
||||
import gnu.javax.security.auth.callback.GnuCallbacks;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The GNU Classpath implementation of the keytool security tool.
|
||||
* <p>
|
||||
* Except for the <code>-identitydb</code> command, available for importing
|
||||
* JDK 1.1 <i>identities</i> into a key store, this implementation is intended
|
||||
* to be compatible with the behaviour described in the public documentation of
|
||||
* the same tool included in JDK 1.4.
|
||||
*/
|
||||
public class Main
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(Main.class.getName());
|
||||
/** The relative file path to the command tool's help text. */
|
||||
private static final String HELP_PATH = "keytool/keytool.txt"; //$NON-NLS-1$
|
||||
/** The Preferences key name for the last issued certificate serial nbr. */
|
||||
static final String LAST_SERIAL_NUMBER = "lastSerialNumber"; //$NON-NLS-1$
|
||||
/** Constant denoting the X.509 certificate type. */
|
||||
static final String X_509 = "X.509"; //$NON-NLS-1$
|
||||
|
||||
/** Whether we have already printed the help text or not. */
|
||||
private boolean helpPrinted;
|
||||
/** The new position of GnuCRYPTO provider if it is not already installed. */
|
||||
private int gnuCryptoProviderNdx = -2;
|
||||
/** The new position of GNU Callbacks provider if it is not already installed. */
|
||||
private int gnuCallbacksNdx = -2;
|
||||
|
||||
private Main()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public static final void main(String[] args)
|
||||
{
|
||||
log.entering(Main.class.getName(), "main", args); //$NON-NLS-1$
|
||||
|
||||
Main tool = new Main();
|
||||
try
|
||||
{
|
||||
tool.setup();
|
||||
tool.start(args);
|
||||
}
|
||||
catch (SecurityException x)
|
||||
{
|
||||
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
|
||||
System.err.println(Messages.getString("Main.6") + x.getMessage()); //$NON-NLS-1$
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
|
||||
System.err.println(Messages.getString("Main.8") + x); //$NON-NLS-1$
|
||||
}
|
||||
finally
|
||||
{
|
||||
tool.teardown();
|
||||
}
|
||||
|
||||
log.exiting(Main.class.getName(), "main"); //$NON-NLS-1$
|
||||
// System.exit(0);
|
||||
}
|
||||
|
||||
// helper methods -----------------------------------------------------------
|
||||
|
||||
private void start(String[] args) throws Exception
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start", args); //$NON-NLS-1$
|
||||
|
||||
if (args == null)
|
||||
args = new String[0];
|
||||
|
||||
int limit = args.length;
|
||||
log.finest("args.length=" + limit); //$NON-NLS-1$
|
||||
int i = 0;
|
||||
String opt;
|
||||
Command cmd;
|
||||
while (i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
cmd = null;
|
||||
if ("-genkey".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new GenKeyCmd();
|
||||
else if ("-import".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new ImportCmd();
|
||||
else if ("-selfcert".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new SelfCertCmd();
|
||||
else if ("-identitydb".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new IdentityDBCmd();
|
||||
else if ("-certreq".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new CertReqCmd();
|
||||
else if ("-export".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new ExportCmd();
|
||||
else if ("-list".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new ListCmd();
|
||||
else if ("-printcert".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new PrintCertCmd();
|
||||
else if ("-keyclone".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new KeyCloneCmd();
|
||||
else if ("-storepasswd".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new StorePasswdCmd();
|
||||
else if ("-keypasswd".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new KeyPasswdCmd();
|
||||
else if ("-delete".equals(opt)) //$NON-NLS-1$
|
||||
cmd = new DeleteCmd();
|
||||
else if ("-help".equals(opt)) //$NON-NLS-1$
|
||||
{
|
||||
printHelp();
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.fine("Unknown command [" + opt + "] at index #" + i //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ ". Arguments from that token onward will be ignored"); //$NON-NLS-1$
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd != null)
|
||||
{
|
||||
i = cmd.processArgs(args, i);
|
||||
cmd.doCommand();
|
||||
}
|
||||
}
|
||||
|
||||
// the -help command is the default; i.e.
|
||||
// keytool
|
||||
// is equivalent to:
|
||||
// keytool -help
|
||||
if (i == 0)
|
||||
printHelp();
|
||||
|
||||
if (i < limit) // more options than needed
|
||||
log.fine("Last recognized argument is assumed at index #" + (i - 1) //$NON-NLS-1$
|
||||
+ ". Remaining arguments (" + args[i] + "...) will be ignored"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private void setup()
|
||||
{
|
||||
log.entering(this.getClass().getName(), "setup"); //$NON-NLS-1$
|
||||
|
||||
gnuCryptoProviderNdx = ProviderUtil.addProvider(new GnuCrypto());
|
||||
gnuCallbacksNdx = ProviderUtil.addProvider(new GnuCallbacks());
|
||||
|
||||
log.exiting(this.getClass().getName(), "setup"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private void teardown()
|
||||
{
|
||||
log.entering(this.getClass().getName(), "teardown"); //$NON-NLS-1$
|
||||
|
||||
// if we added our own providers remove them
|
||||
if (gnuCryptoProviderNdx > 0)
|
||||
ProviderUtil.removeProvider(Registry.GNU_CRYPTO);
|
||||
|
||||
if (gnuCallbacksNdx > 0)
|
||||
ProviderUtil.removeProvider("GNU-CALLBACKS"); //$NON-NLS-1$
|
||||
|
||||
log.exiting(this.getClass().getName(), "teardown"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private void printHelp()
|
||||
{
|
||||
if (helpPrinted)
|
||||
return;
|
||||
|
||||
HelpPrinter.printHelp(HELP_PATH);
|
||||
helpPrinted = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* Messages.java -- I18N related helper class
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* An initially generated Eclipse helper class to ease the use of localized
|
||||
* messages.
|
||||
* <p>
|
||||
* Enriched to handle localized message formats.
|
||||
*/
|
||||
class Messages
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(Messages.class.getName());
|
||||
private static final String BUNDLE_NAME = "gnu.classpath.tools.keytool.MessageBundle"; //$NON-NLS-1$
|
||||
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
|
||||
private static final Map CACHED_FORMATS = new HashMap(5);
|
||||
|
||||
private Messages()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public static String getString(String key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return RESOURCE_BUNDLE.getString(key);
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
return constructMessage(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFormattedString(String key, Object args)
|
||||
{
|
||||
MessageFormat mf = (MessageFormat) CACHED_FORMATS.get(key);
|
||||
if (mf == null)
|
||||
{
|
||||
String formatString = getString(key);
|
||||
if (formatString.startsWith("!"))
|
||||
return constructMessage(key, args);
|
||||
|
||||
mf = new MessageFormat(formatString);
|
||||
CACHED_FORMATS.put(key, mf);
|
||||
}
|
||||
|
||||
// if the argument is not an array, then build one consisiting of the
|
||||
// sole argument before passing it to the format() method
|
||||
try
|
||||
{
|
||||
if (args instanceof Object[])
|
||||
return mf.format(args);
|
||||
|
||||
return mf.format(new Object[] { args });
|
||||
}
|
||||
catch (IllegalArgumentException x)
|
||||
{
|
||||
log.fine("Exception while rendering a message format keyed by ["
|
||||
+ key + "]: " + mf.toPattern());
|
||||
return constructMessage(mf.toPattern(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String constructMessage(String m, Object args)
|
||||
{
|
||||
if (args == null)
|
||||
return '!' + m + '!';
|
||||
|
||||
return '!' + m + '!' + String.valueOf(args) + '!';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* PrintCertCmd.java -- The printcert command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The <b>-printcert</b> keytool command handler is used to read a certificate
|
||||
* from a designated file, and print its contents in a human-readable format.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-file FILE_NAME</dt>
|
||||
* <dd>The fully qualified path of the file to read the certificate from.
|
||||
* If this option is omitted, the tool will process STDIN.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class PrintCertCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(PrintCertCmd.class.getName());
|
||||
private String _certFileName;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param pathName the fully qualified path name of the file to process. */
|
||||
public void setFile(String pathName)
|
||||
{
|
||||
this._certFileName = pathName;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt);
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-file".equals(opt)) // -file FILE_NAME
|
||||
_certFileName = args[++i];
|
||||
else if ("-v".equals(opt))
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setInputStreamParam(_certFileName);
|
||||
|
||||
log.finer("-printcert handler will use the following options:");
|
||||
log.finer(" -file=" + _certFileName);
|
||||
log.finer(" -v=" + verbose);
|
||||
}
|
||||
|
||||
void start() throws CertificateException
|
||||
{
|
||||
log.entering(getClass().getName(), "start");
|
||||
|
||||
CertificateFactory x509Factory = CertificateFactory.getInstance(Main.X_509);
|
||||
Certificate certificate = x509Factory.generateCertificate(inStream);
|
||||
PrintWriter writer = new PrintWriter(System.out, true);
|
||||
writer.println();
|
||||
printVerbose(certificate, writer);
|
||||
|
||||
log.exiting(getClass().getName(), "start");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
/* SelfCertCmd.java -- The selfcert command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.java.security.x509.X500DistinguishedName;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/**
|
||||
* The <b>-selfcert</b> keytool command handler is used to generate a self-
|
||||
* signed X.509 version 1 certificate using key store credentials stored under a
|
||||
* designated alias.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-alias ALIAS</dt>
|
||||
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
|
||||
* Certificate</i>, in a key store is uniquely identified by a user-defined
|
||||
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
|
||||
* when referring to an entry in the key store. Unless specified otherwise,
|
||||
* a default value of <code>mykey</code> shall be used when this option is
|
||||
* omitted from the command line.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-sigalg ALGORITHM</dt>
|
||||
* <dd>The canonical name of the digital signature algorithm to use for
|
||||
* signing the certificate. If this option is omitted, a default value will
|
||||
* be chosen based on the type of the private key associated with the
|
||||
* designated <i>Alias</i>. If the private key is a <code>DSA</code> one,
|
||||
* the value for the signature algorithm will be <code>SHA1withDSA</code>.
|
||||
* If on the other hand the private key is an <code>RSA</code> one, then
|
||||
* the tool will use <code>MD5withRSA</code> as the signature algorithm.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-dname NAME</dt>
|
||||
* <dd>Use this option to specify the <i>Distinguished Name</i> of the
|
||||
* newly generated self-signed certificate. If this option is omitted, the
|
||||
* existing <i>Distinguished Name</i> of the base certificate in the chain
|
||||
* associated with the designated <i>Alias</i> will be used instead.
|
||||
* <p>
|
||||
* The syntax of a valid value for this option MUST follow RFC-2253
|
||||
* specifications. Namely the following components (with their accepted
|
||||
* meaning) will be recognized. Note that the component name is case-
|
||||
* insensitive:
|
||||
* <dl>
|
||||
* <dt>CN</dt>
|
||||
* <dd>The Common Name; e.g. "host.domain.com"</dd>
|
||||
*
|
||||
* <dt>OU</dt>
|
||||
* <dd>The Organizational Unit; e.g. "IT Department"</dd>
|
||||
*
|
||||
* <dt>O</dt>
|
||||
* <dd>The Organization Name; e.g. "The Sample Company"</dd>
|
||||
*
|
||||
* <dt>L</dt>
|
||||
* <dd>The Locality Name; e.g. "Sydney"</dd>
|
||||
*
|
||||
* <dt>ST</dt>
|
||||
* <dd>The State Name; e.g. "New South Wales"</dd>
|
||||
*
|
||||
* <dt>C</dt>
|
||||
* <dd>The 2-letter Country identifier; e.g. "AU"</dd>
|
||||
* </dl>
|
||||
* <p>
|
||||
* When specified with a <code>-dname</code> option, each pair of component
|
||||
* / value will be separated from the other with a comma. Each component
|
||||
* and value pair MUST be separated by an equal sign. For example, the
|
||||
* following is a valid DN value:
|
||||
* <pre>
|
||||
* CN=host.domain.com, O=The Sample Company, L=Sydney, ST=NSW, C=AU
|
||||
* </pre>
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-validity DAY_COUNT</dt>
|
||||
*
|
||||
* <dt>-keypass PASSWORD</dt>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class SelfCertCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(SelfCertCmd.class.getName());
|
||||
private String _alias;
|
||||
private String _sigAlgorithm;
|
||||
private String _dName;
|
||||
private String _password;
|
||||
private String _validityStr;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private X500DistinguishedName distinguishedName;
|
||||
private int validityInDays;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param alias the alias to use. */
|
||||
public void setAlias(String alias)
|
||||
{
|
||||
this._alias = alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param algorithm the canonical name of the digital signature algorithm to
|
||||
* use.
|
||||
*/
|
||||
public void setSigalg(String algorithm)
|
||||
{
|
||||
this._sigAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the distiniguished name of both the issuer and subject (since
|
||||
* we are dealing with a self-signed certificate) to use.
|
||||
*/
|
||||
public void setDname(String name)
|
||||
{
|
||||
this._dName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param days the string representation of the number of days (a decimal,
|
||||
* positive integer) to assign to the generated (self-signed)
|
||||
* certificate.
|
||||
*/
|
||||
public void setValidity(String days)
|
||||
{
|
||||
this._validityStr = days;
|
||||
}
|
||||
|
||||
/** @param password the (private) key password to use. */
|
||||
public void setKeypass(String password)
|
||||
{
|
||||
this._password = password;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt);
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-alias".equals(opt)) // -alias ALIAS
|
||||
_alias = args[++i];
|
||||
else if ("-sigalg".equals(opt)) // -sigalg ALGORITHM
|
||||
_sigAlgorithm = args[++i];
|
||||
else if ("-dname".equals(opt)) // -dname NAME
|
||||
_dName = args[++i];
|
||||
else if ("-keypass".equals(opt)) // -keypass PASSWORD
|
||||
_password = args[++i];
|
||||
else if ("-validity".equals(opt)) // -validity DAY_COUNT
|
||||
_validityStr = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt))
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setAliasParam(_alias);
|
||||
setKeyPasswordNoPrompt(_password);
|
||||
// setDName(_dName);
|
||||
setValidityParam(_validityStr);
|
||||
// setSignatureAlgorithm(_sigAlgorithm);
|
||||
|
||||
log.finer("-selfcert handler will use the following options:");
|
||||
log.finer(" -alias=" + alias);
|
||||
log.finer(" -sigalg=" + _sigAlgorithm);
|
||||
log.finer(" -dname=" + _dName);
|
||||
log.finer(" -keypass=" + _password);
|
||||
log.finer(" -validity=" + validityInDays);
|
||||
log.finer(" -storetype=" + storeType);
|
||||
log.finer(" -keystore=" + storeURL);
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars));
|
||||
log.finer(" -provider=" + provider);
|
||||
log.finer(" -v=" + verbose);
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, NoSuchAlgorithmException,
|
||||
UnrecoverableKeyException, IOException, UnsupportedCallbackException,
|
||||
InvalidKeyException, SignatureException, CertificateException
|
||||
{
|
||||
log.entering(getClass().getName(), "start");
|
||||
|
||||
// 1. get the key entry and certificate chain associated to alias
|
||||
Key privateKey = getAliasPrivateKey();
|
||||
Certificate[] chain = store.getCertificateChain(alias);
|
||||
|
||||
// 2. if the user has not supplied a DN use one from the certificate chain
|
||||
X509Certificate bottomCertificate = (X509Certificate) chain[0];
|
||||
X500Principal defaultPrincipal = bottomCertificate.getIssuerX500Principal();
|
||||
setDName(_dName, defaultPrincipal);
|
||||
|
||||
// 4. get alias's public key from certificate's SubjectPublicKeyInfo
|
||||
PublicKey publicKey = bottomCertificate.getPublicKey();
|
||||
|
||||
// 5. issue the self-signed certificate
|
||||
setSignatureAlgorithmParam(_sigAlgorithm, privateKey);
|
||||
|
||||
byte[] derBytes = getSelfSignedCertificate(distinguishedName,
|
||||
publicKey,
|
||||
(PrivateKey) privateKey);
|
||||
CertificateFactory x509Factory = CertificateFactory.getInstance("X.509");
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(derBytes);
|
||||
Certificate certificate = x509Factory.generateCertificate(bais);
|
||||
|
||||
// 6. store it, w/ its private key, associating them to alias
|
||||
chain = new Certificate[] { certificate };
|
||||
store.setKeyEntry(alias, privateKey, keyPasswordChars, chain);
|
||||
|
||||
// 7. persist the key store
|
||||
saveKeyStore();
|
||||
|
||||
log.exiting(getClass().getName(), "start");
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
private void setDName(String name, X500Principal defaultName)
|
||||
{
|
||||
if (name != null && name.trim().length() > 0)
|
||||
name = name.trim();
|
||||
else
|
||||
{
|
||||
// If dname is supplied at the command line, it is used as the X.500
|
||||
// Distinguished Name for both the issuer and subject of the certificate.
|
||||
// Otherwise, the X.500 Distinguished Name associated with alias (at the
|
||||
// bottom of its existing certificate chain) is used.
|
||||
name = defaultName.toString().trim();
|
||||
}
|
||||
|
||||
distinguishedName = new X500DistinguishedName(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/* StorePasswdCmd.java -- The storepasswd command handler of the keytool
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.keytool;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.TextOutputCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
/**
|
||||
* The <b>-storepasswd</b> keytool command handler is used to change the
|
||||
* password which protects the integrity of the key store.
|
||||
* <p>
|
||||
* Possible options for this command are:
|
||||
* <p>
|
||||
* <dl>
|
||||
* <dt>-new PASSWORD</dt>
|
||||
* <dd>The new, and different, password which will be used to protect the
|
||||
* designated key store.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storetype STORE_TYP}</dt>
|
||||
* <dd>Use this option to specify the type of the key store to use. The
|
||||
* default value, if this option is omitted, is that of the property
|
||||
* <code>keystore.type</code> in the security properties file, which is
|
||||
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
|
||||
* static method.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-keystore URL</dt>
|
||||
* <dd>Use this option to specify the location of the key store to use.
|
||||
* The default value is a file {@link java.net.URL} referencing the file
|
||||
* named <code>.keystore</code> located in the path returned by the call to
|
||||
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
|
||||
* as argument.
|
||||
* <p>
|
||||
* If a URL was specified, but was found to be malformed --e.g. missing
|
||||
* protocol element-- the tool will attempt to use the URL value as a file-
|
||||
* name (with absolute or relative path-name) of a key store --as if the
|
||||
* protocol was <code>file:</code>.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-storepass PASSWORD</dt>
|
||||
* <dd>Use this option to specify the password protecting the key store. If
|
||||
* this option is omitted from the command line, you will be prompted to
|
||||
* provide a password.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-provider PROVIDER_CLASS_NAME</dt>
|
||||
* <dd>A fully qualified class name of a Security Provider to add to the
|
||||
* current list of Security Providers already installed in the JVM in-use.
|
||||
* If a provider class is specified with this option, and was successfully
|
||||
* added to the runtime --i.e. it was not already installed-- then the tool
|
||||
* will attempt to removed this Security Provider before exiting.
|
||||
* <p></dd>
|
||||
*
|
||||
* <dt>-v</dt>
|
||||
* <dd>Use this option to enable more verbose output.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
class StorePasswdCmd extends Command
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(StorePasswdCmd.class.getName());
|
||||
private String _newPassword;
|
||||
private String _ksType;
|
||||
private String _ksURL;
|
||||
private String _ksPassword;
|
||||
private String _providerClassName;
|
||||
private char[] newStorePasswordChars;
|
||||
|
||||
// default 0-arguments constructor
|
||||
|
||||
// public setters -----------------------------------------------------------
|
||||
|
||||
/** @param password the new key-store password to use. */
|
||||
public void setNew(String password)
|
||||
{
|
||||
this._newPassword = password;
|
||||
}
|
||||
|
||||
/** @param type the key-store type to use. */
|
||||
public void setStoretype(String type)
|
||||
{
|
||||
this._ksType = type;
|
||||
}
|
||||
|
||||
/** @param url the key-store URL to use. */
|
||||
public void setKeystore(String url)
|
||||
{
|
||||
this._ksURL = url;
|
||||
}
|
||||
|
||||
/** @param password the key-store password to use. */
|
||||
public void setStorepass(String password)
|
||||
{
|
||||
this._ksPassword = password;
|
||||
}
|
||||
|
||||
/** @param className a security provider fully qualified class name to use. */
|
||||
public void setProvider(String className)
|
||||
{
|
||||
this._providerClassName = className;
|
||||
}
|
||||
|
||||
// life-cycle methods -------------------------------------------------------
|
||||
|
||||
int processArgs(String[] args, int i)
|
||||
{
|
||||
int limit = args.length;
|
||||
String opt;
|
||||
while (++i < limit)
|
||||
{
|
||||
opt = args[i];
|
||||
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (opt == null || opt.length() == 0)
|
||||
continue;
|
||||
|
||||
if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
|
||||
_newPassword = args[++i];
|
||||
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
|
||||
_ksType = args[++i];
|
||||
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
|
||||
_ksURL = args[++i];
|
||||
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
|
||||
_ksPassword = args[++i];
|
||||
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
|
||||
_providerClassName = args[++i];
|
||||
else if ("-v".equals(opt)) //$NON-NLS-1$
|
||||
verbose = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() throws Exception
|
||||
{
|
||||
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
|
||||
setNewKeystorePassword(_newPassword);
|
||||
|
||||
log.finer("-storepasswd handler will use the following options:"); //$NON-NLS-1$
|
||||
log.finer(" -new=" + String.valueOf(newStorePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
|
||||
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
|
||||
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
|
||||
log.finer(" -provider=" + provider); //$NON-NLS-1$
|
||||
log.finer(" -v=" + verbose); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
void start() throws KeyStoreException, NoSuchAlgorithmException,
|
||||
CertificateException, IOException
|
||||
{
|
||||
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
|
||||
|
||||
saveKeyStore(newStorePasswordChars);
|
||||
|
||||
log.exiting(getClass().getName(), "start"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// own methods --------------------------------------------------------------
|
||||
|
||||
protected void setNewKeystorePassword(String password) throws IOException,
|
||||
UnsupportedCallbackException
|
||||
{
|
||||
if (password != null)
|
||||
newStorePasswordChars = password.toCharArray();
|
||||
else
|
||||
{
|
||||
boolean ok = false;
|
||||
Callback[] prompts = new Callback[1];
|
||||
Callback[] errors = new Callback[1];
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
if (! ok)
|
||||
throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prompt4NewPassword(CallbackHandler handler,
|
||||
Callback[] prompts, Callback[] errors)
|
||||
throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
// prompt user (1st time) to provide one
|
||||
String p = Messages.getString("StorePasswdCmd.20"); //$NON-NLS-1$
|
||||
PasswordCallback pcb = new PasswordCallback(p, false);
|
||||
prompts[0] = pcb;
|
||||
handler.handle(prompts);
|
||||
char[] pwd1 = pcb.getPassword();
|
||||
pcb.clearPassword();
|
||||
String ls = SystemProperties.getProperty("line.separator"); //$NON-NLS-1$
|
||||
if (pwd1 == null || pwd1.length < 6)
|
||||
{
|
||||
String m = Messages.getString("StorePasswdCmd.21") + ls; //$NON-NLS-1$
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Arrays.equals(storePasswordChars, pwd1))
|
||||
{
|
||||
String m = Messages.getString("StorePasswdCmd.22") + ls; //$NON-NLS-1$
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
// prompt user (2nd time) for confirmation
|
||||
pcb = new PasswordCallback(Messages.getString("StorePasswdCmd.23"), false); //$NON-NLS-1$
|
||||
prompts[0] = pcb;
|
||||
handler.handle(prompts);
|
||||
char[] pwd2 = pcb.getPassword();
|
||||
pcb.clearPassword();
|
||||
if (! Arrays.equals(pwd1, pwd2))
|
||||
{
|
||||
String m = Messages.getString("StorePasswdCmd.24") + ls; //$NON-NLS-1$
|
||||
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
|
||||
handler.handle(errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
newStorePasswordChars = pwd2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/* PersistentBidiHasthable.java -- Constants for the persistent tables.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* The static fields, shared by the multiple classes, implementing the
|
||||
* persistent work.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public interface Persistent
|
||||
{
|
||||
/**
|
||||
* Sheduled termination task.
|
||||
*/
|
||||
static class ExitTask extends TimerTask
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The timer, sheduling all disk database update events, shared by all
|
||||
* instances.
|
||||
*/
|
||||
static Timer timer = new Timer(true);
|
||||
|
||||
/**
|
||||
* The longest time, in ms, after that the database content on the disk must
|
||||
* be updated. The algorithm is written to avoid the very frequent writings to
|
||||
* the disk.
|
||||
*/
|
||||
static long SAVE_AT_MOST_AFTER = 5000;
|
||||
|
||||
/**
|
||||
* States how long the database may stay not updated during the intensive
|
||||
* operations, in ms. Otherwise the intensively used structure may never
|
||||
* be stored to the disk.
|
||||
*/
|
||||
static long ALWAYS_UPDATE = 300000;
|
||||
|
||||
/**
|
||||
* Write the database content to the disk.
|
||||
*/
|
||||
void writeContent();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/* PersistentBidiHasthable.java -- Bidirectional persistent hash table.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi;
|
||||
|
||||
import gnu.classpath.tools.rmi.rmid.ActivationSystemImpl;
|
||||
import gnu.java.rmi.activation.BidiTable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* The persistent bidirectional hash table, maps both a to b and b to a. The
|
||||
* changes are written to dist after SAVE_AT_MOST_AFTER time from the latest
|
||||
* database change or at most after ALWAYS_UPDATE, if the database is updated
|
||||
* very frequently. To ensure that no information is lost, the shutdown method
|
||||
* must be called before exit.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public class PersistentBidiHashTable extends BidiTable implements
|
||||
Persistent
|
||||
{
|
||||
class WriteToDiskTask extends TimerTask
|
||||
{
|
||||
/**
|
||||
* Save the database.
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
writeContent();
|
||||
sheduled = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces instances of ActivationSystemImpl into the currently active
|
||||
* instance of the ActivationSystemImpl
|
||||
*/
|
||||
class AdaptedReader extends ObjectInputStream
|
||||
{
|
||||
AdaptedReader(InputStream in) throws IOException
|
||||
{
|
||||
super(in);
|
||||
enableResolveObject(true);
|
||||
}
|
||||
|
||||
protected Object resolveObject(Object obj) throws IOException
|
||||
{
|
||||
if (obj instanceof ActivationSystemImpl)
|
||||
return ActivationSystemImpl.singleton2;
|
||||
else
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The database file.
|
||||
*/
|
||||
File database;
|
||||
|
||||
/**
|
||||
* The currently sheduled write to disk task, null if none.
|
||||
*/
|
||||
WriteToDiskTask sheduled = null;
|
||||
|
||||
/**
|
||||
* The time, when the disk database was last updated.
|
||||
*/
|
||||
long lastUpdated;
|
||||
|
||||
/**
|
||||
* Create the unitialised instance that must be initalised when
|
||||
* ActivationSystemImpl.singleton2 is assigned.
|
||||
*/
|
||||
public PersistentBidiHashTable()
|
||||
{
|
||||
// Do not initalise the table fields - the initalise method must be
|
||||
// called later.
|
||||
super(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new persistent table that stores its information into the given
|
||||
* file. The ActivationSystemImpl.singleton2 must be assigned.
|
||||
*
|
||||
* @param file
|
||||
* the file, where the table stores its information.
|
||||
* @param coldStart
|
||||
* if true, the existing file with this name will be erased and
|
||||
* ignored. Otherwise, it will be assumed that the file contains the
|
||||
* persistent table information.
|
||||
*/
|
||||
public void init(File file, boolean coldStart)
|
||||
{
|
||||
try
|
||||
{
|
||||
database = file;
|
||||
if (database.exists())
|
||||
{
|
||||
if (coldStart)
|
||||
{
|
||||
k2v = new Hashtable();
|
||||
v2k = new Hashtable();
|
||||
database.delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
FileInputStream fi = new FileInputStream(file);
|
||||
BufferedInputStream b = new BufferedInputStream(fi);
|
||||
ObjectInputStream oin = new AdaptedReader(b);
|
||||
|
||||
k2v = (Map) oin.readObject();
|
||||
oin.close();
|
||||
|
||||
v2k = new Hashtable(k2v.size());
|
||||
|
||||
// Reguild v2k from k2v:
|
||||
Iterator en = k2v.keySet().iterator();
|
||||
Object key;
|
||||
while (en.hasNext())
|
||||
{
|
||||
key = en.next();
|
||||
v2k.put(k2v.get(key), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
k2v = new Hashtable();
|
||||
v2k = new Hashtable();
|
||||
}
|
||||
}
|
||||
catch (Exception ioex)
|
||||
{
|
||||
InternalError ierr = new InternalError("Unable to intialize with file "
|
||||
+ file);
|
||||
ierr.initCause(ioex);
|
||||
throw ierr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the database content to the disk.
|
||||
*/
|
||||
public synchronized void writeContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
FileOutputStream fou = new FileOutputStream(database);
|
||||
BufferedOutputStream b = new BufferedOutputStream(fou);
|
||||
ObjectOutputStream oout = new ObjectOutputStream(b);
|
||||
oout.writeObject(k2v);
|
||||
oout.close();
|
||||
}
|
||||
catch (Exception ioex)
|
||||
{
|
||||
InternalError ierr = new InternalError(
|
||||
"Failed to write database to disk: "
|
||||
+ database);
|
||||
ierr.initCause(ioex);
|
||||
throw ierr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the modified database as modified. The database will be written after
|
||||
* several seconds, unless another modification occurs.
|
||||
*/
|
||||
public void markDirty()
|
||||
{
|
||||
if (System.currentTimeMillis() - lastUpdated > ALWAYS_UPDATE)
|
||||
{
|
||||
// Force storing to disk under intensive operation.
|
||||
writeContent();
|
||||
lastUpdated = System.currentTimeMillis();
|
||||
if (sheduled != null)
|
||||
{
|
||||
sheduled.cancel();
|
||||
sheduled = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise coalesce the disk database copy update events.
|
||||
if (sheduled != null)
|
||||
sheduled.cancel();
|
||||
sheduled = new WriteToDiskTask();
|
||||
timer.schedule(sheduled, SAVE_AT_MOST_AFTER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current database state to the disk before exit.
|
||||
*/
|
||||
public void shutdown()
|
||||
{
|
||||
if (sheduled != null)
|
||||
{
|
||||
writeContent();
|
||||
sheduled = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the memory maps and mark as should be written to the disk.
|
||||
*/
|
||||
public void put(Object key, Object value)
|
||||
{
|
||||
super.put(key, value);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the memory maps and mark as should be written to the disk.
|
||||
*/
|
||||
public void removeKey(Object key)
|
||||
{
|
||||
super.removeKey(key);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/* PersistentHasthable.java -- Persistent hash table.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* The persistent hash table. The changes are written to dist after
|
||||
* SAVE_AT_MOST_AFTER time from the latest database change or at most after
|
||||
* ALWAYS_UPDATE, if the database is updated very frequently. To ensure that no
|
||||
* information is lost, the shutdown method must be called before exit.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public class PersistentHashTable
|
||||
extends Hashtable
|
||||
implements Serializable, Persistent
|
||||
{
|
||||
|
||||
/**
|
||||
* Use serialVersionUID for interoperability
|
||||
*/
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
class WriteToDiskTask extends TimerTask
|
||||
{
|
||||
/**
|
||||
* Save the database.
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
writeContent();
|
||||
sheduled = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The database file.
|
||||
*/
|
||||
File database;
|
||||
|
||||
/**
|
||||
* The currently sheduled write to disk task, null if none.
|
||||
*/
|
||||
WriteToDiskTask sheduled = null;
|
||||
|
||||
/**
|
||||
* The time, when the disk database was last updated.
|
||||
*/
|
||||
long lastUpdated;
|
||||
|
||||
/**
|
||||
* Setting to false prevents the automated disk update.
|
||||
* The initial value is true to prevent writing while reading and is set
|
||||
* to false in createInstance.
|
||||
*/
|
||||
transient boolean ready;
|
||||
|
||||
/**
|
||||
* Use static method to obtain the instance.
|
||||
*/
|
||||
private PersistentHashTable(File file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new NullPointerException("Null file provided");
|
||||
database = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new persistent table that stores its information into the given
|
||||
* file.
|
||||
*
|
||||
* @param file
|
||||
* the file, where the table stores its information.
|
||||
* @param coldStart
|
||||
* if true, the existing file with this name will be erased and
|
||||
* ignored. Otherwise, it will be assumed that the file contains the
|
||||
* persistent table information.
|
||||
*/
|
||||
public static Map createInstance(File file, boolean coldStart)
|
||||
{
|
||||
try
|
||||
{
|
||||
PersistentHashTable k2v;
|
||||
if (file.exists())
|
||||
{
|
||||
if (coldStart)
|
||||
{
|
||||
file.delete();
|
||||
k2v = new PersistentHashTable(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileInputStream fi = new FileInputStream(file);
|
||||
BufferedInputStream b = new BufferedInputStream(fi);
|
||||
ObjectInputStream oin = new ObjectInputStream(b);
|
||||
|
||||
k2v = (PersistentHashTable) oin.readObject();
|
||||
oin.close();
|
||||
}
|
||||
}
|
||||
else
|
||||
k2v = new PersistentHashTable(file);
|
||||
|
||||
k2v.ready = true;
|
||||
return k2v;
|
||||
}
|
||||
catch (Exception ioex)
|
||||
{
|
||||
InternalError ierr = new InternalError("Unable to intialize with file "
|
||||
+ file);
|
||||
ierr.initCause(ioex);
|
||||
throw ierr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write the database content to the disk.
|
||||
*/
|
||||
public synchronized void writeContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
FileOutputStream fou = new FileOutputStream(database);
|
||||
BufferedOutputStream b = new BufferedOutputStream(fou);
|
||||
ObjectOutputStream oout = new ObjectOutputStream(b);
|
||||
oout.writeObject(this);
|
||||
oout.close();
|
||||
}
|
||||
catch (Exception ioex)
|
||||
{
|
||||
InternalError ierr = new InternalError(
|
||||
"Failed to write database to disk: "+ database);
|
||||
ierr.initCause(ioex);
|
||||
throw ierr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the modified database as modified. The database will be written after
|
||||
* several seconds, unless another modification occurs.
|
||||
*/
|
||||
public void markDirty()
|
||||
{
|
||||
if (System.currentTimeMillis() - lastUpdated > ALWAYS_UPDATE)
|
||||
{
|
||||
// Force storing to disk under intensive operation.
|
||||
writeContent();
|
||||
lastUpdated = System.currentTimeMillis();
|
||||
if (sheduled != null)
|
||||
{
|
||||
sheduled.cancel();
|
||||
sheduled = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise coalesce the disk database copy update events.
|
||||
if (sheduled != null)
|
||||
sheduled.cancel();
|
||||
sheduled = new WriteToDiskTask();
|
||||
timer.schedule(sheduled, SAVE_AT_MOST_AFTER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current database state to the disk before exit.
|
||||
*/
|
||||
public void shutdown()
|
||||
{
|
||||
if (sheduled != null)
|
||||
{
|
||||
writeContent();
|
||||
sheduled = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the memory maps and mark as should be written to the disk.
|
||||
*/
|
||||
public Object put(Object key, Object value)
|
||||
{
|
||||
super.put(key, value);
|
||||
if (ready)
|
||||
markDirty();
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the memory maps and mark as should be written to the disk.
|
||||
*/
|
||||
public Object remove(Object key)
|
||||
{
|
||||
Object removed = super.remove(key);
|
||||
if (ready)
|
||||
markDirty();
|
||||
return removed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* REGISTY.java -- RMI registry starter.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi;
|
||||
|
||||
import gnu.classpath.tools.HelpPrinter;
|
||||
import gnu.classpath.tools.rmi.registry.RegistryImpl;
|
||||
import gnu.java.rmi.server.UnicastServerRef;
|
||||
|
||||
import java.io.File;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.rmi.server.ObjID;
|
||||
import java.rmi.server.RMIServerSocketFactory;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The optionally persistent RMI registry implementation.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public class REGISTRY
|
||||
{
|
||||
/**
|
||||
* The stop command.
|
||||
*/
|
||||
public static String STOP = "gnu.classpath.tools.rmi.registry.command.STOP";
|
||||
|
||||
/**
|
||||
* If true, the registry prints registration events to console.
|
||||
*/
|
||||
public static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* The RMI registry implementation entry point.
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String HelpPath = "rmi/REGISTRY.txt";
|
||||
HelpPrinter.checkHelpKey(args, HelpPath);
|
||||
|
||||
// Parse parameters:
|
||||
String folder = ".";
|
||||
boolean cold = false;
|
||||
boolean trans = false;
|
||||
boolean stop = false;
|
||||
|
||||
int port = Registry.REGISTRY_PORT;
|
||||
RMIServerSocketFactory ssf = null;
|
||||
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
String a = args[i];
|
||||
if (a.equals("-restart"))
|
||||
cold = true;
|
||||
else if (a.equals("-transient"))
|
||||
trans = true;
|
||||
else if (a.equals("-verbose"))
|
||||
verbose = true;
|
||||
else if (a.equals("-stop"))
|
||||
stop = true;
|
||||
else if (i < args.length - 1)
|
||||
{
|
||||
// The additional key parameter is possible.
|
||||
if (a.equals("-port"))
|
||||
port = Integer.parseInt(args[++i]);
|
||||
else if (a.equals("-folder"))
|
||||
folder = args[++i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!stop)
|
||||
{
|
||||
Map table;
|
||||
if (trans)
|
||||
table = new Hashtable();
|
||||
else
|
||||
{
|
||||
// Start the system.
|
||||
File dataFolder = new File(folder);
|
||||
if (!dataFolder.exists())
|
||||
dataFolder.mkdirs();
|
||||
table = PersistentHashTable.createInstance(
|
||||
new File(dataFolder, "rmiregistry.data"), cold);
|
||||
}
|
||||
|
||||
RegistryImpl system = new RegistryImpl(table);
|
||||
|
||||
// We must export with the specific activation id that is only
|
||||
// possible when going into the gnu.java.rmi
|
||||
try
|
||||
{
|
||||
UnicastServerRef sref = new UnicastServerRef(
|
||||
new ObjID(ObjID.REGISTRY_ID), port, ssf);
|
||||
|
||||
sref.exportObject(system);
|
||||
System.out.println("The RMI naming service is listening at " + port);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.out.println("Failed to start RMI naming service at " + port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stop the naming service.
|
||||
try
|
||||
{
|
||||
Registry r = LocateRegistry.getRegistry(port);
|
||||
// Search for this specific line will command to stop the registry.
|
||||
|
||||
// Our service returns null, but any other service will thrown
|
||||
// NotBoundException.
|
||||
r.unbind(STOP);
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
System.out.println("Failed to stop RMI naming service at " + port);
|
||||
}
|
||||
catch (NotBoundException e)
|
||||
{
|
||||
System.out.println("The naming service at port "+port+" is not a "+
|
||||
REGISTRY.class.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
The persistent RMI naming service, required for the remote method invocations
|
||||
(packages java.rmi.*, java.rmi.Registry.*).
|
||||
|
||||
Copyright 2006 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Please report bugs at http://www.gnu.org/software/classpath/bugs.html
|
||||
|
||||
Usage: rmiregistry <options>
|
||||
|
||||
where <options> includes:
|
||||
-port N Start the registry on the given local port. If this key
|
||||
is not specified, the service starts on the port 1099.
|
||||
-verbose Log binding events to stdout.
|
||||
-stop Stop the running naming service at the given port.
|
||||
|
||||
-transient Start transient registry service that does not write any
|
||||
data to the disk. Such service looses the stored bindings if
|
||||
restarted. If this key is not specified, the
|
||||
persistent naming service is started.
|
||||
-restart "Cold start:, clear the persistent naming database, if any.
|
||||
-folder Folder Store the persistent binding file in the given folder. If this
|
||||
key is not specified, the file with persistent bindings is
|
||||
stored into the current folder.
|
||||
|
||||
|
||||
|
||||
@@ -17,30 +17,13 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi;
|
||||
|
||||
import gnu.classpath.tools.HelpPrinter;
|
||||
import gnu.classpath.tools.giop.GRMIC;
|
||||
import gnu.classpath.tools.giop.grmic.GiopRmicCompiler;
|
||||
import gnu.classpath.tools.rmi.rmic.RmicCompiler;
|
||||
|
||||
import java.io.File;
|
||||
@@ -114,6 +97,10 @@ public class RMIC
|
||||
verbose = true;
|
||||
compiler.setVerbose(true);
|
||||
}
|
||||
else if (c.equals("-force"))
|
||||
{
|
||||
compiler.setForce(true);
|
||||
}
|
||||
else if (c.equals("-d"))
|
||||
{
|
||||
int f = i + 1;
|
||||
|
||||
@@ -16,6 +16,8 @@ Usage: rmic <options> <class names>
|
||||
-help Print this help text
|
||||
-v Print version
|
||||
-verbose Verbose output
|
||||
-force Try to generate code even if the input classes seem not
|
||||
consistent with RMI specification.
|
||||
|
||||
-1.2 Generate v 1.2 stubs (default)*
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/* RMID.java -- the RMI activation daemon.
|
||||
Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi;
|
||||
|
||||
import gnu.classpath.tools.HelpPrinter;
|
||||
import gnu.classpath.tools.rmi.rmid.ActivationSystemImpl;
|
||||
import gnu.java.rmi.activation.ActivationSystemTransient;
|
||||
import gnu.java.rmi.server.UnicastServerRef;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.activation.ActivationSystem;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.rmi.server.ObjID;
|
||||
import java.rmi.server.RMIServerSocketFactory;
|
||||
|
||||
|
||||
/**
|
||||
* The persistent RMI activation daemon.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public class RMID
|
||||
{
|
||||
/**
|
||||
* The RMI server socket factory.
|
||||
*/
|
||||
static RMIServerSocketFactory ACTIVATION_REGISTY_SOCKET_FACTORY = null;
|
||||
|
||||
/**
|
||||
* The activation registry port.
|
||||
*/
|
||||
static int ACTIVATION_REGISTRY_PORT = ActivationSystem.SYSTEM_PORT;
|
||||
|
||||
/**
|
||||
* The activation system name.
|
||||
*/
|
||||
static String ACTIVATION_SYSTEM_NAME = "java.rmi.activation.ActivationSystem";
|
||||
|
||||
/**
|
||||
* The RMI activation daemon entry point.
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String HelpPath = "rmi/RMID.txt";
|
||||
HelpPrinter.checkHelpKey(args, HelpPath);
|
||||
|
||||
// Parse parameters:
|
||||
boolean stop = false;
|
||||
String folder = ".";
|
||||
boolean cold = false;
|
||||
boolean trans = false;
|
||||
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
String a = args[i];
|
||||
if (a.equals("-verbose"))
|
||||
ActivationSystemTransient.debug = true;
|
||||
else if (a.equals("-stop"))
|
||||
stop = true;
|
||||
else if (a.equals("-restart"))
|
||||
cold = true;
|
||||
else if (a.equals("-transient"))
|
||||
trans = true;
|
||||
else if (i < args.length - 1)
|
||||
{
|
||||
// The additional key parameter is possible.
|
||||
if (a.equals("-port"))
|
||||
ACTIVATION_REGISTRY_PORT = Integer.parseInt(args[++i]);
|
||||
else if (a.equals("-folder"))
|
||||
folder = args[++i];
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
// Start the system.
|
||||
File dataFolder = new File(folder);
|
||||
if (!dataFolder.exists())
|
||||
dataFolder.mkdirs();
|
||||
ActivationSystem system;
|
||||
|
||||
if (trans)
|
||||
system = ActivationSystemTransient.getInstance();
|
||||
else
|
||||
system = ActivationSystemImpl.getInstance(dataFolder, cold);
|
||||
|
||||
// We must export with the specific activation id that is only
|
||||
// possible when going into the gnu.java.rmi.activation.
|
||||
UnicastServerRef sref = new UnicastServerRef(
|
||||
new ObjID(ObjID.ACTIVATOR_ID), ACTIVATION_REGISTRY_PORT,
|
||||
ACTIVATION_REGISTY_SOCKET_FACTORY);
|
||||
Remote systemStub = sref.exportObject(system);
|
||||
|
||||
// Start the naming system on the activation system port
|
||||
// (if not already running).
|
||||
|
||||
Registry r;
|
||||
try
|
||||
{
|
||||
// Expect the naming service running first.
|
||||
// The local host may want to use the shared registry
|
||||
r = LocateRegistry.getRegistry(ACTIVATION_REGISTRY_PORT);
|
||||
r.rebind(ACTIVATION_SYSTEM_NAME, systemStub);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// The naming service is not running. Start it.
|
||||
r = LocateRegistry.createRegistry(ACTIVATION_REGISTRY_PORT);
|
||||
r.rebind(ACTIVATION_SYSTEM_NAME, systemStub);
|
||||
}
|
||||
String host = InetAddress.getLocalHost().getCanonicalHostName();
|
||||
System.out.println("The RMI daemon is listening on " + host +
|
||||
" (port "
|
||||
+ ACTIVATION_REGISTRY_PORT + ")");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stop the activation system.
|
||||
Registry r;
|
||||
try
|
||||
{
|
||||
System.out.print("Stopping RMI daemon at "
|
||||
+ ACTIVATION_REGISTRY_PORT+" ... ");
|
||||
// Expect the naming service running first.
|
||||
// The local host may want to use the shared registry
|
||||
r = LocateRegistry.getRegistry(ACTIVATION_REGISTRY_PORT);
|
||||
ActivationSystem asys =
|
||||
(ActivationSystem) r.lookup(ACTIVATION_SYSTEM_NAME);
|
||||
asys.shutdown();
|
||||
System.out.println("OK.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.out.println("The RMI daemon seems not running at "
|
||||
+ ACTIVATION_REGISTRY_PORT);
|
||||
if (ActivationSystemTransient.debug)
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Failed to start the RMI daemon.");
|
||||
if (ActivationSystemTransient.debug)
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
The persistent RMI activation daemon, support RMI object activation
|
||||
(package java.rmi.activation.*).
|
||||
|
||||
Copyright 2006 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Please report bugs at http://www.gnu.org/software/classpath/bugs.html
|
||||
|
||||
Usage: rmid <options>
|
||||
|
||||
where <options> includes:
|
||||
-port N Start the service on the given local port. If this key
|
||||
is not specified, the service starts on the port 1098.
|
||||
-verbose Log registration events to stdout.
|
||||
-stop Stop the running activation service at the given port.
|
||||
|
||||
-transient Start transient activation service that does not write any
|
||||
data to the disk. Such service looses the stored activation
|
||||
descriptors, if restarted. If this key is not specified, the
|
||||
persistent naming service is started.
|
||||
-restart "Cold start:, clear the activation descriptor database, if any.
|
||||
-folder Folder Store the persistent descriptor file in the given folder. If this
|
||||
key is not specified, the file with persistent activation
|
||||
information is stored into the current folder.
|
||||
|
||||
All activation groups are activated on the same virtual machine, where the
|
||||
daemon is running. For security reasons, all the classes, required for
|
||||
activation, must be available in the classpath of that machine.
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/* RegistryImpl.java -- the RMI registry implementation
|
||||
Copyright (c) 1996, 1997, 1998, 1999, 2002, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi.registry;
|
||||
|
||||
import gnu.classpath.tools.rmi.Persistent;
|
||||
import gnu.classpath.tools.rmi.REGISTRY;
|
||||
|
||||
import java.rmi.AccessException;
|
||||
import java.rmi.AlreadyBoundException;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The optionally persistent registry implementation.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public class RegistryImpl implements Registry
|
||||
{
|
||||
/**
|
||||
* The binding table.
|
||||
*/
|
||||
Map bindings;
|
||||
|
||||
/**
|
||||
* Create the registry implementation that uses the given bidirectinal
|
||||
* table to keep the data.
|
||||
*/
|
||||
public RegistryImpl(Map aTable)
|
||||
{
|
||||
bindings = aTable;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public Remote lookup(String name) throws RemoteException, NotBoundException,
|
||||
AccessException
|
||||
{
|
||||
Object obj = bindings.get(name);
|
||||
if (obj == null)
|
||||
throw new NotBoundException(name);
|
||||
return ((Remote) obj);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void bind(String name, Remote obj) throws RemoteException,
|
||||
AlreadyBoundException, AccessException
|
||||
{
|
||||
if (REGISTRY.verbose)
|
||||
System.out.println("Bind "+name);
|
||||
if (bindings.containsKey(name))
|
||||
throw new AlreadyBoundException(name);
|
||||
bindings.put(name, obj);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void unbind(String name) throws RemoteException, NotBoundException,
|
||||
AccessException
|
||||
{
|
||||
if (name.equals(REGISTRY.STOP))
|
||||
{
|
||||
if (bindings instanceof Persistent)
|
||||
((Persistent) bindings).writeContent();
|
||||
// Terminate in 10 seconds.
|
||||
System.out.println("Shutdown command received. Will terminate in 10 s");
|
||||
Persistent.timer.schedule(new Persistent.ExitTask(), 10000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (REGISTRY.verbose)
|
||||
System.out.println("Unbind "+name);
|
||||
|
||||
if (!bindings.containsKey(name))
|
||||
throw new NotBoundException(name);
|
||||
else
|
||||
bindings.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void rebind(String name, Remote obj) throws RemoteException,
|
||||
AccessException
|
||||
{
|
||||
if (REGISTRY.verbose)
|
||||
System.out.println("Rebind "+name);
|
||||
bindings.put(name, obj);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public String[] list() throws RemoteException, AccessException
|
||||
{
|
||||
// Create a separated array to prevent race conditions.
|
||||
ArrayList keys = new ArrayList(bindings.keySet());
|
||||
int n = keys.size();
|
||||
String[] rt = new String[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
rt[i] = (String) keys.get(i);
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/* RegistryImpl_Skel.java
|
||||
Copyright (C) 2002, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi.registry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.rmi.MarshalException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.UnmarshalException;
|
||||
import java.rmi.server.Operation;
|
||||
import java.rmi.server.RemoteCall;
|
||||
import java.rmi.server.SkeletonMismatchException;
|
||||
|
||||
/**
|
||||
* This skeleton supports unlikely cases when the naming service is
|
||||
* contacted from other interoperable java implementation that still uses
|
||||
* the old style skeleton-dependent invocations.
|
||||
*/
|
||||
public final class RegistryImpl_Skel
|
||||
implements java.rmi.server.Skeleton
|
||||
{
|
||||
private static final long interfaceHash = 4905912898345647071L;
|
||||
|
||||
/**
|
||||
* Repeated multiple times.
|
||||
*/
|
||||
static final String EUM = "error unmarshalling arguments for Registry";
|
||||
|
||||
/**
|
||||
* Repeated multiple times.
|
||||
*/
|
||||
static final String EMR = "error marshalling return from Registry";
|
||||
|
||||
private static final Operation[] operations =
|
||||
{
|
||||
new Operation("void bind(java.lang.String, Remote"),
|
||||
new Operation("java.lang.String[] list("),
|
||||
new Operation("Remote lookup(java.lang.String"),
|
||||
new Operation("void rebind(java.lang.String, Remote"),
|
||||
new Operation("void unbind(java.lang.String")
|
||||
};
|
||||
|
||||
public Operation[] getOperations()
|
||||
{
|
||||
return ((Operation[]) operations.clone());
|
||||
}
|
||||
|
||||
public void dispatch(Remote obj, RemoteCall call,
|
||||
int opnum, long hash) throws java.lang.Exception
|
||||
{
|
||||
if (opnum < 0)
|
||||
{
|
||||
if (hash == 7583982177005850366L)
|
||||
opnum = 0;
|
||||
else if (hash == 2571371476350237748L)
|
||||
opnum = 1;
|
||||
else if (hash == -7538657168040752697L)
|
||||
opnum = 2;
|
||||
else if (hash == -8381844669958460146L)
|
||||
opnum = 3;
|
||||
else if (hash == 7305022919901907578L)
|
||||
opnum = 4;
|
||||
else
|
||||
throw new SkeletonMismatchException("interface hash mismatch");
|
||||
}
|
||||
else if (hash != interfaceHash)
|
||||
throw new SkeletonMismatchException("interface hash mismatch");
|
||||
|
||||
RegistryImpl server = (RegistryImpl) obj;
|
||||
switch (opnum)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
java.lang.String $param_0;
|
||||
Remote $param_1;
|
||||
try
|
||||
{
|
||||
ObjectInput in = call.getInputStream();
|
||||
$param_0 = (java.lang.String) in.readObject();
|
||||
$param_1 = (Remote) in.readObject();
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
catch (java.lang.ClassCastException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
call.releaseInputStream();
|
||||
}
|
||||
server.bind($param_0, $param_1);
|
||||
try
|
||||
{
|
||||
ObjectOutput out = call.getResultStream(true);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new MarshalException(EMR, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
try
|
||||
{
|
||||
ObjectInput in = call.getInputStream();
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
call.releaseInputStream();
|
||||
}
|
||||
java.lang.String[] $result = server.list();
|
||||
try
|
||||
{
|
||||
ObjectOutput out = call.getResultStream(true);
|
||||
out.writeObject($result);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new MarshalException(EMR, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
java.lang.String $param_0;
|
||||
try
|
||||
{
|
||||
ObjectInput in = call.getInputStream();
|
||||
$param_0 = (java.lang.String) in.readObject();
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
catch (java.lang.ClassCastException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
call.releaseInputStream();
|
||||
}
|
||||
Remote $result = server.lookup($param_0);
|
||||
try
|
||||
{
|
||||
ObjectOutput out = call.getResultStream(true);
|
||||
out.writeObject($result);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new MarshalException(EMR, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
java.lang.String $param_0;
|
||||
Remote $param_1;
|
||||
try
|
||||
{
|
||||
ObjectInput in = call.getInputStream();
|
||||
$param_0 = (java.lang.String) in.readObject();
|
||||
$param_1 = (Remote) in.readObject();
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
catch (java.lang.ClassCastException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
call.releaseInputStream();
|
||||
}
|
||||
server.rebind($param_0, $param_1);
|
||||
try
|
||||
{
|
||||
ObjectOutput out = call.getResultStream(true);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new MarshalException(EMR, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
java.lang.String $param_0;
|
||||
try
|
||||
{
|
||||
ObjectInput in = call.getInputStream();
|
||||
$param_0 = (java.lang.String) in.readObject();
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
catch (java.lang.ClassCastException e)
|
||||
{
|
||||
throw new UnmarshalException(EUM, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
call.releaseInputStream();
|
||||
}
|
||||
server.unbind($param_0);
|
||||
try
|
||||
{
|
||||
ObjectOutput out = call.getResultStream(true);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new MarshalException(EMR, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new UnmarshalException("invalid method number");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/* RegistryImpl_Stub.java -- Registry stub.
|
||||
Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi.registry;
|
||||
|
||||
import java.rmi.AccessException;
|
||||
import java.rmi.AlreadyBoundException;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.Registry;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.rmi.server.RemoteRef;
|
||||
import java.rmi.server.RemoteStub;
|
||||
import java.rmi.UnexpectedException;
|
||||
|
||||
/**
|
||||
* This class delegates its method calls to the remote RMI object, referenced
|
||||
* by {@link RemoteRef}.
|
||||
*
|
||||
* It is normally generated with rmic.
|
||||
*/
|
||||
public final class RegistryImpl_Stub
|
||||
extends RemoteStub
|
||||
implements Registry
|
||||
{
|
||||
/**
|
||||
* Use serialVersionUID for interoperability
|
||||
*/
|
||||
private static final long serialVersionUID = 3;
|
||||
|
||||
/**
|
||||
* The explaining message for {@ling UnexpectedException}.
|
||||
*/
|
||||
private static final String exception_message =
|
||||
"undeclared checked exception";
|
||||
|
||||
/* All remote methods, invoked by this stub: */
|
||||
private static final Method met_list;
|
||||
private static final Method met_rebind;
|
||||
private static final Method met_unbind;
|
||||
private static final Method met_lookup;
|
||||
private static final Method met_bind;
|
||||
private static final Object[] NO_ARGS = new Object[0];
|
||||
static
|
||||
{
|
||||
final Class[] NO_ARGSc = new Class[0];
|
||||
try
|
||||
{
|
||||
met_list =
|
||||
Registry.class.getMethod("list", NO_ARGSc);
|
||||
met_rebind =
|
||||
Registry.class.getMethod("rebind", new Class[]
|
||||
{
|
||||
String.class, Remote.class
|
||||
});
|
||||
met_unbind =
|
||||
Registry.class.getMethod("unbind", new Class[]
|
||||
{
|
||||
String.class
|
||||
});
|
||||
met_lookup =
|
||||
Registry.class.getMethod("lookup", new Class[]
|
||||
{
|
||||
String.class
|
||||
});
|
||||
met_bind =
|
||||
Registry.class.getMethod("bind", new Class[]
|
||||
{
|
||||
String.class, Remote.class
|
||||
});
|
||||
|
||||
}
|
||||
catch (NoSuchMethodException nex)
|
||||
{
|
||||
NoSuchMethodError err = new NoSuchMethodError(
|
||||
"RegistryImpl_Stub class initialization failed");
|
||||
err.initCause(nex);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the instance for _RegistryImpl_Stub that forwards method calls to the
|
||||
* remote object.
|
||||
*
|
||||
* @para the reference to the remote object.
|
||||
*/
|
||||
public RegistryImpl_Stub(RemoteRef reference)
|
||||
{
|
||||
super(reference);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
/** @inheritDoc */
|
||||
public String [] list()
|
||||
throws RemoteException, AccessException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_list,
|
||||
NO_ARGS,
|
||||
2571371476350237748L);
|
||||
return (String []) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void rebind(String p0, Remote p1)
|
||||
throws RemoteException, AccessException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_rebind,
|
||||
new Object[] {p0, p1},
|
||||
-8381844669958460146L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void unbind(String p0)
|
||||
throws RemoteException, NotBoundException, AccessException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_unbind,
|
||||
new Object[] {p0},
|
||||
7305022919901907578L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public Remote lookup(String p0)
|
||||
throws RemoteException, NotBoundException, AccessException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_lookup,
|
||||
new Object[] {p0},
|
||||
-7538657168040752697L);
|
||||
return (Remote) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void bind(String p0, Remote p1)
|
||||
throws RemoteException, AlreadyBoundException, AccessException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_bind,
|
||||
new Object[] {p0, p1},
|
||||
7583982177005850366L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -22,18 +22,7 @@
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi.rmic;
|
||||
@@ -43,7 +32,6 @@ import gnu.java.rmi.server.RMIHashes;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
import java.util.zip.Adler32;
|
||||
|
||||
/**
|
||||
* Keeps information about the single method and generates the code fragments,
|
||||
|
||||
@@ -22,18 +22,7 @@ Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi.rmic;
|
||||
|
||||
@@ -17,28 +17,11 @@ You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
*/
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi.rmic;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class WrapUnWrapper
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.initCause(e);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.initCause(e);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/* ActivationSystemImpl.java -- implementation of the activation system.
|
||||
Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.classpath.tools.rmi.rmid;
|
||||
|
||||
import gnu.classpath.tools.rmi.Persistent;
|
||||
import gnu.classpath.tools.rmi.PersistentBidiHashTable;
|
||||
import gnu.java.rmi.activation.ActivationSystemTransient;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.rmi.MarshalledObject;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.activation.ActivationDesc;
|
||||
import java.rmi.activation.ActivationException;
|
||||
import java.rmi.activation.ActivationGroupDesc;
|
||||
import java.rmi.activation.ActivationGroupID;
|
||||
import java.rmi.activation.ActivationID;
|
||||
import java.rmi.activation.ActivationInstantiator;
|
||||
import java.rmi.activation.ActivationMonitor;
|
||||
import java.rmi.activation.ActivationSystem;
|
||||
import java.rmi.activation.Activator;
|
||||
import java.rmi.activation.UnknownGroupException;
|
||||
import java.rmi.activation.UnknownObjectException;
|
||||
|
||||
/**
|
||||
* Implements the rmid activation system.
|
||||
*
|
||||
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
|
||||
*/
|
||||
public class ActivationSystemImpl extends ActivationSystemTransient implements
|
||||
ActivationSystem, Activator, ActivationMonitor, Serializable
|
||||
{
|
||||
/**
|
||||
* Use for interoperability.
|
||||
*/
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* The singleton instance of this class.
|
||||
*/
|
||||
public static ActivationSystemImpl singleton2;
|
||||
|
||||
/**
|
||||
* Obtain the singleton instance of this class.
|
||||
*
|
||||
* @param folder the folder, where the activation system will keep its files.
|
||||
* @param cold do the cold start if true, hot (usual) if false.
|
||||
*/
|
||||
public static ActivationSystem getInstance(File folder, boolean cold)
|
||||
{
|
||||
if (singleton2 == null)
|
||||
singleton2 = new ActivationSystemImpl(folder, cold);
|
||||
return singleton2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the group with transient maps.
|
||||
*
|
||||
* @param folder
|
||||
* the folder, where the activation system will keep its files.
|
||||
* @param cold
|
||||
* do the cold start if true, hot (usual) if false.
|
||||
*/
|
||||
protected ActivationSystemImpl(File folder, boolean cold)
|
||||
{
|
||||
super(new PersistentBidiHashTable(), new PersistentBidiHashTable());
|
||||
singleton2 = this;
|
||||
((PersistentBidiHashTable) groupDescs).init(
|
||||
new File(folder, "asi_objects.data"), cold);
|
||||
((PersistentBidiHashTable) descriptions).init(
|
||||
new File(folder, "asi_groups.data"), cold);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public MarshalledObject activate(ActivationID id, boolean force)
|
||||
throws ActivationException, UnknownObjectException, RemoteException
|
||||
{
|
||||
return super.activate(id, force);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationMonitor activeGroup(ActivationGroupID id,
|
||||
ActivationInstantiator group,
|
||||
long incarnation)
|
||||
throws UnknownGroupException, ActivationException, RemoteException
|
||||
{
|
||||
return super.activeGroup(id, group, incarnation);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void activeObject(ActivationID id, MarshalledObject obj)
|
||||
throws UnknownObjectException, RemoteException
|
||||
{
|
||||
super.activeObject(id, obj);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationDesc getActivationDesc(ActivationID id)
|
||||
throws ActivationException, UnknownObjectException, RemoteException
|
||||
{
|
||||
return super.getActivationDesc(id);
|
||||
}
|
||||
|
||||
public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID groupId)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
return super.getActivationGroupDesc(groupId);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void inactiveGroup(ActivationGroupID groupId, long incarnation)
|
||||
throws UnknownGroupException, RemoteException
|
||||
{
|
||||
super.inactiveGroup(groupId, incarnation);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void inactiveObject(ActivationID id) throws UnknownObjectException,
|
||||
RemoteException
|
||||
{
|
||||
super.inactiveObject(id);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationGroupID registerGroup(ActivationGroupDesc groupDesc)
|
||||
throws ActivationException, RemoteException
|
||||
{
|
||||
return super.registerGroup(groupDesc);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationID registerObject(ActivationDesc desc)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
return super.registerObject(desc);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationDesc setActivationDesc(ActivationID id, ActivationDesc desc)
|
||||
throws ActivationException, UnknownObjectException,
|
||||
UnknownGroupException, RemoteException
|
||||
{
|
||||
return super.setActivationDesc(id, desc);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationGroupDesc setActivationGroupDesc(
|
||||
ActivationGroupID groupId, ActivationGroupDesc groupDesc)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
return super.setActivationGroupDesc(groupId, groupDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method saves the state of the activation system and then
|
||||
* terminates in 10 seconds.
|
||||
*/
|
||||
public void shutdown() throws RemoteException
|
||||
{
|
||||
super.shutdown();
|
||||
System.out.println("Shutdown command received. Will terminate in 10 s");
|
||||
Persistent.timer.schedule(new Persistent.ExitTask(), 10000);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void unregisterGroup(ActivationGroupID groupId)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
super.unregisterGroup(groupId);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void unregisterObject(ActivationID id) throws ActivationException,
|
||||
UnknownObjectException, RemoteException
|
||||
{
|
||||
super.unregisterObject(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the object from the input stream.
|
||||
*
|
||||
* @param in the stream to read from
|
||||
*
|
||||
* @throws IOException if thrown by the stream
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private void readObject(ObjectInputStream in) throws IOException,
|
||||
ClassNotFoundException
|
||||
{
|
||||
// Read no fields.
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the object to the output stream.
|
||||
*
|
||||
* @param out the stream to write int
|
||||
* @throws IOException if thrown by the stream
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException,
|
||||
ClassNotFoundException
|
||||
{
|
||||
// Write no fields.
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,556 @@
|
||||
/* ActivationSystemImpl.java -- implementation of the activation system.
|
||||
Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.classpath.tools.rmi.rmid;
|
||||
|
||||
import java.rmi.MarshalledObject;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.activation.ActivationDesc;
|
||||
import java.rmi.activation.ActivationException;
|
||||
import java.rmi.activation.ActivationGroupDesc;
|
||||
import java.rmi.activation.ActivationGroupID;
|
||||
import java.rmi.activation.ActivationID;
|
||||
import java.rmi.activation.ActivationInstantiator;
|
||||
import java.rmi.activation.ActivationMonitor;
|
||||
import java.rmi.activation.ActivationSystem;
|
||||
import java.rmi.activation.Activator;
|
||||
import java.rmi.activation.UnknownGroupException;
|
||||
import java.rmi.activation.UnknownObjectException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.rmi.server.RemoteRef;
|
||||
import java.rmi.server.RemoteStub;
|
||||
import java.rmi.UnexpectedException;
|
||||
|
||||
/**
|
||||
* This class delegates its method calls to the remote RMI object, referenced
|
||||
* by {@link RemoteRef}.
|
||||
*
|
||||
* It is normally generated with rmic.
|
||||
*/
|
||||
public final class ActivationSystemImpl_Stub
|
||||
extends RemoteStub
|
||||
implements ActivationMonitor, Activator, ActivationSystem
|
||||
{
|
||||
/**
|
||||
* Use serialVersionUID for interoperability
|
||||
*/
|
||||
private static final long serialVersionUID = 2;
|
||||
|
||||
/**
|
||||
* The explaining message for {@ling UnexpectedException}.
|
||||
*/
|
||||
private static final String exception_message =
|
||||
"undeclared checked exception";
|
||||
|
||||
/* All remote methods, invoked by this stub: */
|
||||
private static final Method met_setActivationGroupDesc;
|
||||
private static final Method met_inactiveGroup;
|
||||
private static final Method met_unregisterObject;
|
||||
private static final Method met_getActivationDesc;
|
||||
private static final Method met_setActivationDesc;
|
||||
private static final Method met_shutdown;
|
||||
private static final Method met_activate;
|
||||
private static final Method met_activeGroup;
|
||||
private static final Method met_registerGroup;
|
||||
private static final Method met_getActivationGroupDesc;
|
||||
private static final Method met_activeObject;
|
||||
private static final Method met_registerObject;
|
||||
private static final Method met_inactiveObject;
|
||||
private static final Method met_unregisterGroup;
|
||||
private static final Object[] NO_ARGS = new Object[0];
|
||||
static
|
||||
{
|
||||
final Class[] NO_ARGSc = new Class[0];
|
||||
try
|
||||
{
|
||||
met_setActivationGroupDesc =
|
||||
ActivationSystem.class.getMethod("setActivationGroupDesc", new Class[]
|
||||
{
|
||||
ActivationGroupID.class, ActivationGroupDesc.class
|
||||
});
|
||||
met_inactiveGroup =
|
||||
ActivationMonitor.class.getMethod("inactiveGroup", new Class[]
|
||||
{
|
||||
ActivationGroupID.class, long.class
|
||||
});
|
||||
met_unregisterObject =
|
||||
ActivationSystem.class.getMethod("unregisterObject", new Class[]
|
||||
{
|
||||
ActivationID.class
|
||||
});
|
||||
met_getActivationDesc =
|
||||
ActivationSystem.class.getMethod("getActivationDesc", new Class[]
|
||||
{
|
||||
ActivationID.class
|
||||
});
|
||||
met_setActivationDesc =
|
||||
ActivationSystem.class.getMethod("setActivationDesc", new Class[]
|
||||
{
|
||||
ActivationID.class, ActivationDesc.class
|
||||
});
|
||||
met_shutdown =
|
||||
ActivationSystem.class.getMethod("shutdown", NO_ARGSc);
|
||||
met_activate =
|
||||
Activator.class.getMethod("activate", new Class[]
|
||||
{
|
||||
ActivationID.class, boolean.class
|
||||
});
|
||||
met_activeGroup =
|
||||
ActivationSystem.class.getMethod("activeGroup", new Class[]
|
||||
{
|
||||
ActivationGroupID.class, ActivationInstantiator.class, long.class
|
||||
});
|
||||
met_registerGroup =
|
||||
ActivationSystem.class.getMethod("registerGroup", new Class[]
|
||||
{
|
||||
ActivationGroupDesc.class
|
||||
});
|
||||
met_getActivationGroupDesc =
|
||||
ActivationSystem.class.getMethod("getActivationGroupDesc", new Class[]
|
||||
{
|
||||
ActivationGroupID.class
|
||||
});
|
||||
met_activeObject =
|
||||
ActivationMonitor.class.getMethod("activeObject", new Class[]
|
||||
{
|
||||
ActivationID.class, MarshalledObject.class
|
||||
});
|
||||
met_registerObject =
|
||||
ActivationSystem.class.getMethod("registerObject", new Class[]
|
||||
{
|
||||
ActivationDesc.class
|
||||
});
|
||||
met_inactiveObject =
|
||||
ActivationMonitor.class.getMethod("inactiveObject", new Class[]
|
||||
{
|
||||
ActivationID.class
|
||||
});
|
||||
met_unregisterGroup =
|
||||
ActivationSystem.class.getMethod("unregisterGroup", new Class[]
|
||||
{
|
||||
ActivationGroupID.class
|
||||
});
|
||||
|
||||
}
|
||||
catch (NoSuchMethodException nex)
|
||||
{
|
||||
NoSuchMethodError err = new NoSuchMethodError(
|
||||
"ActivationSystemImpl_Stub class initialization failed");
|
||||
err.initCause(nex);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the instance for _ActivationSystemImpl_Stub that forwards method calls to the
|
||||
* remote object.
|
||||
*
|
||||
* @para the reference to the remote object.
|
||||
*/
|
||||
public ActivationSystemImpl_Stub(RemoteRef reference)
|
||||
{
|
||||
super(reference);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
/** @inheritDoc */
|
||||
public ActivationGroupDesc setActivationGroupDesc(ActivationGroupID p0,
|
||||
ActivationGroupDesc p1)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_setActivationGroupDesc,
|
||||
new Object[] { p0, p1 },
|
||||
1213918527826541191L);
|
||||
return (ActivationGroupDesc) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void inactiveGroup(ActivationGroupID p0, long p1)
|
||||
throws UnknownGroupException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_inactiveGroup, new Object[] { p0, new Long(p1) },
|
||||
-399287892768650944L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void unregisterObject(ActivationID p0) throws ActivationException,
|
||||
UnknownObjectException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_unregisterObject, new Object[] { p0 },
|
||||
-6843850585331411084L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationDesc getActivationDesc(ActivationID p0)
|
||||
throws ActivationException, UnknownObjectException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_getActivationDesc,
|
||||
new Object[] { p0 }, 4830055440982622087L);
|
||||
return (ActivationDesc) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationDesc setActivationDesc(ActivationID p0, ActivationDesc p1)
|
||||
throws ActivationException, UnknownObjectException,
|
||||
UnknownGroupException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_setActivationDesc,
|
||||
new Object[] { p0, p1 },
|
||||
7128043237057180796L);
|
||||
return (ActivationDesc) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void shutdown() throws RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_shutdown, NO_ARGS, -7207851917985848402L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public MarshalledObject activate(ActivationID p0, boolean p1)
|
||||
throws ActivationException, UnknownObjectException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_activate,
|
||||
new Object[] { p0, new Boolean(p1) },
|
||||
-8767355154875805558L);
|
||||
return (MarshalledObject) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationMonitor activeGroup(ActivationGroupID p0,
|
||||
ActivationInstantiator p1, long p2)
|
||||
throws UnknownGroupException, ActivationException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_activeGroup,
|
||||
new Object[] { p0, p1, new Long(p2) },
|
||||
-4575843150759415294L);
|
||||
return (ActivationMonitor) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationGroupID registerGroup(ActivationGroupDesc p0)
|
||||
throws ActivationException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_registerGroup,
|
||||
new Object[] { p0 }, 6921515268192657754L);
|
||||
return (ActivationGroupID) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID p0)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_getActivationGroupDesc,
|
||||
new Object[] { p0 }, -8701843806548736528L);
|
||||
return (ActivationGroupDesc) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void activeObject(ActivationID p0, MarshalledObject p1)
|
||||
throws UnknownObjectException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_activeObject, new Object[] { p0, p1 },
|
||||
2543984342209939736L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public ActivationID registerObject(ActivationDesc p0)
|
||||
throws ActivationException, UnknownGroupException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object result = ref.invoke(this, met_registerObject,
|
||||
new Object[] { p0 }, -3006759798994351347L);
|
||||
return (ActivationID) result;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void inactiveObject(ActivationID p0) throws UnknownObjectException,
|
||||
RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_inactiveObject, new Object[] { p0 },
|
||||
-4165404120701281807L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public void unregisterGroup(ActivationGroupID p0) throws ActivationException,
|
||||
UnknownGroupException, RemoteException
|
||||
{
|
||||
try
|
||||
{
|
||||
ref.invoke(this, met_unregisterGroup, new Object[] { p0 },
|
||||
3768097077835970701L);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (RemoteException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnexpectedException uex = new UnexpectedException(exception_message);
|
||||
uex.detail = e;
|
||||
throw uex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/bin/sh
|
||||
|
||||
## Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
##
|
||||
## This file is a part of GNU Classpath.
|
||||
##
|
||||
## GNU Classpath is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or (at
|
||||
## your option) any later version.
|
||||
##
|
||||
## GNU Classpath is distributed in the hope that it will be useful, but
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
## General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with GNU Classpath; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
## USA.
|
||||
##
|
||||
## Linking this library statically or dynamically with other modules is
|
||||
## making a combined work based on this library. Thus, the terms and
|
||||
## conditions of the GNU General Public License cover the whole
|
||||
## combination.
|
||||
##
|
||||
## As a special exception, the copyright holders of this library give you
|
||||
## permission to link this library with independent modules to produce an
|
||||
## executable, regardless of the license terms of these independent
|
||||
## modules, and to copy and distribute the resulting executable under
|
||||
## terms of your choice, provided that you also meet, for each linked
|
||||
## independent module, the terms and conditions of the license of that
|
||||
## module. An independent module is a module which is not derived from
|
||||
## or based on this library. If you modify this library, you may extend
|
||||
## this exception to your version of the library, but you are not
|
||||
## obligated to do so. If you do not wish to do so, delete this
|
||||
## exception statement from your version.
|
||||
##
|
||||
##
|
||||
## A simple shell script to launch the GNU Classpath jarsigner tool.
|
||||
##
|
||||
|
||||
prefix=@prefix@
|
||||
tools_dir=@datadir@/@PACKAGE@
|
||||
tools_cp=${tools_dir}/tools.zip
|
||||
|
||||
# find the java executable...
|
||||
if [ -z "${JAVA}" ] ; then
|
||||
if [ -n "${JAVA_HOME}" ] ; then
|
||||
if [ -x "${JAVA_HOME}/jre/sh/java" ] ; then
|
||||
JAVA="${JAVA_HOME}/jre/sh/java"
|
||||
else
|
||||
JAVA="${JAVA_HOME}/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVA=`which java 2> /dev/null `
|
||||
if [ -z "${JAVA}" ] ; then
|
||||
JAVA=java
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${JAVA}" -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.jarsigner.Main $@
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/bin/sh
|
||||
|
||||
## Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
##
|
||||
## This file is a part of GNU Classpath.
|
||||
##
|
||||
## GNU Classpath is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or (at
|
||||
## your option) any later version.
|
||||
##
|
||||
## GNU Classpath is distributed in the hope that it will be useful, but
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
## General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with GNU Classpath; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
## USA.
|
||||
##
|
||||
## Linking this library statically or dynamically with other modules is
|
||||
## making a combined work based on this library. Thus, the terms and
|
||||
## conditions of the GNU General Public License cover the whole
|
||||
## combination.
|
||||
##
|
||||
## As a special exception, the copyright holders of this library give you
|
||||
## permission to link this library with independent modules to produce an
|
||||
## executable, regardless of the license terms of these independent
|
||||
## modules, and to copy and distribute the resulting executable under
|
||||
## terms of your choice, provided that you also meet, for each linked
|
||||
## independent module, the terms and conditions of the license of that
|
||||
## module. An independent module is a module which is not derived from
|
||||
## or based on this library. If you modify this library, you may extend
|
||||
## this exception to your version of the library, but you are not
|
||||
## obligated to do so. If you do not wish to do so, delete this
|
||||
## exception statement from your version.
|
||||
##
|
||||
##
|
||||
## A simple shell script to launch the GNU Classpath keytool tool.
|
||||
##
|
||||
|
||||
prefix=@prefix@
|
||||
tools_dir=@datadir@/@PACKAGE@
|
||||
tools_cp=${tools_dir}/tools.zip
|
||||
|
||||
# find the java executable...
|
||||
if [ -z "${JAVA}" ] ; then
|
||||
if [ -n "${JAVA_HOME}" ] ; then
|
||||
if [ -x "${JAVA_HOME}/jre/sh/java" ] ; then
|
||||
JAVA="${JAVA_HOME}/jre/sh/java"
|
||||
else
|
||||
JAVA="${JAVA_HOME}/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVA=`which java 2> /dev/null `
|
||||
if [ -z "${JAVA}" ] ; then
|
||||
JAVA=java
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${JAVA}" -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.keytool.Main $@
|
||||
Reference in New Issue
Block a user