hehe, it seems like I'm going back in time with this :) I've just finished to port the GConf backend to IcedTea, so sorry for cross posting, but I think it's a good news for both Classpath and IcedTea. I'm asking for comment because I'm not a configure expert, so may very well be that this is not the perfect way to handle things. I've tested with few applications and all seems correct, the code is pretty much the same as the Classpath version. I've not tested it as concern the security model. I say this because I've seen that the FileBasedPreferences in openjdk does a little more checks on the SecurityManager than what we do. I want to check this carefully, but other than that, I think it's ok as is. This thing works that way, if the user issues a --disable-gconf-peer to configure, nothing happens and the backend is not compiled. Otherwise, the backend is compiled and a shared object is created and then copied in the jre tree (much like we do with gcjwebplugin). Also, a patch is applied to call this backend on Linux and Solaris. I'm waiting for comments, thanks, Mario -- Lima Software - http://www.limasoftware.net/ GNU Classpath Developer - http://www.classpath.org/ Fedora Ambassador - http://fedoraproject.org/wiki/MarioTorre Jabber: neugens@xxxxxxxxxx pgp key: http://subkeys.pgp.net/ PGP Key ID: 80F240CF Fingerprint: BA39 9666 94EC 8B73 27FA FC7C 4086 63E3 80F2 40CF Please, support open standards: http://opendocumentfellowship.org/petition/ http://www.nosoftwarepatents.com/
diff -r 2d58a540c22c Makefile.am --- a/Makefile.am Mon Oct 15 15:56:10 2007 -0400 +++ b/Makefile.am Wed Oct 31 01:07:05 2007 +0100 @@ -25,8 +25,20 @@ install: clean-tools-jar clean-tools clean-shared-objects \ clean-copy clean-rt clean-gcjwebplugin +if CREATE_GCONF_PEER_LIBRARIES + GCONF_PEER_BASE_DIR = gconf-prefs-peer + GCONF_PEER_LIB_DIR = $(GCONF_PEER_BASE_DIR)/native + GCONF_PEER_SRC = gnu/java/util/prefs + GCONF_PATCH = patches/icedtea-enable-gconf.patch +else + GCONF_PATCH = +endif + +SUBDIRS = $(GCONF_PEER_BASE_DIR) + EXTRA_DIST = rt generated $(ICEDTEA_PATCHES) \ - gcjwebplugin.cc patches/icedtea-speed.patch tools-copy-files.txt + gcjwebplugin.cc patches/icedtea-speed.patch tools-copy-files.txt \ + gconf-prefs-peer # OpenJDK build environment. LINUX_DIR = linux-$(BUILD_ARCH_DIR) @@ -146,7 +158,8 @@ ICEDTEA_PATCHES = \ patches/icedtea-memory-limits.patch \ patches/icedtea-xjc.patch \ $(FAST_BUILD_PATCH) \ - $(DISTRIBUTION_PATCHES) + $(DISTRIBUTION_PATCHES) \ + $(GCONF_PATCH) stamps/patch.stamp: stamps/extract.stamp for p in $(ICEDTEA_PATCHES) ; \ @@ -208,6 +221,12 @@ icedtea: stamps/bootstrap-directory-syml $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) cp -af gcjwebplugin.so \ $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) ; \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ + fi @echo "IcedTea is served:" $(BUILD_OUTPUT_DIR) icedtea-debug: stamps/bootstrap-directory-symlink.stamp \ @@ -221,6 +240,12 @@ icedtea-debug: stamps/bootstrap-director $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) cp -af gcjwebplugin.so \ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) ; \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ + fi @echo "IcedTea (debug build) is served:" \ $(BUILD_OUTPUT_DIR)-debug @@ -286,6 +311,12 @@ ICEDTEA_COPY_DIRS = \ java/util stamps/copy-source-files.stamp: stamps/extract.stamp stamps/patch.stamp + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + if [ ! -d "rt/gnu" ]; then \ + mkdir -p rt/gnu ; \ + fi ;\ + cp -arf gconf-prefs-peer/gnu/* rt/gnu ;\ + fi ; \ for copy_dir in $(ICEDTEA_COPY_DIRS) ; \ do \ mkdir -p rt/$$copy_dir ; \ @@ -297,6 +328,9 @@ stamps/copy-source-files.stamp: stamps/e clean-copy: rm -f stamps/copy-source-files.stamp + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + rm -rf rt/gnu/util/prefs ;\ + fi ; \ for copy_dir in $(ICEDTEA_COPY_DIRS) ; \ do \ rm -rf rt/$$copy_dir ; \ diff -r 2d58a540c22c Makefile.in --- a/Makefile.in Mon Oct 15 15:56:10 2007 -0400 +++ b/Makefile.in Wed Oct 31 01:07:05 2007 +0100 @@ -47,6 +47,18 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = gconf-prefs-peer DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -82,10 +94,15 @@ ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +ENABLE_GCONF_PEER = @ENABLE_GCONF_PEER@ EXEEXT = @EXEEXT@ FIND = @FIND@ FREETYPE2_INC_DIR = @FREETYPE2_INC_DIR@ GAWK = @GAWK@ +GCONF_CFLAGS = @GCONF_CFLAGS@ +GCONF_LIBS = @GCONF_LIBS@ +GDK_CFLAGS = @GDK_CFLAGS@ +GDK_LIBS = @GDK_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GREP = @GREP@ @@ -183,8 +200,15 @@ OPENJDK_VERSION = b22 OPENJDK_VERSION = b22 OPENJDK_DATE = 12_oct_2007 OPENJDK_MD5SUM = 7cf9c2765fb16c36c07f961b2a009cb2 +@CREATE_GCONF_PEER_LIBRARIES_TRUE@GCONF_PEER_BASE_DIR = gconf-prefs-peer +@CREATE_GCONF_PEER_LIBRARIES_TRUE@GCONF_PEER_LIB_DIR = $(GCONF_PEER_BASE_DIR)/native +@CREATE_GCONF_PEER_LIBRARIES_TRUE@GCONF_PEER_SRC = gnu/java/util/prefs +@CREATE_GCONF_PEER_LIBRARIES_FALSE@GCONF_PATCH = +@CREATE_GCONF_PEER_LIBRARIES_TRUE@GCONF_PATCH = patches/icedtea-enable-gconf.patch +SUBDIRS = $(GCONF_PEER_BASE_DIR) EXTRA_DIST = rt generated $(ICEDTEA_PATCHES) \ - gcjwebplugin.cc patches/icedtea-speed.patch tools-copy-files.txt + gcjwebplugin.cc patches/icedtea-speed.patch tools-copy-files.txt \ + gconf-prefs-peer # OpenJDK build environment. @@ -261,7 +285,8 @@ ICEDTEA_PATCHES = \ patches/icedtea-memory-limits.patch \ patches/icedtea-xjc.patch \ $(FAST_BUILD_PATCH) \ - $(DISTRIBUTION_PATCHES) + $(DISTRIBUTION_PATCHES) \ + $(GCONF_PATCH) # Bootstrap Directory Targets @@ -295,7 +320,7 @@ OPENJDK_SOURCEPATH_DIRS = \ OPENJDK_SOURCEPATH_DIRS = \ $(SHARE):$(SOLARIS):$(LANGTOOLS):$(JAXP) -all: all-am +all: all-recursive .SUFFIXES: am--refresh: @@ -331,12 +356,137 @@ Makefile: $(srcdir)/Makefile.in $(top_bu cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique tags: TAGS -TAGS: - + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi ctags: CTAGS -CTAGS: - +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) @@ -364,6 +514,23 @@ distdir: $(DISTFILES) test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ @@ -464,17 +631,18 @@ distcleancheck: distclean $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am -check: check-am +check: check-recursive all-am: Makefile all-local -installdirs: -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am +installdirs: installdirs-recursive +installdirs-am: +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-am +installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ @@ -490,77 +658,81 @@ maintainer-clean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -clean: clean-am +clean: clean-recursive clean-am: clean-generic mostlyclean-am -distclean: distclean-am +distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-local - -dvi: dvi-am +distclean-am: clean-am distclean-generic distclean-local \ + distclean-tags + +dvi: dvi-recursive dvi-am: -html: html-am - -info: info-am +html: html-recursive + +info: info-recursive info-am: install-data-am: -install-dvi: install-dvi-am +install-dvi: install-dvi-recursive install-exec-am: -install-html: install-html-am - -install-info: install-info-am +install-html: install-html-recursive + +install-info: install-info-recursive install-man: -install-pdf: install-pdf-am - -install-ps: install-ps-am +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive installcheck-am: -maintainer-clean: maintainer-clean-am +maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-am +mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic -pdf: pdf-am +pdf: pdf-recursive pdf-am: -ps: ps-am +ps: ps-recursive ps-am: uninstall-am: -.MAKE: install-am install-strip - -.PHONY: all all-am all-local am--refresh check check-am clean \ - clean-generic dist dist-all dist-bzip2 dist-gzip dist-shar \ - dist-tarZ dist-zip distcheck distclean distclean-generic \ - distclean-local distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am all-local am--refresh check check-am clean \ + clean-generic ctags ctags-recursive dist dist-all dist-bzip2 \ + dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ + distclean-generic distclean-local distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am uninstall uninstall-am + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am # Top-Level Targets @@ -682,6 +854,12 @@ icedtea: stamps/bootstrap-directory-syml $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) cp -af gcjwebplugin.so \ $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) ; \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ + fi @echo "IcedTea is served:" $(BUILD_OUTPUT_DIR) icedtea-debug: stamps/bootstrap-directory-symlink.stamp \ @@ -695,6 +873,12 @@ icedtea-debug: stamps/bootstrap-director $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) cp -af gcjwebplugin.so \ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) ; \ + cp -af $(GCONF_PEER_LIB_DIR)/libgconfpeer.so \ + $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ + fi @echo "IcedTea (debug build) is served:" \ $(BUILD_OUTPUT_DIR)-debug @@ -741,6 +925,12 @@ clean-shared-objects: rm -f $(SHARED_OBJECT_FILES) stamps/copy-source-files.stamp: stamps/extract.stamp stamps/patch.stamp + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + if [ ! -d "rt/gnu" ]; then \ + mkdir -p rt/gnu ; \ + fi ;\ + cp -arf gconf-prefs-peer/gnu/* rt/gnu ;\ + fi ; \ for copy_dir in $(ICEDTEA_COPY_DIRS) ; \ do \ mkdir -p rt/$$copy_dir ; \ @@ -752,6 +942,9 @@ stamps/copy-source-files.stamp: stamps/e clean-copy: rm -f stamps/copy-source-files.stamp + if test "x${ENABLE_GCONF_PEER}" = xyes; then \ + rm -rf rt/gnu/util/prefs ;\ + fi ; \ for copy_dir in $(ICEDTEA_COPY_DIRS) ; \ do \ rm -rf rt/$$copy_dir ; \ diff -r 2d58a540c22c configure --- a/configure Mon Oct 15 15:56:10 2007 -0400 +++ b/configure Wed Oct 31 01:07:05 2007 +0100 @@ -713,6 +713,8 @@ GAWK GAWK SYSTEM_ICEDTEA_DIR SYSTEM_ANT_DIR +CREATE_GCONF_PEER_LIBRARIES_TRUE +CREATE_GCONF_PEER_LIBRARIES_FALSE BUILD_ARCH_DIR INSTALL_ARCH_DIR JAVA @@ -739,6 +741,11 @@ GLIB_LIBS GLIB_LIBS GTK_CFLAGS GTK_LIBS +GCONF_CFLAGS +GCONF_LIBS +GDK_CFLAGS +GDK_LIBS +ENABLE_GCONF_PEER LIBOBJS LTLIBOBJS' ac_subst_files='' @@ -760,7 +767,11 @@ GLIB_CFLAGS GLIB_CFLAGS GLIB_LIBS GTK_CFLAGS -GTK_LIBS' +GTK_LIBS +GCONF_CFLAGS +GCONF_LIBS +GDK_CFLAGS +GDK_LIBS' # Initialize some variables set by options. @@ -1342,6 +1353,8 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors + --disable-gconf-peer compile GConf native peers default=yes + --enable-fast-build optimize for quick building: use -O0 and do not build documentation @@ -1374,6 +1387,11 @@ Some influential environment variables: GLIB_LIBS linker flags for GLIB, overriding pkg-config GTK_CFLAGS C compiler flags for GTK, overriding pkg-config GTK_LIBS linker flags for GTK, overriding pkg-config + GCONF_CFLAGS + C compiler flags for GCONF, overriding pkg-config + GCONF_LIBS linker flags for GCONF, overriding pkg-config + GDK_CFLAGS C compiler flags for GDK, overriding pkg-config + GDK_LIBS linker flags for GDK, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -2370,7 +2388,7 @@ echo "${ECHO_T}$am_cv_prog_tar_pax" >&6; -ac_config_files="$ac_config_files Makefile" +ac_config_files="$ac_config_files Makefile gconf-prefs-peer/Makefile gconf-prefs-peer/native/Makefile" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || @@ -4822,6 +4840,33 @@ fi +# Check whether --enable-gconf-peer was given. +if test "${enable_gconf_peer+set}" = set; then + enableval=$enable_gconf_peer; case "${enableval}" in + yes) COMPILE_GCONF_PEER=yes ;; + no) COMPILE_GCONF_PEER=no ;; + *) COMPILE_GCONF_PEER=yes ;; + esac +else + COMPILE_GCONF_PEER=yes +fi + + if test "x${COMPILE_GCONF_PEER}" = xyes; then + CREATE_GCONF_PEER_LIBRARIES_TRUE= + CREATE_GCONF_PEER_LIBRARIES_FALSE='#' +else + CREATE_GCONF_PEER_LIBRARIES_TRUE='#' + CREATE_GCONF_PEER_LIBRARIES_FALSE= +fi + +# Check whether --enable-gconf-peers was given. +if test "${enable_gconf_peers+set}" = set; then + enableval=$enable_gconf_peers; { { echo "$as_me:$LINENO: error: No --enable-gconf-peers (or --disable-gconf-peers) option; you want --enable-gconf-peer" >&5 +echo "$as_me: error: No --enable-gconf-peers (or --disable-gconf-peers) option; you want --enable-gconf-peer" >&2;} + { (exit 1); exit 1; }; } +fi + + case "${host}" in x86_64-*-*) @@ -7697,6 +7742,238 @@ fi +if test "x${COMPILE_GCONF_PEER}" = xyes; then + +pkg_failed=no +{ echo "$as_me:$LINENO: checking for GCONF" >&5 +echo $ECHO_N "checking for GCONF... $ECHO_C" >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GCONF_CFLAGS"; then + pkg_cv_GCONF_CFLAGS="$GCONF_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"gconf-2.0 >= 2.6.0\"") >&5 + ($PKG_CONFIG --exists --print-errors "gconf-2.0 >= 2.6.0") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_GCONF_CFLAGS=`$PKG_CONFIG --cflags "gconf-2.0 >= 2.6.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GCONF_LIBS"; then + pkg_cv_GCONF_LIBS="$GCONF_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"gconf-2.0 >= 2.6.0\"") >&5 + ($PKG_CONFIG --exists --print-errors "gconf-2.0 >= 2.6.0") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_GCONF_LIBS=`$PKG_CONFIG --libs "gconf-2.0 >= 2.6.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GCONF_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gconf-2.0 >= 2.6.0"` + else + GCONF_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gconf-2.0 >= 2.6.0"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GCONF_PKG_ERRORS" >&5 + + { { echo "$as_me:$LINENO: error: Package requirements (gconf-2.0 >= 2.6.0) were not met: + +$GCONF_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GCONF_CFLAGS +and GCONF_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" >&5 +echo "$as_me: error: Package requirements (gconf-2.0 >= 2.6.0) were not met: + +$GCONF_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GCONF_CFLAGS +and GCONF_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" >&2;} + { (exit 1); exit 1; }; } +elif test $pkg_failed = untried; then + { { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GCONF_CFLAGS +and GCONF_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>. +See \`config.log' for more details." >&5 +echo "$as_me: error: The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GCONF_CFLAGS +and GCONF_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + GCONF_CFLAGS=$pkg_cv_GCONF_CFLAGS + GCONF_LIBS=$pkg_cv_GCONF_LIBS + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + : +fi + + + +pkg_failed=no +{ echo "$as_me:$LINENO: checking for GDK" >&5 +echo $ECHO_N "checking for GDK... $ECHO_C" >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GDK_CFLAGS"; then + pkg_cv_GDK_CFLAGS="$GDK_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"gdk-2.0 >= 2.8\"") >&5 + ($PKG_CONFIG --exists --print-errors "gdk-2.0 >= 2.8") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_GDK_CFLAGS=`$PKG_CONFIG --cflags "gdk-2.0 >= 2.8" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GDK_LIBS"; then + pkg_cv_GDK_LIBS="$GDK_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"gdk-2.0 >= 2.8\"") >&5 + ($PKG_CONFIG --exists --print-errors "gdk-2.0 >= 2.8") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_GDK_LIBS=`$PKG_CONFIG --libs "gdk-2.0 >= 2.8" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GDK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gdk-2.0 >= 2.8"` + else + GDK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gdk-2.0 >= 2.8"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GDK_PKG_ERRORS" >&5 + + { { echo "$as_me:$LINENO: error: Package requirements (gdk-2.0 >= 2.8) were not met: + +$GDK_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GDK_CFLAGS +and GDK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" >&5 +echo "$as_me: error: Package requirements (gdk-2.0 >= 2.8) were not met: + +$GDK_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GDK_CFLAGS +and GDK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" >&2;} + { (exit 1); exit 1; }; } +elif test $pkg_failed = untried; then + { { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GDK_CFLAGS +and GDK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>. +See \`config.log' for more details." >&5 +echo "$as_me: error: The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GDK_CFLAGS +and GDK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + GDK_CFLAGS=$pkg_cv_GDK_CFLAGS + GDK_LIBS=$pkg_cv_GDK_LIBS + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + : +fi + + + + ENABLE_GCONF_PEER=yes + +fi + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -7844,6 +8121,13 @@ Usually this means the macro was only in Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${CREATE_GCONF_PEER_LIBRARIES_TRUE}" && test -z "${CREATE_GCONF_PEER_LIBRARIES_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"CREATE_GCONF_PEER_LIBRARIES\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"CREATE_GCONF_PEER_LIBRARIES\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi if test -z "${USE_ALT_OPENJDK_SRC_ZIP_TRUE}" && test -z "${USE_ALT_OPENJDK_SRC_ZIP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"USE_ALT_OPENJDK_SRC_ZIP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -8332,6 +8616,8 @@ do do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "gconf-prefs-peer/Makefile") CONFIG_FILES="$CONFIG_FILES gconf-prefs-peer/Makefile" ;; + "gconf-prefs-peer/native/Makefile") CONFIG_FILES="$CONFIG_FILES gconf-prefs-peer/native/Makefile" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 @@ -8533,6 +8819,8 @@ for ac_last_try in false false false fal for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SYSTEM_ANT_DIR!$SYSTEM_ANT_DIR$ac_delim +CREATE_GCONF_PEER_LIBRARIES_TRUE!$CREATE_GCONF_PEER_LIBRARIES_TRUE$ac_delim +CREATE_GCONF_PEER_LIBRARIES_FALSE!$CREATE_GCONF_PEER_LIBRARIES_FALSE$ac_delim BUILD_ARCH_DIR!$BUILD_ARCH_DIR$ac_delim INSTALL_ARCH_DIR!$INSTALL_ARCH_DIR$ac_delim JAVA!$JAVA$ac_delim @@ -8559,11 +8847,16 @@ GLIB_LIBS!$GLIB_LIBS$ac_delim GLIB_LIBS!$GLIB_LIBS$ac_delim GTK_CFLAGS!$GTK_CFLAGS$ac_delim GTK_LIBS!$GTK_LIBS$ac_delim +GCONF_CFLAGS!$GCONF_CFLAGS$ac_delim +GCONF_LIBS!$GCONF_LIBS$ac_delim +GDK_CFLAGS!$GDK_CFLAGS$ac_delim +GDK_LIBS!$GDK_LIBS$ac_delim +ENABLE_GCONF_PEER!$ENABLE_GCONF_PEER$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 29; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 36; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff -r 2d58a540c22c configure.ac --- a/configure.ac Mon Oct 15 15:56:10 2007 -0400 +++ b/configure.ac Wed Oct 31 01:07:05 2007 +0100 @@ -1,7 +1,9 @@ AC_PREREQ([2.61]) AC_PREREQ([2.61]) AC_INIT([icedtea], [1.4], [fitzsim@xxxxxxxxxx]) AM_INIT_AUTOMAKE([tar-pax]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile +gconf-prefs-peer/Makefile +gconf-prefs-peer/native/Makefile]) AC_CANONICAL_HOST AC_PREFIX_DEFAULT([bootstrap]) @@ -51,6 +53,17 @@ AC_ARG_WITH([ant-home], SYSTEM_ANT_DIR=/usr/share/ant ]) AC_SUBST(SYSTEM_ANT_DIR) + +AC_ARG_ENABLE([gconf-peer], + [AS_HELP_STRING(--disable-gconf-peer,compile GConf native peers [default=yes])], + [case "${enableval}" in + yes) COMPILE_GCONF_PEER=yes ;; + no) COMPILE_GCONF_PEER=no ;; + *) COMPILE_GCONF_PEER=yes ;; + esac], + [COMPILE_GCONF_PEER=yes]) +AM_CONDITIONAL(CREATE_GCONF_PEER_LIBRARIES, test "x${COMPILE_GCONF_PEER}" = xyes) +AC_ARG_ENABLE([gconf-peers],,AC_MSG_ERROR([No --enable-gconf-peers (or --disable-gconf-peers) option; you want --enable-gconf-peer])) SET_ARCH_DIRS JAVA=$SYSTEM_ICEDTEA_DIR/bin/java @@ -118,4 +131,18 @@ AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) +dnl gconf-peer +if test "x${COMPILE_GCONF_PEER}" = xyes; then + PKG_CHECK_MODULES(GCONF, gconf-2.0 >= 2.6.0) + AC_SUBST(GCONF_CFLAGS) + AC_SUBST(GCONF_LIBS) + dnl we also need gdk for locking + PKG_CHECK_MODULES(GDK, gdk-2.0 >= 2.8) + AC_SUBST(GDK_CFLAGS) + AC_SUBST(GDK_LIBS) + + ENABLE_GCONF_PEER=yes + AC_SUBST(ENABLE_GCONF_PEER) +fi + AC_OUTPUT diff -r 2d58a540c22c gconf-prefs-peer/gnu/java/util/prefs/GConfBasedFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gconf-prefs-peer/gnu/java/util/prefs/GConfBasedFactory.java Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,78 @@ +/* GConfBasedFactory.java -- GConf based PreferencesFactory implementation + 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.java.util.prefs; + +import java.util.prefs.Preferences; +import java.util.prefs.PreferencesFactory; + +/** + * Factory object that generates a Preferences nodes that are read from a GConf + * daemon. + * + * @author Mario Torre <neugens@xxxxxxxxxxxxxxxx> + */ +public class GConfBasedFactory implements PreferencesFactory +{ + /** System preference root. */ + private static final Preferences systemPreferences + = new GConfBasedPreferences(null, "", false); + + /** User preference root. */ + private static final Preferences userPreferences + = new GConfBasedPreferences(null, "", true); + + /** + * Returns the system root preference node. + * + * @see java.util.prefs.PreferencesFactory#systemRoot() + */ + public Preferences systemRoot() + { + return systemPreferences; + } + + /** + * Returns the user root preference node corresponding to the calling user. + * + * @see java.util.prefs.PreferencesFactory#userRoot() + */ + public Preferences userRoot() + { + return userPreferences; + } +} diff -r 2d58a540c22c gconf-prefs-peer/gnu/java/util/prefs/GConfBasedPreferences.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gconf-prefs-peer/gnu/java/util/prefs/GConfBasedPreferences.java Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,423 @@ +/* GConfBasedPreferences.java -- GConf based Preferences implementation + 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.java.util.prefs; + +import gnu.java.util.prefs.gconf.GConfNativePeer; + +import java.security.Permission; + +import java.util.List; +import java.util.prefs.AbstractPreferences; +import java.util.prefs.BackingStoreException; + +/** + * This is a GConf based preference implementation which writes the preferences + * as GConf key-value pairs. System Root is defined to be the + * <code>"/system"</code> directory of GConf for the current user, while User + * Root is <code>"/apps/java"</code>. These defaults can be modified by + * defining two system properties:<br /> + * <br /> + * User Root:<br /> + * <br /> + * + * <pre> + * gnu.java.util.prefs.gconf.user_root + * </pre> + * + * <br /> + * <br /> + * and System Root:<br /> + * <br /> + * + * <pre> + * gnu.java.util.prefs.gconf.system_root + * </pre> + * + * <br /> + * + * @author Mario Torre <neugens@xxxxxxxxxxxxxxxx> + */ +public class GConfBasedPreferences + extends AbstractPreferences +{ + /** Get access to Runtime permission */ + private static final Permission PERMISSION + = new RuntimePermission("preferences"); + + /** CGonf client backend */ + private static GConfNativePeer backend = new GConfNativePeer(); + + /** Default user root path */ + private static final String DEFAULT_USER_ROOT = "/apps/classpath"; + + /** Default system root path */ + private static final String DEFAULT_SYSTEM_ROOT = "/system"; + + /** current node full path */ + private String node = ""; + + /** True if this is a preference node in the user tree, false otherwise. */ + private final boolean isUser; + + /** + * Creates a preference root user node. + */ + public GConfBasedPreferences() + { + this(true); + } + + /** + * Creates a preference root node. When <code>isUser</code> is true it will + * be user node otherwise it will be a system node. + */ + public GConfBasedPreferences(boolean isUser) + { + this(null, "", isUser); + } + + /** + * Creates a new preference node given a parent node and a name, which has to + * be relative to its parent. When <code>isUser</code> is true it will be user + * node otherwise it will be a system node. + * + * @param parent The parent node of this newly created node. + * @param name A name relative to the parent node. + * @param isUser Set to <code>true</code> initializes this node to be + * a user node, <code>false</code> initialize it to be a system node. + */ + public GConfBasedPreferences(AbstractPreferences parent, String name, + boolean isUser) + { + super(parent, name); + this.isUser = isUser; + + // stores the fully qualified name of this node + String absolutePath = this.absolutePath(); + if (absolutePath != null && absolutePath.endsWith("/")) + { + absolutePath = absolutePath.substring(0, absolutePath.length() - 1); + } + + // strip invalid characters + // please, note that all names are unescaped into the native peer + int index = absolutePath.lastIndexOf('/'); + if (index > -1) + { + absolutePath = absolutePath.substring(0, index + 1); + absolutePath = absolutePath + GConfNativePeer.escapeString(name); + } + + this.node = this.getRealRoot(isUser) + absolutePath; + + boolean nodeExist = backend.nodeExist(this.node); + + this.newNode = !nodeExist; + } + + /** + * Returns a child node with the given name. + * If the child node does not exists, it will be created. + * + * @param name The name of the requested node. + * @return A new reference to the node, creating the node if it is necessary. + */ + protected AbstractPreferences childSpi(String name) + { + // we don't check anything here, if the node is a new node this will be + // detected in the constructor, so we simply return a new reference to + // the requested node. + + GConfBasedPreferences preferenceNode + = new GConfBasedPreferences(this, name, this.isUser); + + // register the node for to GConf so that it can listen + // events outside the scope of the application + backend.startWatchingNode(this.node); + + return preferenceNode; + } + + /** + * Returns an array of names of the children of this preference node. + * If the current node does not have children, the returned array will be + * of <code>size</code> 0 (that is, not <code>null</code>). + * + * @return A <code>String</code> array of names of children of the current + * node. + * @throws BackingStoreException if this operation cannot be completed. + */ + protected String[] childrenNamesSpi() throws BackingStoreException + { + List<String> nodeList = backend.getChildrenNodes(this.node); + String[] nodes = new String[nodeList.size()]; + nodeList.toArray(nodes); + + return nodes; + } + + /** + * Suggest a flush to the backend. Actually, this is only a suggestion as + * GConf handles this for us asynchronously. More over, both sync and flush + * have the same meaning in this class, so calling sync has exactly the same + * effect. + * + * @see #sync + * @throws BackingStoreException if this operation cannot be completed. + */ + public void flush() throws BackingStoreException + { + backend.suggestSync(); + } + + /** + * Request a flush. + * + * @see #flush + * @throws BackingStoreException if this operation cannot be completed. + */ + protected void flushSpi() throws BackingStoreException + { + this.flush(); + } + + /** + * Returns all of the key in this preference node. + * If the current node does not have preferences, the returned array will be + * of size zero. + * + * @return A <code>String</code> array of keys stored under the current + * node. + * @throws BackingStoreException if this operation cannot be completed. + */ + protected String[] keysSpi() throws BackingStoreException + { + List<String> keyList = backend.getKeys(this.node); + String[] keys = new String[keyList.size()]; + keyList.toArray(keys); + + return keys; + } + + /** + * Does a recursive postorder traversal of the preference tree, starting from + * the given directory invalidating every preference found in the node. + * + * @param directory The name of the starting directory (node) + */ + private void postorderRemove(String directory) + { + try + { + // gets the listing of directories in this node + List<String> dirs = backend.getChildrenNodes(directory); + + if (dirs.size() != 0) + { + for (String currentDir : dirs) + { + // recursive search inside this directory + postorderRemove(currentDir); + } + } + + // remove all the keys associated to this directory + List<String> entries = backend.getKeys(directory); + + if (entries.size() != 0) + { + for (String key : entries) + { + this.removeSpi(key); + } + } + } + catch (BackingStoreException ex) + { + /* ignore */ + } + } + + /** + * Stores the given key-value pair into this preference node. + * + * @param key The key of this preference. + * @param value The value of this preference. + */ + protected void putSpi(String key, String value) + { + backend.setString(this.getGConfKey(key), value); + } + + /** + * Removes this preference node, including all its children. + * Also removes the preferences associated. + */ + protected void removeNodeSpi() throws BackingStoreException + { + this.postorderRemove(this.node); + this.flush(); + } + + /** + * Removes the given key from this preference node. + * If the key does not exist, no operation is performed. + * + * @param key The key to remove. + */ + protected void removeSpi(String key) + { + backend.unset(this.getGConfKey(key)); + } + + /** + * Suggest a sync to the backend. Actually, this is only a suggestion as GConf + * handles this for us asynchronously. More over, both sync and flush have the + * same meaning in this class, so calling flush has exactly the same effect. + * + * @see #flush + * @throws BackingStoreException if this operation cannot be completed due to + * a failure in the backing store, or inability to communicate with + * it. + */ + public void sync() throws BackingStoreException + { + this.flush(); + } + + /** + * Request a sync. + * + * @see #sync + * @throws BackingStoreException if this operation cannot be completed due to + * a failure in the backing store, or inability to communicate with + * it. + */ + protected void syncSpi() throws BackingStoreException + { + this.sync(); + } + + /** + * Returns the value of the given key. + * If the keys does not have a value, or there is an error in the backing + * store, <code>null</code> is returned instead. + * + * @param key The key to retrieve. + * @return The value associated with the given key. + */ + protected String getSpi(String key) + { + return backend.getKey(this.getGConfKey(key)); + } + + /** + * Returns <code>true</code> if this preference node is a user node, + * <code>false</code> if is a system preference node. + * + * @return <code>true</code> if this preference node is a user node, + * <code>false</code> if is a system preference node. + */ + public boolean isUserNode() + { + return this.isUser; + } + + /* + * PRIVATE METHODS + */ + + /** + * Builds a GConf key string suitable for operations on the backend. + * + * @param key The key to convert into a valid GConf key. + * @return A valid Gconf key. + */ + private String getGConfKey(String key) + { + String nodeName = ""; + + // strip key + // please, note that all names are unescaped into the native peer + key = GConfNativePeer.escapeString(key); + + if (this.node.endsWith("/")) + { + nodeName = this.node + key; + } + else + { + nodeName = this.node + "/" + key; + } + + return nodeName; + } + + /** + * Builds the root node to use for this preference. + * + * @param isUser Defines if this node is a user (<code>true</code>) or system + * (<code>false</code>) node. + * @return The real root of this preference tree. + */ + private String getRealRoot(boolean isUser) + { + // not sure about this, we should have already these permissions... + SecurityManager security = System.getSecurityManager(); + + if (security != null) + { + security.checkPermission(PERMISSION); + } + + String root = null; + + if (isUser) + { + root = System.getProperty("gnu.java.util.prefs.gconf.user_root", + DEFAULT_USER_ROOT); + } + else + { + root = System.getProperty("gnu.java.util.prefs.gconf.system_root", + DEFAULT_SYSTEM_ROOT); + } + + return root; + } +} diff -r 2d58a540c22c gconf-prefs-peer/gnu/java/util/prefs/gconf/GConfNativePeer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gconf-prefs-peer/gnu/java/util/prefs/gconf/GConfNativePeer.java Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,335 @@ +/* GConfNativePeer.java -- GConf based preference peer for native methods + 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.java.util.prefs.gconf; + +import java.util.List; +import java.util.prefs.BackingStoreException; + +/** + * Native peer for GConf based preference backend. + * + * @author Mario Torre <neugens@xxxxxxxxxxxxxxxx> + */ +public final class GConfNativePeer +{ + /** + * Object to achieve locks for methods that need to be synchronized. + */ + private static final Object[] semaphore = new Object[0]; + + /** + * Creates a new instance of GConfNativePeer + */ + public GConfNativePeer() + { + synchronized (semaphore) + { + init_class(); + } + } + + /** + * Queries whether the node <code>node</code> exists in theGConf database. + * Returns <code>true</code> or <code>false</code>. + * + * @param node the node to check. + */ + public boolean nodeExist(String node) + { + return gconf_client_dir_exists(node); + } + + /** + * Add the node <code>node</code> to the list of nodes the GConf will watch. + * An event is raised everytime this node is changed. You can add a node + * multiple times. + * + * @param node the node to track. + */ + public void startWatchingNode(String node) + { + gconf_client_add_dir(node); + } + + /** + * Remove the node <code>node</code> to the list of nodes the GConf is + * watching. Note that if a node has been added multiple times, you must + * remove it the same number of times before the remove takes effect. + * + * @param node the node you don't want to track anymore. + */ + public void stopWatchingNode(String node) + { + gconf_client_remove_dir(node); + } + + /** + * Change the value of key to val. Automatically creates the key if it didn't + * exist before (ie it was unset or it only had a default value). + * Key names must be valid GConf key names, that is, there can be more + * restrictions than for normal Preference Backend. + * + * @param key the key to alter (or add). + * @param value the new value for this key. + * @return true if the key was updated, false otherwise. + */ + public boolean setString(String key, String value) + { + return gconf_client_set_string(key, value); + } + + /** + * Unsets the value of key; if key is already unset, has no effect. Depending + * on the GConf daemon, unsetting a key may have the side effect to remove it + * completely form the database. + * + * @param key the key to unset. + * @return true on success, false if the key was not updated. + */ + public boolean unset(String key) + { + return gconf_client_unset(key); + } + + /** + * Gets the value of a configuration key. + * + * @param key the configuration key. + * @return the values of this key, null if the key is not valid. + */ + public String getKey(String key) + { + return gconf_client_get_string(key); + } + + /** + * Lists the key in the given node. Does not list subnodes. Keys names are the + * stripped names (name relative to the current node) of the keys stored in + * this node. + * + * @param node the node where keys are stored. + * @return a java.util.List of keys. If there are no keys in the given node, a + * list of size 0 is returned. + */ + public List<String> getKeys(String node) throws BackingStoreException + { + return gconf_client_all_keys(node); + } + + /** + * Lists the subnodes in <code>node</code>. The returned list contains + * allocated strings. Each string is the name relative tho the given node. + * + * @param node the node to get subnodes from. If there are no subnodes in the + * given node, a list of size 0 is returned. + */ + public List<String> getChildrenNodes(String node) throws BackingStoreException + { + return gconf_client_all_nodes(node); + } + + /** + * Escape the given string so the it is a valid GConf name. + */ + public static String escapeString(String plain) + { + return gconf_escape_key(plain); + } + + /** + * Unescape a string escaped with {@link #escapeString}. + */ + public static String unescapeString(String escaped) + { + return gconf_unescape_key(escaped); + } + + /** + * Suggest to the backend GConf daemon to synch with the database. + */ + public void suggestSync() throws BackingStoreException + { + gconf_client_suggest_sync(); + } + + protected void finalize() throws Throwable + { + try + { + synchronized (semaphore) + { + finalize_class(); + } + } + finally + { + super.finalize(); + } + } + + /* ***** native methods ***** */ + + /* + * Basicly, these are one to one mappings to GConfClient functions. + * GConfClient instances are handled by the native layer, and are hidden from + * the main java class. + */ + + /** + * Initialize the GConf native peer and enable the object cache. + * It is meant to be used by the static initializer. + */ + native static final private void init_id_cache(); + + /** + * Initialize the GConf native peer. This is meant to be used by the + * class constructor. + */ + native static final private void init_class(); + + /** + * Class finalizer. + */ + native static final private void finalize_class(); + + /** + * Queries the GConf database to see if the given node exists, returning + * true if the node exist, false otherwise. + * + * @param node the node to query for existence. + * @return true if the node exist, false otherwise. + */ + native static final protected boolean gconf_client_dir_exists(String node); + + /** + * Adds the given node to the list of nodes that GConf watches for + * changes. + * + * @param node the node to watch for changes. + */ + native static final protected void gconf_client_add_dir(String node); + + /** + * Removes the given node from the list of nodes that GConf watches for + * changes. + * + * @param node the node to remove from from the list of watched nodes. + */ + native static final protected void gconf_client_remove_dir(String node); + + /** + * Sets the given key/value pair into the GConf database. + * The key must be a valid GConf key. + * + * @param key the key to store in the GConf database + * @param value the value to associate to the given key. + * @return true if the change has effect, false otherwise. + */ + native static final protected boolean gconf_client_set_string(String key, + String value); + + /** + * Returns the key associated to the given key. Null is returned if the + * key is not valid. + * + * @param key the key to return the value of. + * @return The value associated to the given key, or null. + */ + native static final protected String gconf_client_get_string(String key); + + /** + * Usets the given key, removing the key from the database. + * + * @param key the key to remove. + * @return true if the operation success, false otherwise. + */ + native static final protected boolean gconf_client_unset(String key); + + /** + * Suggest to the GConf native peer a sync with the database. + * + */ + native static final protected void gconf_client_suggest_sync() + throws BackingStoreException; + + /** + * Returns a list of all nodes under the given node. + * + * @param node the source node. + * @return A list of nodes under the given source node. + */ + native + static final protected List<String> gconf_client_all_nodes(String node) + throws BackingStoreException; + + /** + * Returns a list of all keys stored in the given node. + * + * @param node the source node. + * @return A list of all keys stored in the given node. + */ + native + static final protected List<String> gconf_client_all_keys(String node) + throws BackingStoreException; + + /** + * Escape the input String so that it's a valid element for GConf. + * + * @param plain the String to escape. + * @return An escaped String for use with GConf. + */ + native + static final protected String gconf_escape_key(String plain); + + /** + * Converts a string escaped with gconf_escape_key back into its + * original form. + * + * @param escaped key as returned by gconf_escape_key + * @return An unescaped key. + */ + native + static final protected String gconf_unescape_key(String escaped); + + static + { + System.loadLibrary("gconfpeer"); + init_id_cache(); + } +} diff -r 2d58a540c22c gconf-prefs-peer/native/GConfNativePeer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gconf-prefs-peer/native/GConfNativePeer.c Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,763 @@ +/* GConfNativePeer.c -- Implements native methods for class GConfNativePeer + Copyright (C) 2003, 2004 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. */ + +#include <stdio.h> +#include <string.h> + +#include <jni.h> + +#include <glib.h> +#include <gdk/gdk.h> +#include <gconf/gconf-client.h> + +#include "gnu_java_util_prefs_gconf_GConfNativePeer.h" + +/* + * Cached id, methods and objects + */ + +/** Reference count */ +static int reference_count = 0; + +/** GConfClient backend */ +static GConfClient *client = NULL; + +/** java.util.ArrayList class */ +static jclass jlist_class = NULL; + +/** java.util.ArrayList constructor id */ +static jmethodID jlist_init_id = NULL; + +/** ava.util.ArrayList add id */ +static jmethodID jlist_add_id = NULL; + +/* ***** PRIVATE FUNCTIONS DELCARATION ***** */ + +/*** Taken from jcl.h. See GNU CLasspath native sources *** */ +static void JCL_ThrowException (JNIEnv * env, const char *className, const char *errMsg); +static jclass JCL_FindClass (JNIEnv * env, const char *className); +static void JCL_free_cstring (JNIEnv * env, jstring s, const char *cstr); +static const char *JCL_jstring_to_cstring (JNIEnv * env, jstring s); + +/** + * Gets the reference of the default GConfClient and initialize the + * the type system. + * The client reference should be released with g_object_unref after use. + * This functions must be called with gdk lock held. + */ +static void init_gconf_client (void); + +/** + * Throws a new runtime exception after a failure, with the given message. + */ +static void throw_exception (JNIEnv * env, const char *msg); + +/** + * Throws the given exception after a failure, with the given message. + */ +static void +throw_exception_by_name (JNIEnv * env, const char *name, const char *msg); + +/** + * Return a reference to a java.util.ArrayList class. + */ +static gboolean set_jlist_class (JNIEnv * env); + +/** + * Builds a new reference to a new java.util.ArrayList instace. + * The instance should be freed by the caller after use. + */ +static jclass get_jlist_reference (JNIEnv * env, jclass jlist_class); + +/* ***** END: PRIVATE FUNCTIONS DELCARATION ***** */ + +/* ***** NATIVE FUNCTIONS ***** */ + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: init_class + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1class + (JNIEnv *env, jclass clazz) +{ + if (reference_count == 0) + { + Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache + (env, clazz); + return; + } + + reference_count++; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: init_id_chache + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache + (JNIEnv *env, jclass clazz __attribute__ ((unused))) +{ + reference_count++; + + gdk_threads_enter (); + init_gconf_client (); + gdk_threads_leave (); + + /* if client is null, there is probably an out of memory */ + if (client == NULL) + { + /* release the string and throw a runtime exception */ + throw_exception (env, + "Unable to initialize GConfClient in native code\n"); + return; + } + + /* ***** java.util.ArrayList ***** */ + if (set_jlist_class (env) == FALSE) + { + throw_exception (env, + "Unable to get valid reference to java.util.List in native code\n"); + return; + } +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_all_keys + * Signature: (Ljava/lang/String;)Ljava/util/List; + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1all_1keys + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node) +{ + /* TODO: check all the calls to gdk_threads_enter/leave */ + + const char *dir = NULL; + const char *_val = NULL; + const char *_val_unescaped = NULL; + + GError *err = NULL; + GSList *entries = NULL; + GSList *tmp; + + /* java.util.ArrayList */ + jobject jlist = NULL; + + dir = JCL_jstring_to_cstring (env, node); + if (dir == NULL) + { + return NULL; + } + + gdk_threads_enter (); + entries = gconf_client_all_entries (client, dir, &err); + gdk_threads_leave (); + if (err != NULL) + { + throw_exception_by_name (env, "java/util/prefs/BackingStoreException", + err->message); + g_error_free (err); + err = NULL; + + JCL_free_cstring (env, node, dir); + return NULL; + } + + jlist = get_jlist_reference (env, jlist_class); + if (jlist == NULL) + { + throw_exception_by_name (env, "java/util/prefs/BackingStoreException", + "Unable to get java.util.List reference in native code\n"); + JCL_free_cstring (env, node, dir); + g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL); + g_slist_free (entries); + return NULL; + } + + tmp = entries; + while (tmp != NULL) + { + _val = gconf_entry_get_key (tmp->data); + _val = strrchr (_val, '/'); + ++_val; + + _val_unescaped = gconf_unescape_key (_val, strlen (_val)); + + (*env)->CallBooleanMethod (env, jlist, jlist_add_id, + (*env)->NewStringUTF (env, _val_unescaped)); + + tmp = g_slist_next (tmp); + + g_free ((gpointer) _val_unescaped); + } + + /* clean up things */ + JCL_free_cstring (env, node, dir); + g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL); + g_slist_free (entries); + + return jlist; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_all_nodes + * Signature: (Ljava/lang/String;)Ljava/util/List; + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1all_1nodes + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node) +{ + const char *dir = NULL; + const char *_val = NULL; + const char *_val_unescaped = NULL; + + GError *err = NULL; + GSList *entries = NULL; + GSList *tmp; + + /* java.util.ArrayList */ + jobject jlist = NULL; + + dir = JCL_jstring_to_cstring (env, node); + if (dir == NULL) + { + return NULL; + } + + gdk_threads_enter (); + entries = gconf_client_all_dirs (client, dir, &err); + gdk_threads_leave (); + if (err != NULL) + { + throw_exception_by_name (env, "java/util/prefs/BackingStoreException", + err->message); + g_error_free (err); + err = NULL; + JCL_free_cstring (env, node, dir); + return NULL; + } + + jlist = get_jlist_reference (env, jlist_class); + if (jlist == NULL) + { + throw_exception_by_name (env, "java/util/prefs/BackingStoreException", + "Unable to get java.util.List reference in native code\n"); + JCL_free_cstring (env, node, dir); + g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL); + g_slist_free (entries); + return NULL; + } + + tmp = entries; + while (tmp != NULL) + { + _val = tmp->data; + + _val = strrchr (_val, '/'); + ++_val; + + _val_unescaped = gconf_unescape_key (_val, strlen (_val)); + + (*env)->CallBooleanMethod (env, jlist, jlist_add_id, + (*env)->NewStringUTF (env, _val_unescaped)); + + tmp = g_slist_next (tmp); + + g_free ((gpointer) _val_unescaped); + } + + /* clean up things */ + JCL_free_cstring (env, node, dir); + g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL); + g_slist_free (entries); + + return jlist; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_suggest_sync + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1suggest_1sync + (JNIEnv *env, jclass clazz __attribute__ ((unused))) +{ + GError *err = NULL; + + gdk_threads_enter (); + gconf_client_suggest_sync (client, &err); + gdk_threads_leave (); + if (err != NULL) + { + throw_exception_by_name (env, "java/util/prefs/BackingStoreException", + err->message); + g_error_free (err); + err = NULL; + } +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_unset + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring key) +{ + const char *_key = NULL; + gboolean result = JNI_FALSE; + GError *err = NULL; + + _key = JCL_jstring_to_cstring (env, key); + if (_key == NULL) + { + return JNI_FALSE; + } + + gdk_threads_enter (); + result = gconf_client_unset (client, _key, &err); + gdk_threads_leave (); + if (err != NULL) + { + result = JNI_FALSE; + g_error_free (err); + err = NULL; + } + + JCL_free_cstring (env, key, _key); + + return result; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_get_string + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring key) +{ + const char *_key = NULL; + const char *_value = NULL; + GError *err = NULL; + jstring result = NULL; + + _key = JCL_jstring_to_cstring (env, key); + if (_key == NULL) + { + return NULL; + } + + gdk_threads_enter (); + _value = gconf_client_get_string (client, _key, &err); + gdk_threads_leave (); + JCL_free_cstring (env, key, _key); + if (err != NULL) + { + /* just in case */ + if (_value != NULL) g_free ((gpointer) _value); + g_error_free (err); + err = NULL; + + return NULL; + } + + /* Even if Gconf reported no error it is possible that NULL was returned */ + /* and it should be prevented to create a Java string from that value. */ + if (_value != NULL) + { + result = (*env)->NewStringUTF (env, _value); + g_free ((gpointer) _value); + } + + return result; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_set_string + * Signature: (Ljava/lang/String;Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string + (JNIEnv *env, jclass clazz __attribute__ ((unused)), + jstring key, jstring value) +{ + const char *_key = NULL; + const char *_value = NULL; + GError *err = NULL; + + gboolean result = JNI_FALSE; + + /* load an UTF string from the virtual machine. */ + _key = JCL_jstring_to_cstring (env, key); + _value = JCL_jstring_to_cstring (env, value); + if (_key == NULL || _value == NULL) + { + return JNI_FALSE; + } + + gdk_threads_enter (); + result = gconf_client_set_string (client, _key, _value, &err); + gdk_threads_leave (); + if (err != NULL) + { + g_error_free (err); + err = NULL; + result = JNI_FALSE; + } + + JCL_free_cstring (env, key, _key); + JCL_free_cstring (env, value, _value); + + return (jboolean) result; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_remove_dir + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1remove_1dir + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node) +{ + const char *dir = NULL; + + dir = JCL_jstring_to_cstring (env, node); + if (dir == NULL) + return; + + gdk_threads_enter (); + gconf_client_remove_dir (client, dir, NULL); + gdk_threads_leave (); + + JCL_free_cstring (env, node, dir); +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_add_dir + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1add_1dir + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node) +{ + const char *dir = NULL; + + dir = JCL_jstring_to_cstring (env, node); + if (dir == NULL) + return; + + /* ignore errors */ + gdk_threads_enter (); + gconf_client_add_dir (client, dir, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + gdk_threads_leave (); + + JCL_free_cstring (env, node, dir); +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: gconf_client_dir_exists + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node) +{ + const char *dir = NULL; + GError *err = NULL; + jboolean value = JNI_FALSE; + + dir = JCL_jstring_to_cstring (env, node); + if (dir == NULL) + return value; + + /* on error return false */ + gdk_threads_enter (); + value = gconf_client_dir_exists (client, dir, &err); + gdk_threads_leave (); + if (err != NULL) + value = JNI_FALSE; + + JCL_free_cstring (env, node, dir); + + return value; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: finalize_class + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_finalize_1class + (JNIEnv *env, jclass clazz __attribute__ ((unused))) +{ + if (reference_count == 0) + { + /* last reference, free all resources and return */ + gdk_threads_enter (); + g_object_unref (G_OBJECT (client)); + gdk_threads_leave (); + + (*env)->DeleteGlobalRef (env, jlist_class); + + jlist_class = NULL; + jlist_init_id = NULL; + jlist_add_id = NULL; + + return; + } + + reference_count--; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1escape_1key + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jstring JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1escape_1key + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring plain) +{ + const char *escaped = NULL; + const char *_plain = NULL; + jstring result = NULL; + + _plain = JCL_jstring_to_cstring (env, plain); + if (_plain == NULL) + { + return NULL; + } + + gdk_threads_enter (); + escaped = gconf_escape_key (_plain, strlen (_plain)); + gdk_threads_leave (); + + JCL_free_cstring (env, plain, _plain); + /* check for NULL, if so prevent string creation */ + if (escaped != NULL) + { + result = (*env)->NewStringUTF (env, escaped); + g_free ((gpointer) escaped); + } + + return result; +} + +/* + * Class: gnu_java_util_prefs_gconf_GConfNativePeer + * Method: Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1unescape_1key + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jstring JNICALL +Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1unescape_1key + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring escaped) +{ + const char *plain = NULL; + const char *_escaped = NULL; + jstring result = NULL; + + _escaped = JCL_jstring_to_cstring (env, escaped); + if (_escaped == NULL) + { + return NULL; + } + + gdk_threads_enter (); + plain = gconf_unescape_key (_escaped, strlen (_escaped)); + gdk_threads_leave (); + + JCL_free_cstring (env, escaped, _escaped); + /* check for NULL, if so prevent string creation */ + if (plain != NULL) + { + result = (*env)->NewStringUTF (env, plain); + g_free ((gpointer) plain); + } + + return result; +} + +/* ***** END: NATIVE FUNCTIONS ***** */ + +/* ***** PRIVATE FUNCTIONS IMPLEMENTATION ***** */ + +static void throw_exception (JNIEnv *env, const char *msg) +{ + throw_exception_by_name (env, "java/lang/RuntimeException", msg); +} + +static void +throw_exception_by_name (JNIEnv *env, const char *name, const char *msg) +{ + JCL_ThrowException (env, name, msg); +} + +static void init_gconf_client (void) +{ + g_type_init (); + client = gconf_client_get_default (); +} + +static gboolean set_jlist_class (JNIEnv *env) +{ + jclass local_jlist_class = NULL; + + /* gets a reference to the ArrayList class */ + local_jlist_class = JCL_FindClass (env, "java/util/ArrayList"); + if (local_jlist_class == NULL) + { + return FALSE; + } + + jlist_class = (*env)->NewGlobalRef (env, local_jlist_class); + (*env)->DeleteLocalRef (env, local_jlist_class); + if (jlist_class == NULL) + { + return FALSE; + } + + /* and initialize it */ + jlist_init_id = (*env)->GetMethodID (env, jlist_class, "<init>", "()V"); + if (jlist_init_id == NULL) + { + return FALSE; + } + + jlist_add_id = (*env)->GetMethodID (env, jlist_class, "add", + "(Ljava/lang/Object;)Z"); + if (jlist_add_id == NULL) + { + return FALSE; + } + + return TRUE; +} + +static jobject get_jlist_reference (JNIEnv *env, jclass jlist_class) +{ + return (*env)->NewObject (env, jlist_class, jlist_init_id); +} + +static jclass JCL_FindClass (JNIEnv * env, const char *className) +{ + jclass retval = (*env)->FindClass (env, className); + if (retval == NULL) + { + JCL_ThrowException (env, "java/lang/ClassNotFoundException", className); + } + return retval; +} + +static const char *JCL_jstring_to_cstring (JNIEnv * env, + jstring s) +{ + const char *cstr; + if (s == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "Null string"); + return NULL; + } + cstr = (const char *) (*env)->GetStringUTFChars (env, s, NULL); + if (cstr == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "GetStringUTFChars() failed."); + return NULL; + } + return cstr; +} + +static void JCL_free_cstring (JNIEnv * env, jstring s, + const char *cstr) +{ + (*env)->ReleaseStringUTFChars (env, s, cstr); +} + +static void JCL_ThrowException (JNIEnv * env, + const char *className, + const char *errMsg) +{ + jclass excClass; + if ((*env)->ExceptionOccurred (env)) + { + (*env)->ExceptionClear (env); + } + excClass = (*env)->FindClass (env, className); + if (excClass == NULL) + { + jclass errExcClass; + errExcClass = + (*env)->FindClass (env, "java/lang/ClassNotFoundException"); + if (errExcClass == NULL) + { + errExcClass = (*env)->FindClass (env, "java/lang/InternalError"); + if (errExcClass == NULL) + { + fprintf (stderr, "JCL: Utterly failed to throw exeption "); + fprintf (stderr, "%s", className); + fprintf (stderr, " with message "); + fprintf (stderr, "%s", errMsg); + return; + } + } + /* Removed this (more comprehensive) error string to avoid the need for + * a static variable or allocation of a buffer for this message in this + * (unlikely) error case. --Fridi. + * + * sprintf(errstr,"JCL: Failed to throw exception %s with message %s: could not find exception class.", className, errMsg); + */ + (*env)->ThrowNew (env, errExcClass, className); + } + (*env)->ThrowNew (env, excClass, errMsg); +} + +/* ***** END: PRIVATE FUNCTIONS IMPLEMENTATION ***** */ diff -r 2d58a540c22c gconf-prefs-peer/native/gnu_java_util_prefs_gconf_GConfNativePeer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gconf-prefs-peer/native/gnu_java_util_prefs_gconf_GConfNativePeer.h Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,32 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __gnu_java_util_prefs_gconf_GConfNativePeer__ +#define __gnu_java_util_prefs_gconf_GConfNativePeer__ + +#include <jni.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT void JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache (JNIEnv *env, jclass); +JNIEXPORT void JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1class (JNIEnv *env, jclass); +JNIEXPORT void JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_finalize_1class (JNIEnv *env, jclass); +JNIEXPORT jboolean JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists (JNIEnv *env, jclass, jstring); +JNIEXPORT void JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1add_1dir (JNIEnv *env, jclass, jstring); +JNIEXPORT void JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1remove_1dir (JNIEnv *env, jclass, jstring); +JNIEXPORT jboolean JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string (JNIEnv *env, jclass, jstring, jstring); +JNIEXPORT jstring JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string (JNIEnv *env, jclass, jstring); +JNIEXPORT jboolean JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset (JNIEnv *env, jclass, jstring); +JNIEXPORT void JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1suggest_1sync (JNIEnv *env, jclass); +JNIEXPORT jobject JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1all_1nodes (JNIEnv *env, jclass, jstring); +JNIEXPORT jobject JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1all_1keys (JNIEnv *env, jclass, jstring); +JNIEXPORT jstring JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1escape_1key (JNIEnv *env, jclass, jstring); +JNIEXPORT jstring JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1unescape_1key (JNIEnv *env, jclass, jstring); + +#ifdef __cplusplus +} +#endif + +#endif /* __gnu_java_util_prefs_gconf_GConfNativePeer__ */ diff -r 2d58a540c22c patches/icedtea-enable-gconf.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/icedtea-enable-gconf.patch Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,11 @@ +--- icedtea-clean/openjdk/j2se/src/share/classes/java/util/prefs/Preferences.java 2007-10-12 10:02:28.000000000 +0200 ++++ icedtea/openjdk/j2se/src/share/classes/java/util/prefs/Preferences.java 2007-10-30 21:17:39.000000000 +0100 +@@ -294,7 +294,7 @@ + String platformFactory = + System.getProperty("os.name").startsWith("Windows") + ? "java.util.prefs.WindowsPreferencesFactory" +- : "java.util.prefs.FileSystemPreferencesFactory"; ++ : "gnu.java.util.prefs.GConfPreferencesFactory"; + try { + return (PreferencesFactory) + Class.forName(platformFactory, false, null).newInstance(); diff -r 2d58a540c22c rt/gnu/java/util/prefs/GConfBasedFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/gnu/java/util/prefs/GConfBasedFactory.java Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,78 @@ +/* GConfBasedFactory.java -- GConf based PreferencesFactory implementation + 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.java.util.prefs; + +import java.util.prefs.Preferences; +import java.util.prefs.PreferencesFactory; + +/** + * Factory object that generates a Preferences nodes that are read from a GConf + * daemon. + * + * @author Mario Torre <neugens@xxxxxxxxxxxxxxxx> + */ +public class GConfBasedFactory implements PreferencesFactory +{ + /** System preference root. */ + private static final Preferences systemPreferences + = new GConfBasedPreferences(null, "", false); + + /** User preference root. */ + private static final Preferences userPreferences + = new GConfBasedPreferences(null, "", true); + + /** + * Returns the system root preference node. + * + * @see java.util.prefs.PreferencesFactory#systemRoot() + */ + public Preferences systemRoot() + { + return systemPreferences; + } + + /** + * Returns the user root preference node corresponding to the calling user. + * + * @see java.util.prefs.PreferencesFactory#userRoot() + */ + public Preferences userRoot() + { + return userPreferences; + } +} diff -r 2d58a540c22c rt/gnu/java/util/prefs/GConfBasedPreferences.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/gnu/java/util/prefs/GConfBasedPreferences.java Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,423 @@ +/* GConfBasedPreferences.java -- GConf based Preferences implementation + 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.java.util.prefs; + +import gnu.java.util.prefs.gconf.GConfNativePeer; + +import java.security.Permission; + +import java.util.List; +import java.util.prefs.AbstractPreferences; +import java.util.prefs.BackingStoreException; + +/** + * This is a GConf based preference implementation which writes the preferences + * as GConf key-value pairs. System Root is defined to be the + * <code>"/system"</code> directory of GConf for the current user, while User + * Root is <code>"/apps/java"</code>. These defaults can be modified by + * defining two system properties:<br /> + * <br /> + * User Root:<br /> + * <br /> + * + * <pre> + * gnu.java.util.prefs.gconf.user_root + * </pre> + * + * <br /> + * <br /> + * and System Root:<br /> + * <br /> + * + * <pre> + * gnu.java.util.prefs.gconf.system_root + * </pre> + * + * <br /> + * + * @author Mario Torre <neugens@xxxxxxxxxxxxxxxx> + */ +public class GConfBasedPreferences + extends AbstractPreferences +{ + /** Get access to Runtime permission */ + private static final Permission PERMISSION + = new RuntimePermission("preferences"); + + /** CGonf client backend */ + private static GConfNativePeer backend = new GConfNativePeer(); + + /** Default user root path */ + private static final String DEFAULT_USER_ROOT = "/apps/classpath"; + + /** Default system root path */ + private static final String DEFAULT_SYSTEM_ROOT = "/system"; + + /** current node full path */ + private String node = ""; + + /** True if this is a preference node in the user tree, false otherwise. */ + private final boolean isUser; + + /** + * Creates a preference root user node. + */ + public GConfBasedPreferences() + { + this(true); + } + + /** + * Creates a preference root node. When <code>isUser</code> is true it will + * be user node otherwise it will be a system node. + */ + public GConfBasedPreferences(boolean isUser) + { + this(null, "", isUser); + } + + /** + * Creates a new preference node given a parent node and a name, which has to + * be relative to its parent. When <code>isUser</code> is true it will be user + * node otherwise it will be a system node. + * + * @param parent The parent node of this newly created node. + * @param name A name relative to the parent node. + * @param isUser Set to <code>true</code> initializes this node to be + * a user node, <code>false</code> initialize it to be a system node. + */ + public GConfBasedPreferences(AbstractPreferences parent, String name, + boolean isUser) + { + super(parent, name); + this.isUser = isUser; + + // stores the fully qualified name of this node + String absolutePath = this.absolutePath(); + if (absolutePath != null && absolutePath.endsWith("/")) + { + absolutePath = absolutePath.substring(0, absolutePath.length() - 1); + } + + // strip invalid characters + // please, note that all names are unescaped into the native peer + int index = absolutePath.lastIndexOf('/'); + if (index > -1) + { + absolutePath = absolutePath.substring(0, index + 1); + absolutePath = absolutePath + GConfNativePeer.escapeString(name); + } + + this.node = this.getRealRoot(isUser) + absolutePath; + + boolean nodeExist = backend.nodeExist(this.node); + + this.newNode = !nodeExist; + } + + /** + * Returns a child node with the given name. + * If the child node does not exists, it will be created. + * + * @param name The name of the requested node. + * @return A new reference to the node, creating the node if it is necessary. + */ + protected AbstractPreferences childSpi(String name) + { + // we don't check anything here, if the node is a new node this will be + // detected in the constructor, so we simply return a new reference to + // the requested node. + + GConfBasedPreferences preferenceNode + = new GConfBasedPreferences(this, name, this.isUser); + + // register the node for to GConf so that it can listen + // events outside the scope of the application + backend.startWatchingNode(this.node); + + return preferenceNode; + } + + /** + * Returns an array of names of the children of this preference node. + * If the current node does not have children, the returned array will be + * of <code>size</code> 0 (that is, not <code>null</code>). + * + * @return A <code>String</code> array of names of children of the current + * node. + * @throws BackingStoreException if this operation cannot be completed. + */ + protected String[] childrenNamesSpi() throws BackingStoreException + { + List<String> nodeList = backend.getChildrenNodes(this.node); + String[] nodes = new String[nodeList.size()]; + nodeList.toArray(nodes); + + return nodes; + } + + /** + * Suggest a flush to the backend. Actually, this is only a suggestion as + * GConf handles this for us asynchronously. More over, both sync and flush + * have the same meaning in this class, so calling sync has exactly the same + * effect. + * + * @see #sync + * @throws BackingStoreException if this operation cannot be completed. + */ + public void flush() throws BackingStoreException + { + backend.suggestSync(); + } + + /** + * Request a flush. + * + * @see #flush + * @throws BackingStoreException if this operation cannot be completed. + */ + protected void flushSpi() throws BackingStoreException + { + this.flush(); + } + + /** + * Returns all of the key in this preference node. + * If the current node does not have preferences, the returned array will be + * of size zero. + * + * @return A <code>String</code> array of keys stored under the current + * node. + * @throws BackingStoreException if this operation cannot be completed. + */ + protected String[] keysSpi() throws BackingStoreException + { + List<String> keyList = backend.getKeys(this.node); + String[] keys = new String[keyList.size()]; + keyList.toArray(keys); + + return keys; + } + + /** + * Does a recursive postorder traversal of the preference tree, starting from + * the given directory invalidating every preference found in the node. + * + * @param directory The name of the starting directory (node) + */ + private void postorderRemove(String directory) + { + try + { + // gets the listing of directories in this node + List<String> dirs = backend.getChildrenNodes(directory); + + if (dirs.size() != 0) + { + for (String currentDir : dirs) + { + // recursive search inside this directory + postorderRemove(currentDir); + } + } + + // remove all the keys associated to this directory + List<String> entries = backend.getKeys(directory); + + if (entries.size() != 0) + { + for (String key : entries) + { + this.removeSpi(key); + } + } + } + catch (BackingStoreException ex) + { + /* ignore */ + } + } + + /** + * Stores the given key-value pair into this preference node. + * + * @param key The key of this preference. + * @param value The value of this preference. + */ + protected void putSpi(String key, String value) + { + backend.setString(this.getGConfKey(key), value); + } + + /** + * Removes this preference node, including all its children. + * Also removes the preferences associated. + */ + protected void removeNodeSpi() throws BackingStoreException + { + this.postorderRemove(this.node); + this.flush(); + } + + /** + * Removes the given key from this preference node. + * If the key does not exist, no operation is performed. + * + * @param key The key to remove. + */ + protected void removeSpi(String key) + { + backend.unset(this.getGConfKey(key)); + } + + /** + * Suggest a sync to the backend. Actually, this is only a suggestion as GConf + * handles this for us asynchronously. More over, both sync and flush have the + * same meaning in this class, so calling flush has exactly the same effect. + * + * @see #flush + * @throws BackingStoreException if this operation cannot be completed due to + * a failure in the backing store, or inability to communicate with + * it. + */ + public void sync() throws BackingStoreException + { + this.flush(); + } + + /** + * Request a sync. + * + * @see #sync + * @throws BackingStoreException if this operation cannot be completed due to + * a failure in the backing store, or inability to communicate with + * it. + */ + protected void syncSpi() throws BackingStoreException + { + this.sync(); + } + + /** + * Returns the value of the given key. + * If the keys does not have a value, or there is an error in the backing + * store, <code>null</code> is returned instead. + * + * @param key The key to retrieve. + * @return The value associated with the given key. + */ + protected String getSpi(String key) + { + return backend.getKey(this.getGConfKey(key)); + } + + /** + * Returns <code>true</code> if this preference node is a user node, + * <code>false</code> if is a system preference node. + * + * @return <code>true</code> if this preference node is a user node, + * <code>false</code> if is a system preference node. + */ + public boolean isUserNode() + { + return this.isUser; + } + + /* + * PRIVATE METHODS + */ + + /** + * Builds a GConf key string suitable for operations on the backend. + * + * @param key The key to convert into a valid GConf key. + * @return A valid Gconf key. + */ + private String getGConfKey(String key) + { + String nodeName = ""; + + // strip key + // please, note that all names are unescaped into the native peer + key = GConfNativePeer.escapeString(key); + + if (this.node.endsWith("/")) + { + nodeName = this.node + key; + } + else + { + nodeName = this.node + "/" + key; + } + + return nodeName; + } + + /** + * Builds the root node to use for this preference. + * + * @param isUser Defines if this node is a user (<code>true</code>) or system + * (<code>false</code>) node. + * @return The real root of this preference tree. + */ + private String getRealRoot(boolean isUser) + { + // not sure about this, we should have already these permissions... + SecurityManager security = System.getSecurityManager(); + + if (security != null) + { + security.checkPermission(PERMISSION); + } + + String root = null; + + if (isUser) + { + root = System.getProperty("gnu.java.util.prefs.gconf.user_root", + DEFAULT_USER_ROOT); + } + else + { + root = System.getProperty("gnu.java.util.prefs.gconf.system_root", + DEFAULT_SYSTEM_ROOT); + } + + return root; + } +} diff -r 2d58a540c22c rt/gnu/java/util/prefs/gconf/GConfNativePeer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/gnu/java/util/prefs/gconf/GConfNativePeer.java Wed Oct 31 01:07:05 2007 +0100 @@ -0,0 +1,335 @@ +/* GConfNativePeer.java -- GConf based preference peer for native methods + 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.java.util.prefs.gconf; + +import java.util.List; +import java.util.prefs.BackingStoreException; + +/** + * Native peer for GConf based preference backend. + * + * @author Mario Torre <neugens@xxxxxxxxxxxxxxxx> + */ +public final class GConfNativePeer +{ + /** + * Object to achieve locks for methods that need to be synchronized. + */ + private static final Object[] semaphore = new Object[0]; + + /** + * Creates a new instance of GConfNativePeer + */ + public GConfNativePeer() + { + synchronized (semaphore) + { + init_class(); + } + } + + /** + * Queries whether the node <code>node</code> exists in theGConf database. + * Returns <code>true</code> or <code>false</code>. + * + * @param node the node to check. + */ + public boolean nodeExist(String node) + { + return gconf_client_dir_exists(node); + } + + /** + * Add the node <code>node</code> to the list of nodes the GConf will watch. + * An event is raised everytime this node is changed. You can add a node + * multiple times. + * + * @param node the node to track. + */ + public void startWatchingNode(String node) + { + gconf_client_add_dir(node); + } + + /** + * Remove the node <code>node</code> to the list of nodes the GConf is + * watching. Note that if a node has been added multiple times, you must + * remove it the same number of times before the remove takes effect. + * + * @param node the node you don't want to track anymore. + */ + public void stopWatchingNode(String node) + { + gconf_client_remove_dir(node); + } + + /** + * Change the value of key to val. Automatically creates the key if it didn't + * exist before (ie it was unset or it only had a default value). + * Key names must be valid GConf key names, that is, there can be more + * restrictions than for normal Preference Backend. + * + * @param key the key to alter (or add). + * @param value the new value for this key. + * @return true if the key was updated, false otherwise. + */ + public boolean setString(String key, String value) + { + return gconf_client_set_string(key, value); + } + + /** + * Unsets the value of key; if key is already unset, has no effect. Depending + * on the GConf daemon, unsetting a key may have the side effect to remove it + * completely form the database. + * + * @param key the key to unset. + * @return true on success, false if the key was not updated. + */ + public boolean unset(String key) + { + return gconf_client_unset(key); + } + + /** + * Gets the value of a configuration key. + * + * @param key the configuration key. + * @return the values of this key, null if the key is not valid. + */ + public String getKey(String key) + { + return gconf_client_get_string(key); + } + + /** + * Lists the key in the given node. Does not list subnodes. Keys names are the + * stripped names (name relative to the current node) of the keys stored in + * this node. + * + * @param node the node where keys are stored. + * @return a java.util.List of keys. If there are no keys in the given node, a + * list of size 0 is returned. + */ + public List<String> getKeys(String node) throws BackingStoreException + { + return gconf_client_all_keys(node); + } + + /** + * Lists the subnodes in <code>node</code>. The returned list contains + * allocated strings. Each string is the name relative tho the given node. + * + * @param node the node to get subnodes from. If there are no subnodes in the + * given node, a list of size 0 is returned. + */ + public List<String> getChildrenNodes(String node) throws BackingStoreException + { + return gconf_client_all_nodes(node); + } + + /** + * Escape the given string so the it is a valid GConf name. + */ + public static String escapeString(String plain) + { + return gconf_escape_key(plain); + } + + /** + * Unescape a string escaped with {@link #escapeString}. + */ + public static String unescapeString(String escaped) + { + return gconf_unescape_key(escaped); + } + + /** + * Suggest to the backend GConf daemon to synch with the database. + */ + public void suggestSync() throws BackingStoreException + { + gconf_client_suggest_sync(); + } + + protected void finalize() throws Throwable + { + try + { + synchronized (semaphore) + { + finalize_class(); + } + } + finally + { + super.finalize(); + } + } + + /* ***** native methods ***** */ + + /* + * Basicly, these are one to one mappings to GConfClient functions. + * GConfClient instances are handled by the native layer, and are hidden from + * the main java class. + */ + + /** + * Initialize the GConf native peer and enable the object cache. + * It is meant to be used by the static initializer. + */ + native static final private void init_id_cache(); + + /** + * Initialize the GConf native peer. This is meant to be used by the + * class constructor. + */ + native static final private void init_class(); + + /** + * Class finalizer. + */ + native static final private void finalize_class(); + + /** + * Queries the GConf database to see if the given node exists, returning + * true if the node exist, false otherwise. + * + * @param node the node to query for existence. + * @return true if the node exist, false otherwise. + */ + native static final protected boolean gconf_client_dir_exists(String node); + + /** + * Adds the given node to the list of nodes that GConf watches for + * changes. + * + * @param node the node to watch for changes. + */ + native static final protected void gconf_client_add_dir(String node); + + /** + * Removes the given node from the list of nodes that GConf watches for + * changes. + * + * @param node the node to remove from from the list of watched nodes. + */ + native static final protected void gconf_client_remove_dir(String node); + + /** + * Sets the given key/value pair into the GConf database. + * The key must be a valid GConf key. + * + * @param key the key to store in the GConf database + * @param value the value to associate to the given key. + * @return true if the change has effect, false otherwise. + */ + native static final protected boolean gconf_client_set_string(String key, + String value); + + /** + * Returns the key associated to the given key. Null is returned if the + * key is not valid. + * + * @param key the key to return the value of. + * @return The value associated to the given key, or null. + */ + native static final protected String gconf_client_get_string(String key); + + /** + * Usets the given key, removing the key from the database. + * + * @param key the key to remove. + * @return true if the operation success, false otherwise. + */ + native static final protected boolean gconf_client_unset(String key); + + /** + * Suggest to the GConf native peer a sync with the database. + * + */ + native static final protected void gconf_client_suggest_sync() + throws BackingStoreException; + + /** + * Returns a list of all nodes under the given node. + * + * @param node the source node. + * @return A list of nodes under the given source node. + */ + native + static final protected List<String> gconf_client_all_nodes(String node) + throws BackingStoreException; + + /** + * Returns a list of all keys stored in the given node. + * + * @param node the source node. + * @return A list of all keys stored in the given node. + */ + native + static final protected List<String> gconf_client_all_keys(String node) + throws BackingStoreException; + + /** + * Escape the input String so that it's a valid element for GConf. + * + * @param plain the String to escape. + * @return An escaped String for use with GConf. + */ + native + static final protected String gconf_escape_key(String plain); + + /** + * Converts a string escaped with gconf_escape_key back into its + * original form. + * + * @param escaped key as returned by gconf_escape_key + * @return An unescaped key. + */ + native + static final protected String gconf_unescape_key(String escaped); + + static + { + System.loadLibrary("gconfpeer"); + init_id_cache(); + } +}
Attachment:
signature.asc
Description: Questa =?ISO-8859-1?Q?=E8?= una parte del messaggio firmata digitalmente